Skip to content

Commit 6f3e245

Browse files
authored
fix: tool call with stream mode (#3085)
1 parent 53b9419 commit 6f3e245

File tree

1 file changed

+62
-21
lines changed

1 file changed

+62
-21
lines changed

camel/agents/chat_agent.py

Lines changed: 62 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -2697,12 +2697,6 @@ def _process_stream_chunks_with_accumulator(
26972697
# If we have complete tool calls, execute them with
26982698
# sync status updates
26992699
if accumulated_tool_calls:
2700-
# Record assistant message with tool calls first
2701-
self._record_assistant_tool_calls_message(
2702-
accumulated_tool_calls,
2703-
content_accumulator.get_full_content(),
2704-
)
2705-
27062700
# Execute tools synchronously with
27072701
# optimized status updates
27082702
for (
@@ -2942,10 +2936,19 @@ def _execute_tool_from_stream_data(
29422936
tool = self._internal_tools[function_name]
29432937
try:
29442938
result = tool(**args)
2939+
# First, create and record the assistant message with tool
2940+
# call
2941+
assist_msg = FunctionCallingMessage(
2942+
role_name=self.role_name,
2943+
role_type=self.role_type,
2944+
meta_dict=None,
2945+
content="",
2946+
func_name=function_name,
2947+
args=args,
2948+
tool_call_id=tool_call_id,
2949+
)
29452950

2946-
# Only record the tool response message, not the assistant
2947-
# message assistant message with tool_calls was already
2948-
# recorded in _record_assistant_tool_calls_message
2951+
# Then create the tool response message
29492952
func_msg = FunctionCallingMessage(
29502953
role_name=self.role_name,
29512954
role_type=self.role_type,
@@ -2956,7 +2959,25 @@ def _execute_tool_from_stream_data(
29562959
tool_call_id=tool_call_id,
29572960
)
29582961

2959-
self.update_memory(func_msg, OpenAIBackendRole.FUNCTION)
2962+
# Record both messages with precise timestamps to ensure
2963+
# correct ordering
2964+
import time
2965+
2966+
current_time_ns = time.time_ns()
2967+
base_timestamp = (
2968+
current_time_ns / 1_000_000_000
2969+
) # Convert to seconds
2970+
2971+
self.update_memory(
2972+
assist_msg,
2973+
OpenAIBackendRole.ASSISTANT,
2974+
timestamp=base_timestamp,
2975+
)
2976+
self.update_memory(
2977+
func_msg,
2978+
OpenAIBackendRole.FUNCTION,
2979+
timestamp=base_timestamp + 1e-6,
2980+
)
29602981

29612982
return ToolCallingRecord(
29622983
tool_name=function_name,
@@ -3040,10 +3061,19 @@ async def _aexecute_tool_from_stream_data(
30403061
else:
30413062
# Fallback: synchronous call
30423063
result = tool(**args)
3064+
# First, create and record the assistant message with tool
3065+
# call
3066+
assist_msg = FunctionCallingMessage(
3067+
role_name=self.role_name,
3068+
role_type=self.role_type,
3069+
meta_dict=None,
3070+
content="",
3071+
func_name=function_name,
3072+
args=args,
3073+
tool_call_id=tool_call_id,
3074+
)
30433075

3044-
# Only record the tool response message, not the assistant
3045-
# message assistant message with tool_calls was already
3046-
# recorded in _record_assistant_tool_calls_message
3076+
# Then create the tool response message
30473077
func_msg = FunctionCallingMessage(
30483078
role_name=self.role_name,
30493079
role_type=self.role_type,
@@ -3054,7 +3084,25 @@ async def _aexecute_tool_from_stream_data(
30543084
tool_call_id=tool_call_id,
30553085
)
30563086

3057-
self.update_memory(func_msg, OpenAIBackendRole.FUNCTION)
3087+
# Record both messages with precise timestamps to ensure
3088+
# correct ordering
3089+
import time
3090+
3091+
current_time_ns = time.time_ns()
3092+
base_timestamp = (
3093+
current_time_ns / 1_000_000_000
3094+
) # Convert to seconds
3095+
3096+
self.update_memory(
3097+
assist_msg,
3098+
OpenAIBackendRole.ASSISTANT,
3099+
timestamp=base_timestamp,
3100+
)
3101+
self.update_memory(
3102+
func_msg,
3103+
OpenAIBackendRole.FUNCTION,
3104+
timestamp=base_timestamp + 1e-6,
3105+
)
30583106

30593107
return ToolCallingRecord(
30603108
tool_name=function_name,
@@ -3444,13 +3492,6 @@ async def _aprocess_stream_chunks_with_accumulator(
34443492
# If we have complete tool calls, execute them with
34453493
# async status updates
34463494
if accumulated_tool_calls:
3447-
# Record assistant message with
3448-
# tool calls first
3449-
self._record_assistant_tool_calls_message(
3450-
accumulated_tool_calls,
3451-
content_accumulator.get_full_content(),
3452-
)
3453-
34543495
# Execute tools asynchronously with real-time
34553496
# status updates
34563497
async for (

0 commit comments

Comments
 (0)