{"record":{"id":"b77dfd0aff80d1f0","repo":"langchain-ai/deepagents","slug":"could-not-convert-name-into-a-tool-exc","errorCode":null,"errorMessage":"Could not convert {name} into a tool: {exc}","messagePattern":"Could not convert (.+?) into a tool: (.+?)","errorType":"exception","errorClass":"ExtensionError","httpStatus":null,"severity":"error","filePath":"libs/code/deepagents_code/extensions/api.py","lineNumber":141,"sourceCode":"\n        Args:\n            tool: Tool instance or plain callable.\n\n        Raises:\n            ExtensionError: If a callable cannot be converted into a tool.\n        \"\"\"\n        self._ensure_active()\n        from langchain_core.tools import BaseTool, tool as as_tool\n\n        if isinstance(tool, BaseTool):\n            self._registry.add_tool(tool, self._source)\n            return\n        try:\n            converted = as_tool(tool)\n        except Exception as exc:\n            name = getattr(tool, \"__name__\", repr(tool))\n            msg = f\"Could not convert {name} into a tool: {exc}\"\n            raise ExtensionError(msg) from exc\n        self._registry.add_tool(converted, self._source)  # type: ignore[arg-type]  # callable overload returns BaseTool\n\n    def register_backend_route(self, prefix: str, backend: BackendProtocol) -> None:\n        \"\"\"Mount a backend under a virtual filesystem path.\n\n        File operations under `prefix` are routed to `backend` by the agent's\n        `CompositeBackend`. Shell execution remains on the default backend and\n        cannot access routed virtual content.\n\n        Args:\n            prefix: Lowercase absolute path ending in `/`, such as `/memories/`.\n            backend: Backend serving file operations under the prefix.\n\n        Raises:\n            ExtensionError: If the prefix or backend is invalid.\n        \"\"\"\n        self._ensure_active()\n        from deepagents.backends.protocol import BackendProtocol","sourceCodeStart":123,"sourceCodeEnd":159,"githubUrl":"https://github.com/langchain-ai/deepagents/blob/a1af029e6e73cb17c36bff823d227747b28e91e1/libs/code/deepagents_code/extensions/api.py#L123-L159","documentation":"Raised by ExtensionApi.register_tool when `as_tool()` cannot turn the supplied callable into a LangChain tool. The original conversion failure is chained as __cause__ and the tool's name is included in the message. It signals that the function's signature, docstring, or annotations are unsuitable for automatic tool conversion.","triggerScenarios":"Calling `ext.register_tool(fn)` where fn lacks a resolvable signature, has annotations the tool converter cannot handle (e.g. unsupported/missing type hints), or raises during argument-schema generation inside `as_tool`.","commonSituations":"Registering a builtin or C function without introspectable signatures; a function with untyped or exotic-typed parameters (unions of non-JSON types, arbitrary objects); registering an object that is not a plain function.","solutions":["Read the chained __cause__ exception to see why as_tool failed","Add complete, JSON-serializable type annotations to every parameter and the return value of the function","Ensure the function has a usable name (__name__) and a docstring describing its behavior","If the callable cannot satisfy as_tool, wrap it in a plain function or build the tool explicitly instead of relying on automatic conversion","Verify the object being registered is actually a callable function, not an arbitrary object"],"exampleFix":"// before\next.register_tool(some_builtin_open)\n\n// after\ndef open_file(path: str) -> str:\n    \"\"\"Open a file and return its contents.\"\"\"\n    return Path(path).read_text()\n\next.register_tool(open_file)","handlingStrategy":"validation","validationCode":"import inspect\n\ndef can_register(fn) -> bool:\n    if not callable(fn) or not hasattr(fn, \"__name__\"):\n        return False\n    try:\n        return inspect.signature(fn) is not None\n    except (TypeError, ValueError):\n        return False\n\nif not can_register(my_func):\n    raise ValueError(\"function lacks introspectable signature/annotations\")","typeGuard":"def is_tool_candidate(fn: object) -> bool:\n    return callable(fn) and hasattr(fn, \"__name__\") and hasattr(fn, \"__doc__\")","tryCatchPattern":"try:\n    ext.register_tool(my_func)\nexcept ExtensionError as exc:\n    logger.error(\"tool registration failed for %s: %s\", my_func, exc.__cause__)","preventionTips":["Always annotate all parameters and return type with JSON-serializable types","Write a docstring on every function you register as a tool","Test tool registration in unit tests before shipping the extension"],"tags":["extensions","tool-registration","type-annotations"],"backgroundTag":"tool-conversion-failed","analyzedSha":"a1af029e6e73cb17c36bff823d227747b28e91e1","analyzedAt":"2026-08-29T11:43:24.718Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}