Compare commits

...
2 Commits
Author SHA1 Message Date
Sydney Runkle 8086a20865 add test 2025-08-29 17:04:25 -04:00
Sydney Runkle fcfb9dd3a7 asyncio escape hatch 2025-08-29 17:02:03 -04:00
2 changed files with 39 additions and 1 deletions
@@ -443,7 +443,12 @@ class ToolNode(RunnableCallable):
return invalid_tool_message
try:
call_args = {**call, **{"type": "tool_call"}}
response = self.tools_by_name[call["name"]].invoke(call_args, config)
tool = self.tools_by_name[call["name"]]
try:
response = tool.invoke(call_args, config)
except NotImplementedError:
response = asyncio.run(tool.ainvoke(call_args, config))
# GraphInterrupt is a special exception that will always be raised.
# It can be triggered in the following scenarios,
+33
View File
@@ -1156,3 +1156,36 @@ async def test_tool_node_command_remove_all_messages():
command = result[0]
assert isinstance(command, Command)
assert command.update == {"messages": [RemoveMessage(id=REMOVE_ALL_MESSAGES)]}
async def test_async_tool_called_syncly() -> None:
"""Confirm that async tools can be called synchronously."""
@dec_tool
async def async_tool():
"""An async tool."""
return "async tool"
tool_node = ToolNode([async_tool])
result = tool_node.invoke(
{
"messages": [
AIMessage(
content="",
tool_calls=[
{
"name": "async_tool",
"args": {},
"id": "1",
"type": "tool_call",
}
],
)
]
}
)
assert result == {
"messages": [
ToolMessage(content="async tool", name="async_tool", tool_call_id="1")
]
}