From 8086a208651ea88f8c8d081408d02fcdd1b30490 Mon Sep 17 00:00:00 2001 From: Sydney Runkle Date: Fri, 29 Aug 2025 17:04:25 -0400 Subject: [PATCH] add test --- libs/prebuilt/langgraph/prebuilt/tool_node.py | 2 +- libs/prebuilt/tests/test_tool_node.py | 33 +++++++++++++++++++ 2 files changed, 34 insertions(+), 1 deletion(-) diff --git a/libs/prebuilt/langgraph/prebuilt/tool_node.py b/libs/prebuilt/langgraph/prebuilt/tool_node.py index 453f2c961..554a0d8c9 100644 --- a/libs/prebuilt/langgraph/prebuilt/tool_node.py +++ b/libs/prebuilt/langgraph/prebuilt/tool_node.py @@ -447,7 +447,7 @@ class ToolNode(RunnableCallable): try: response = tool.invoke(call_args, config) - except NotImplementedError as e: + except NotImplementedError: response = asyncio.run(tool.ainvoke(call_args, config)) # GraphInterrupt is a special exception that will always be raised. diff --git a/libs/prebuilt/tests/test_tool_node.py b/libs/prebuilt/tests/test_tool_node.py index 2b6dfbebe..d6f759f4b 100644 --- a/libs/prebuilt/tests/test_tool_node.py +++ b/libs/prebuilt/tests/test_tool_node.py @@ -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") + ] + }