refactor: update callback type signatures to support sync and async responses

This commit is contained in:
Alankrit Verma 2025-04-29 09:02:09 -04:00
parent 504aa6ba06
commit fcbf57466e
3 changed files with 82 additions and 83 deletions

View File

@ -57,11 +57,11 @@ AfterModelCallback: TypeAlias = Callable[
] ]
BeforeToolCallback: TypeAlias = Callable[ BeforeToolCallback: TypeAlias = Callable[
[BaseTool, dict[str, Any], ToolContext], [BaseTool, dict[str, Any], ToolContext],
Awaitable[Optional[dict]], Union[Awaitable[Optional[dict]], Optional[dict]],
] ]
AfterToolCallback: TypeAlias = Callable[ AfterToolCallback: TypeAlias = Callable[
[BaseTool, dict[str, Any], ToolContext, dict], [BaseTool, dict[str, Any], ToolContext, dict],
Awaitable[Optional[dict]], Union[Awaitable[Optional[dict]], Optional[dict]],
] ]
InstructionProvider: TypeAlias = Callable[[ReadonlyContext], str] InstructionProvider: TypeAlias = Callable[[ReadonlyContext], str]

View File

@ -151,36 +151,33 @@ async def handle_function_calls_async(
# do not use "args" as the variable name, because it is a reserved keyword # do not use "args" as the variable name, because it is a reserved keyword
# in python debugger. # in python debugger.
function_args = function_call.args or {} function_args = function_call.args or {}
function_response = None function_response: Optional[dict] = None
# # Calls the tool if before_tool_callback does not exist or returns None.
# if agent.before_tool_callback: # before_tool_callback (sync or async)
# function_response = agent.before_tool_callback(
# tool=tool, args=function_args, tool_context=tool_context
# )
# Short-circuit via before_tool_callback (sync *or* async)
if agent.before_tool_callback: if agent.before_tool_callback:
_maybe = agent.before_tool_callback( function_response = agent.before_tool_callback(
tool=tool, args=function_args, tool_context=tool_context tool=tool, args=function_args, tool_context=tool_context
) )
if inspect.isawaitable(_maybe): if inspect.isawaitable(function_response):
_maybe = await _maybe function_response = await function_response
function_response = _maybe
if not function_response: if not function_response:
function_response = await __call_tool_async( function_response = await __call_tool_async(
tool, args=function_args, tool_context=tool_context tool, args=function_args, tool_context=tool_context
) )
# Calls after_tool_callback if it exists.
# after_tool_callback (sync or async)
if agent.after_tool_callback: if agent.after_tool_callback:
_maybe2 = agent.after_tool_callback( altered_function_response = agent.after_tool_callback(
tool=tool, tool=tool,
args=function_args, args=function_args,
tool_context=tool_context, tool_context=tool_context,
tool_response=function_response, tool_response=function_response,
) )
if inspect.isawaitable(_maybe2): if inspect.isawaitable(altered_function_response):
_maybe2 = await _maybe2 altered_function_response = await altered_function_response
if _maybe2 is not None: if altered_function_response is not None:
function_response = _maybe2 function_response = altered_function_response
if tool.is_long_running: if tool.is_long_running:
# Allow long running function to return None to not provide function response. # Allow long running function to return None to not provide function response.

View File

@ -27,6 +27,7 @@ from ... import utils
class AsyncBeforeToolCallback: class AsyncBeforeToolCallback:
def __init__(self, mock_response: Dict[str, Any]): def __init__(self, mock_response: Dict[str, Any]):
self.mock_response = mock_response self.mock_response = mock_response
@ -40,6 +41,7 @@ class AsyncBeforeToolCallback:
class AsyncAfterToolCallback: class AsyncAfterToolCallback:
def __init__(self, mock_response: Dict[str, Any]): def __init__(self, mock_response: Dict[str, Any]):
self.mock_response = mock_response self.mock_response = mock_response