langchain-ai/langchain · error · ValueError

Runnable must have an object schema.

Error message

Runnable must have an object schema.

What it means

Raised by the @tool decorator when the object being converted is a Runnable whose input JSON schema is not of type 'object'. Tools expose their inputs as named keyword arguments, so the Runnable must accept a single dict/TypedDict/pydantic-model input; scalar (str, int) or tuple inputs cannot be mapped to tool arguments.

Source

Thrown at libs/core/langchain_core/tools/convert.py:291

        """Create a decorator that takes a callable and returns a tool.

        Args:
            tool_name: The name that will be assigned to the tool.

        Returns:
            A function that takes a callable or `Runnable` and returns a tool.
        """

        def _tool_factory(
            dec_func: Callable[..., Any] | Runnable[Any, Any],
        ) -> BaseTool:
            tool_description = description
            if isinstance(dec_func, Runnable):
                runnable = dec_func

                if runnable.get_input_jsonschema().get("type") != "object":
                    msg = "Runnable must have an object schema."
                    raise ValueError(msg)

                async def ainvoke_wrapper(
                    callbacks: Callbacks | None = None, **kwargs: Any
                ) -> Any:
                    return await runnable.ainvoke(kwargs, {"callbacks": callbacks})

                def invoke_wrapper(
                    callbacks: Callbacks | None = None, **kwargs: Any
                ) -> Any:
                    return runnable.invoke(kwargs, {"callbacks": callbacks})

                coroutine = ainvoke_wrapper
                func = invoke_wrapper
                schema: ArgsSchema | None = runnable.input_schema
                tool_description = description or repr(runnable)
            elif inspect.iscoroutinefunction(dec_func):
                coroutine = dec_func
                func = None

View on GitHub (pinned to e32fa9a52e)

Solutions

  1. Give the Runnable a dict-like input: wrap it so InputType is a TypedDict or pydantic BaseModel, e.g. lambda x: chain(x['text']) with InputType typed as a TypedDict
  2. Or skip @tool and use Tool(func=lambda text: runnable.invoke(text)) for single-string inputs
  3. Check runnable.get_input_jsonschema() first and restructure until it returns {"type": "object", ...}

Example fix

# before
chain = prompt | llm          # InputType: str
@tool
def my_tool(): ...             # or tool(chain)

# after
class ChainInput(TypedDict):
    question: str

def _run(x: ChainInput) -> str:
    return (prompt | llm).invoke({"question": x["question"]})

chain = RunnableLambda(_run)  # get_input_jsonschema() -> type: object
tool = chain.as_tool(name="answer")
Defensive patterns

Strategy: type-guard

Validate before calling

def is_object_schema_runnable(runnable) -> bool:
    try:
        schema = runnable.get_input_jsonschema()
    except Exception:
        return False
    return isinstance(schema, dict) and schema.get("type") == "object"

Type guard

from langchain_core.runnables import Runnable

def can_convert_to_tool(runnable: object) -> bool:
    return (
        isinstance(runnable, Runnable)
        and runnable.get_input_jsonschema().get("type") == "object"
    )

Try / catch

try:
    t = runnable.as_tool()
except ValueError as e:
    if "object schema" in str(e):
        t = Tool(name="runnable", func=lambda **kw: runnable.invoke(kw),
                 description="Wrapped runnable")
    else:
        raise

Prevention

When it happens

Trigger: @tool applied to a Runnable whose InputType is str (e.g. a bare prompt template or a lambda taking a string); runnable.as_tool() / convert_runnable_to_tool on a chain with InputType = int or a Union; a Runnable built with a func whose input schema is an array.

Common situations: Wrapping a prompt | llm chain that takes a plain string input; converting a parser or embedding-style Runnable into a tool; using .with_structured_output(...) on something whose input is not a dict.

Related errors


AI-assisted analysis of langchain-ai/langchain@e32fa9a52e (2026-08-14). Data as JSON: /api/errors/a11a920e433fce66. Report an issue: GitHub.