langchain-ai/deepagents · error · ExtensionError

Could not convert {name} into a tool: {exc}

Error message

Could not convert {name} into a tool: {exc}

What it means

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.

Source

Thrown at libs/code/deepagents_code/extensions/api.py:141

        Args:
            tool: Tool instance or plain callable.

        Raises:
            ExtensionError: If a callable cannot be converted into a tool.
        """
        self._ensure_active()
        from langchain_core.tools import BaseTool, tool as as_tool

        if isinstance(tool, BaseTool):
            self._registry.add_tool(tool, self._source)
            return
        try:
            converted = as_tool(tool)
        except Exception as exc:
            name = getattr(tool, "__name__", repr(tool))
            msg = f"Could not convert {name} into a tool: {exc}"
            raise ExtensionError(msg) from exc
        self._registry.add_tool(converted, self._source)  # type: ignore[arg-type]  # callable overload returns BaseTool

    def register_backend_route(self, prefix: str, backend: BackendProtocol) -> None:
        """Mount a backend under a virtual filesystem path.

        File operations under `prefix` are routed to `backend` by the agent's
        `CompositeBackend`. Shell execution remains on the default backend and
        cannot access routed virtual content.

        Args:
            prefix: Lowercase absolute path ending in `/`, such as `/memories/`.
            backend: Backend serving file operations under the prefix.

        Raises:
            ExtensionError: If the prefix or backend is invalid.
        """
        self._ensure_active()
        from deepagents.backends.protocol import BackendProtocol

View on GitHub (pinned to a1af029e6e)

Solutions

  1. Read the chained __cause__ exception to see why as_tool failed
  2. Add complete, JSON-serializable type annotations to every parameter and the return value of the function
  3. Ensure the function has a usable name (__name__) and a docstring describing its behavior
  4. If the callable cannot satisfy as_tool, wrap it in a plain function or build the tool explicitly instead of relying on automatic conversion
  5. Verify the object being registered is actually a callable function, not an arbitrary object

Example fix

// before
ext.register_tool(some_builtin_open)

// after
def open_file(path: str) -> str:
    """Open a file and return its contents."""
    return Path(path).read_text()

ext.register_tool(open_file)
Defensive patterns

Strategy: validation

Validate before calling

import inspect

def can_register(fn) -> bool:
    if not callable(fn) or not hasattr(fn, "__name__"):
        return False
    try:
        return inspect.signature(fn) is not None
    except (TypeError, ValueError):
        return False

if not can_register(my_func):
    raise ValueError("function lacks introspectable signature/annotations")

Type guard

def is_tool_candidate(fn: object) -> bool:
    return callable(fn) and hasattr(fn, "__name__") and hasattr(fn, "__doc__")

Try / catch

try:
    ext.register_tool(my_func)
except ExtensionError as exc:
    logger.error("tool registration failed for %s: %s", my_func, exc.__cause__)

Prevention

When it happens

Trigger: 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`.

Common situations: 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.

Related errors


AI-assisted analysis of langchain-ai/deepagents@a1af029e6e (2026-08-29). Data as JSON: /api/errors/b77dfd0aff80d1f0. Report an issue: GitHub.