{"record":{"id":"3d1e3cc434b59bbb","repo":"langchain-ai/langchain","slug":"tool-does-not-support-sync-invocation","errorCode":null,"errorMessage":"Tool does not support sync invocation.","messagePattern":"Tool does not support sync invocation\\.","errorType":"exception","errorClass":"NotImplementedError","httpStatus":null,"severity":"error","filePath":"libs/core/langchain_core/tools/simple.py","lineNumber":124,"sourceCode":"        \"\"\"Use the tool.\n\n        Args:\n            *args: Positional arguments to pass to the tool\n            config: Configuration for the run\n            run_manager: Optional callback manager to use for the run\n            **kwargs: Keyword arguments to pass to the tool\n\n        Returns:\n            The result of the tool execution\n        \"\"\"\n        if self.func:\n            if run_manager and signature(self.func).parameters.get(\"callbacks\"):\n                kwargs[\"callbacks\"] = run_manager.get_child()\n            if config_param := _get_runnable_config_param(self.func):\n                kwargs[config_param] = config\n            return self.func(*args, **kwargs)\n        msg = \"Tool does not support sync invocation.\"\n        raise NotImplementedError(msg)\n\n    async def _arun(\n        self,\n        *args: Any,\n        config: RunnableConfig,\n        run_manager: AsyncCallbackManagerForToolRun | None = None,\n        **kwargs: Any,\n    ) -> Any:\n        \"\"\"Use the tool asynchronously.\n\n        Args:\n            *args: Positional arguments to pass to the tool\n            config: Configuration for the run\n            run_manager: Optional callback manager to use for the run\n            **kwargs: Keyword arguments to pass to the tool\n\n        Returns:\n            The result of the tool execution","sourceCodeStart":106,"sourceCodeEnd":142,"githubUrl":"https://github.com/langchain-ai/langchain/blob/e32fa9a52eab3b61ad7a45399bfde59b3e580fc4/libs/core/langchain_core/tools/simple.py#L106-L142","documentation":"Tool._run raises NotImplementedError when self.func is None, i.e. the tool was constructed with only a coroutine. Sync invocation (.invoke/.run) has no implementation to call; only async invocation (.ainvoke) works.","triggerScenarios":"StructuredTool-style Tool created with coroutine=async_fn and func=None, then called via tool.invoke(...), tool.run(...), or ToolNode with a sync executor / agent using .invoke().","commonSituations":"Building async-only tools (I/O-bound APIs) but running the agent loop synchronously; a library expecting sync tools receiving an async-only one; CI tests calling .invoke on async tools.","solutions":["Provide a sync func alongside the coroutine","Or call it asynchronously: await tool.ainvoke(...) and run the agent with .ainvoke/.astream","In ToolNode/agent contexts, use the async path (await node.ainvoke(...)) so the coroutine is used"],"exampleFix":"# before\ntool = Tool.from_function(func=None, coroutine=my_async_fn, ...)  # func omitted\ntool.invoke(\"x\")  # NotImplementedError\n\n# after\nresult = asyncio.run(tool.ainvoke(\"x\"))\n# or provide a sync bridge:\ndef sync_fn(x):\n    return asyncio.run(my_async_fn(x))\ntool = Tool(name=\"t\", func=sync_fn, coroutine=my_async_fn, description=\"...\")","handlingStrategy":"type-guard","validationCode":"def supports_sync(tool) -> bool:\n    return getattr(tool, \"func\", None) is not None\n\ndef invoke_maybe_async(tool, payload):\n    if supports_sync(tool):\n        return tool.invoke(payload)\n    import asyncio\n    return asyncio.run(tool.ainvoke(payload))","typeGuard":"def is_sync_capable(tool: object) -> bool:\n    return callable(getattr(tool, \"func\", None))","tryCatchPattern":"try:\n    out = tool.invoke(payload)\nexcept NotImplementedError:\n    out = asyncio.run(tool.ainvoke(payload))","preventionTips":["Standardize on the async path (.ainvoke) in applications that use any async tools","Always provide a sync func when authoring tools for shared libraries","In tests, choose invoke vs ainvoke based on whether tool.func is set"],"tags":["langchain","tools","async","not-implemented"],"backgroundTag":null,"analyzedSha":"e32fa9a52eab3b61ad7a45399bfde59b3e580fc4","analyzedAt":"2026-08-14T18:42:09.092Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}