2323class ControllerResponse :
2424 agent : Agent
2525 message : str
26- turns : int
2726
2827
2928class Controller :
@@ -78,7 +77,6 @@ def __call__(self, agent: Agent, message: str = None) -> ControllerResponse:
7877 return self .run_sync (agent = agent , message = message )
7978
8079 def _add_trace_event (self , event : TraceEvent ) -> None :
81- """ 添加trace事件 """
8280 self .trace ['events' ].append (event )
8381 if self .trace_callback :
8482 self .trace_callback (event )
@@ -93,131 +91,125 @@ async def run(self, agent: Agent, message: str = None) -> ControllerResponse:
9391 Returns:
9492 (Agent, str): 最终激活的 Agent 和输出
9593 """
96- turn = 1
97- self .set_agent_instruction (agent )
9894 if message :
9995 self ._add_trace_event (TraceEvent (
10096 event_type = TraceEventType .USER_MESSAGE ,
10197 agent = agent ,
10298 data = {'message' : message }
10399 ))
104-
105- assistant_output = agent .chat_completion (message )
106-
107- while assistant_output .tool_calls : # None 或者空数组
108- functions = assistant_output .tool_calls
109- for item in functions :
110- function = item .function
111- args = json .loads (function .arguments )
112-
113- if (tool_function := agent .tool_functions .get (function .name )) is not None :
114-
115- self ._add_trace_event (TraceEvent (
116- event_type = TraceEventType .TOOL_CALL ,
117- agent = agent ,
118- data = {'function' : function .name , 'arguments' : args }
119- ))
120-
121- # 自动注入上下文变量
122- if (var_name := agent .use_context_variables .get (function .name )) is not None :
123- args [var_name ] = self .context_variables
124-
125- # 自动注入当前Agent
126- if (var_name := agent .use_agent_variables .get (function .name )) is not None :
127- args [var_name ] = agent
128-
129- tool_content = tool_function (** args )
130- if inspect .iscoroutine (tool_content ): # 处理异步函数
131- tool_content = await tool_content
132-
133- match tool_content :
134- case Agent () as new_agent :
135- result = Result (agent = new_agent ,
136- content = json .dumps ({'assistant' : new_agent .name }, ensure_ascii = False ))
137- case str () as content :
138- result = Result (content = content )
139- case ContextVariables () as new_variables :
140- result = Result (context_variables = new_variables )
141- case Result () as result : # 上述三种返回值的组合类
142- pass
143- case _:
144- result = Result ()
145-
146- elif (mcp_sever := agent .mcp_functions .get (function .name )) is not None :
147- self ._add_trace_event (TraceEvent (
148- agent = agent ,
149- event_type = TraceEventType .MCP_TOOL_CALL ,
150- data = {'function' : function .name , 'arguments' : args }
151- ))
152-
153- resp = (await mcp_sever .session .call_tool (function .name , args )).content
154- text_contents = []
155- for content in resp :
156- match content :
157- case TextContent ():
158- text_contents .append (content .text )
159- case ImageContent ():
160- text_contents .append (content .data )
161- case EmbeddedResource ():
162- text_contents .append (content .resource .text )
163- case BlobResourceContents ():
164- text_contents .append (content .blob )
165- text = '\n ' .join (text_contents )
166- result = Result (content = text )
167- else :
168- result = Result (content = f'Failed to call tool: { function .name } ' )
169-
170- trace_result = {'content' : result .content }
171- if result .context_variables ._vars :
172- trace_result ['context_variables' ] = result .context_variables ._vars
173- if not result .message :
174- trace_result ['message' ] = False
175-
100+
101+ active_agent = agent
102+ self .set_agent_instruction (active_agent )
103+ agent_output = active_agent .chat_completion ()
104+
105+ while True :
106+ if agent_output .content :
176107 self ._add_trace_event (TraceEvent (
177- agent = agent ,
178- event_type = TraceEventType . TOOL_RESULT ,
179- data = {'function ' : function . name , 'result' : trace_result }
108+ event_type = TraceEventType . AGENT_MESSAGE ,
109+ agent = active_agent ,
110+ data = {'message ' : agent_output . content }
180111 ))
112+ if not agent_output .tool_calls :
113+ break
114+ functions = agent_output .tool_calls
115+ for item in functions :
116+ function = item .function
117+ args = json .loads (function .arguments )
118+
119+ if (tool_function := active_agent .tool_functions .get (function .name )) is not None :
120+
121+ self ._add_trace_event (TraceEvent (
122+ event_type = TraceEventType .TOOL_CALL ,
123+ agent = active_agent ,
124+ data = {'function' : function .name , 'arguments' : args }
125+ ))
126+
127+ # 自动注入上下文变量
128+ if (var_name := active_agent .use_context_variables .get (function .name )) is not None :
129+ args [var_name ] = self .context_variables
130+
131+ # 自动注入当前Agent
132+ if (var_name := active_agent .use_agent_variables .get (function .name )) is not None :
133+ args [var_name ] = active_agent
134+
135+ tool_content = tool_function (** args )
136+ if inspect .iscoroutine (tool_content ): # 处理异步函数
137+ tool_content = await tool_content
138+
139+ match tool_content :
140+ case Agent () as new_agent :
141+ result = Result (agent = new_agent ,
142+ content = json .dumps ({'assistant' : new_agent .name }, ensure_ascii = False ))
143+ case str () as content :
144+ result = Result (content = content )
145+ case ContextVariables () as new_variables :
146+ result = Result (context_variables = new_variables )
147+ case Result () as result : # 上述三种返回值的组合类
148+ pass
149+ case _:
150+ result = Result ()
151+
152+ elif (mcp_sever := active_agent .mcp_functions .get (function .name )) is not None :
153+ self ._add_trace_event (TraceEvent (
154+ agent = active_agent ,
155+ event_type = TraceEventType .MCP_TOOL_CALL ,
156+ data = {'function' : function .name , 'arguments' : args }
157+ ))
158+
159+ resp = (await mcp_sever .session .call_tool (function .name , args )).content
160+ text_contents = []
161+ for content in resp :
162+ match content :
163+ case TextContent ():
164+ text_contents .append (content .text )
165+ case ImageContent ():
166+ text_contents .append (content .data )
167+ case EmbeddedResource ():
168+ text_contents .append (content .resource .text )
169+ case BlobResourceContents ():
170+ text_contents .append (content .blob )
171+ text = '\n ' .join (text_contents )
172+ result = Result (content = text )
181173
182- agent .add_tool_call_result_message (result .content , item .id )
183- if result .agent is not None : # 转移给其他Agent
184- if result .message :
185- result .agent .messages .extend (copy .deepcopy (agent .messages ))
186-
187- self ._add_trace_event (TraceEvent (
188- agent = agent ,
189- event_type = TraceEventType .AGENT_SWITCH ,
190- data = {'to_agent' : result .agent }
191- ))
192- agent = result .agent
193- if result .context_variables ._vars :
174+ else :
175+ result = Result (content = f'Failed to call tool: { function .name } ' )
176+
177+ active_agent .add_tool_call_result_message (result .content , item .id )
178+ trace_result = {'content' : result .content }
179+ if result .context_variables ._vars :
180+ trace_result ['context_variables' ] = result .context_variables ._vars
181+ if not result .message :
182+ trace_result ['message' ] = False
183+
194184 self ._add_trace_event (TraceEvent (
195- agent = agent ,
196- event_type = TraceEventType .CONTEXT_UPDATE ,
197- data = {'old_context ' : self . context_variables , 'new_context ' : result . context_variables }
185+ agent = active_agent ,
186+ event_type = TraceEventType .TOOL_RESULT ,
187+ data = {'function ' : function . name , 'result ' : trace_result }
198188 ))
199- self .context_variables .update (result .context_variables )
200189
201- self .set_agent_instruction (agent )
202-
203- assistant_output = agent .chat_completion ()
204- turn += 1
205-
206- if hasattr (assistant_output , 'reasoning_content' ):
207- self ._add_trace_event (TraceEvent (
208- event_type = TraceEventType .AGENT_THINK ,
209- agent = agent ,
210- data = {'message' : assistant_output .reasoning_content }
211- ))
212- self ._add_trace_event (TraceEvent (
213- event_type = TraceEventType .AGENT_MESSAGE ,
214- agent = agent ,
215- data = {'message' : assistant_output .content }
216- ))
190+ if result .agent is not None :
191+ if result .message :
192+ result .agent .messages .extend (copy .deepcopy (active_agent .messages ))
193+ self ._add_trace_event (TraceEvent (
194+ agent = active_agent ,
195+ event_type = TraceEventType .AGENT_SWITCH ,
196+ data = {'to_agent' : result .agent }
197+ ))
198+ active_agent = result .agent
199+ if result .context_variables ._vars :
200+ self ._add_trace_event (TraceEvent (
201+ agent = active_agent ,
202+ event_type = TraceEventType .CONTEXT_UPDATE ,
203+ data = {'old_context' : self .context_variables , 'new_context' : result .context_variables }
204+ ))
205+ self .context_variables .update (result .context_variables )
206+
207+ self .set_agent_instruction (active_agent )
208+ agent_output = active_agent .chat_completion ()
217209
218210 self .trace ['end_time' ] = datetime .now ()
219211
220- return ControllerResponse (agent = agent , message = assistant_output .content , turns = turn )
212+ return ControllerResponse (agent = active_agent , message = agent_output .content )
221213
222214 def run_sync (self , agent : Agent , message : str = None ) -> ControllerResponse :
223215 """ 运行 Agent (同步版本)
0 commit comments