11import asyncio
22import json
3- from typing import Any , Coroutine , Dict , List , Mapping , Tuple
3+ from typing import Any , Coroutine , Dict , List , Mapping , Sequence , Tuple
44
55from agnext .chat .agents .base import BaseChatAgent
66from agnext .chat .types import (
1212 TextMessage ,
1313)
1414from agnext .chat .utils import convert_messages_to_llm_messages
15- from agnext .components .function_executor import FunctionExecutor
16- from agnext .components .models import FunctionExecutionResult , FunctionExecutionResultMessage , ModelClient , SystemMessage
17- from agnext .components .type_routed_agent import TypeRoutedAgent , message_handler
18- from agnext .components .types import (
15+ from agnext .components import (
1916 FunctionCall ,
20- FunctionSignature ,
17+ TypeRoutedAgent ,
18+ message_handler ,
2119)
20+ from agnext .components .models import FunctionExecutionResult , FunctionExecutionResultMessage , ModelClient , SystemMessage
21+ from agnext .components .tools import Tool
2222from agnext .core import AgentRuntime , CancellationToken
2323
2424
@@ -30,13 +30,13 @@ def __init__(
3030 runtime : AgentRuntime ,
3131 system_messages : List [SystemMessage ],
3232 model_client : ModelClient ,
33- function_executor : FunctionExecutor | None = None ,
33+ tools : Sequence [ Tool ] = [] ,
3434 ) -> None :
3535 super ().__init__ (name , description , runtime )
3636 self ._system_messages = system_messages
3737 self ._client = model_client
3838 self ._chat_messages : List [Message ] = []
39- self ._function_executor = function_executor
39+ self ._tools = tools
4040
4141 @message_handler ()
4242 async def on_text_message (self , message : TextMessage , cancellation_token : CancellationToken ) -> None :
@@ -52,23 +52,18 @@ async def on_reset(self, message: Reset, cancellation_token: CancellationToken)
5252 async def on_respond_now (
5353 self , message : RespondNow , cancellation_token : CancellationToken
5454 ) -> TextMessage | FunctionCallMessage :
55- # Get function signatures.
56- function_signatures : List [FunctionSignature ] = (
57- [] if self ._function_executor is None else list (self ._function_executor .function_signatures )
58- )
59-
6055 # Get a response from the model.
6156 response = await self ._client .create (
6257 self ._system_messages + convert_messages_to_llm_messages (self ._chat_messages , self .name ),
63- functions = function_signatures ,
58+ tools = self . _tools ,
6459 json_output = message .response_format == ResponseFormat .json_object ,
6560 )
6661
6762 # If the agent has function executor, and the response is a list of
6863 # tool calls, iterate with itself until we get a response that is not a
6964 # list of tool calls.
7065 while (
71- self ._function_executor is not None
66+ len ( self ._tools ) > 0
7267 and isinstance (response .content , list )
7368 and all (isinstance (x , FunctionCall ) for x in response .content )
7469 ):
@@ -81,7 +76,7 @@ async def on_respond_now(
8176 # Make an assistant message from the response.
8277 response = await self ._client .create (
8378 self ._system_messages + convert_messages_to_llm_messages (self ._chat_messages , self .name ),
84- functions = function_signatures ,
79+ tools = self . _tools ,
8580 json_output = message .response_format == ResponseFormat .json_object ,
8681 )
8782
@@ -105,8 +100,8 @@ async def on_respond_now(
105100 async def on_tool_call_message (
106101 self , message : FunctionCallMessage , cancellation_token : CancellationToken
107102 ) -> FunctionExecutionResultMessage :
108- if self ._function_executor is None :
109- raise ValueError ("Function executor is not set. " )
103+ if len ( self ._tools ) == 0 :
104+ raise ValueError ("No tools available " )
110105
111106 # Add a tool call message.
112107 self ._chat_messages .append (message )
@@ -127,7 +122,9 @@ async def on_tool_call_message(
127122 )
128123 continue
129124 # Execute the function.
130- future = self .execute_function (function_call .name , arguments , function_call .id )
125+ future = self .execute_function (
126+ function_call .name , arguments , function_call .id , cancellation_token = cancellation_token
127+ )
131128 # Append the async result.
132129 execution_futures .append (future )
133130 if execution_futures :
@@ -146,14 +143,25 @@ async def on_tool_call_message(
146143 # Return the results.
147144 return tool_call_result_msg
148145
149- async def execute_function (self , name : str , args : Dict [str , Any ], call_id : str ) -> Tuple [str , str ]:
150- if self ._function_executor is None :
151- raise ValueError ("Function executor is not set." )
146+ async def execute_function (
147+ self , name : str , args : Dict [str , Any ], call_id : str , cancellation_token : CancellationToken
148+ ) -> Tuple [str , str ]:
149+ # Find tool
150+ tool = next ((t for t in self ._tools if t .name == name ), None )
151+ if tool is None :
152+ raise ValueError (f"Tool { name } not found." )
152153 try :
153- result = await self ._function_executor .execute_function (name , args )
154+ result = await tool .run_json (args , cancellation_token )
155+ result_json_or_str = result .model_dump ()
156+ if isinstance (result , dict ):
157+ result_str = json .dumps (result_json_or_str )
158+ elif isinstance (result_json_or_str , str ):
159+ result_str = result_json_or_str
160+ else :
161+ raise ValueError (f"Unexpected result type: { type (result )} " )
154162 except Exception as e :
155- result = f"Error: { str (e )} "
156- return (result , call_id )
163+ result_str = f"Error: { str (e )} "
164+ return (result_str , call_id )
157165
158166 def save_state (self ) -> Mapping [str , Any ]:
159167 return {
0 commit comments