[GH-ISSUE #1219] [langchain]: Passing ToolRuntime #172

Open
opened 2026-02-17 17:19:20 -05:00 by yindo · 0 comments
Owner

Originally created by @tahoward on GitHub (Oct 31, 2025).
Original GitHub issue: https://github.com/langchain-ai/docs/issues/1219

Type of issue

question

Language

Python

Description

Hello, I'm trying to execute a tool that I'd like runtime info passed to without "create_agent" and just invoking and handling the tool execution cycle manually.

Example:

@tool("Other_Tool", description="Another tool.")
async def other_tool(request, runtime: ToolRuntime):
    logger.info(f"Other_Tool_Runtime: {runtime}")
    
    data = runtime.state.get("data")
    
    if data is None:
        data = {}
    
    data[f"my_data_{len(data)}"] = request
    
    return Command(
        update={
            "messages": [ToolMessage(content="Other_Tool Completed.", tool_call_id=runtime.tool_call_id)],
            "data": data
        }
    )


@tool("My_Tool", description="A sample tool.")
async def my_tool(request, runtime: ToolRuntime):
    
    model_with_tools = model.bind_tools(tools=[
        other_tool
    ])

    tools: Dict[str, Callable] = {
        "Other_Tool":  other_tool,
    }

    messages = [SystemMessage(content="You are an agent that runs other tool."), HumanMessage(content=request)]
    ai_message = await model_with_tools.ainvoke(input=messages)
    messages.append(ai_message)

    for tool_call in ai_message.tool_calls:
        tool_call['args']['runtime'] = ToolRuntime(
            state=runtime.state,
            context=runtime.context,
            tool_call_id=tool_call["id"],
            config=runtime.config,
            stream_writer=runtime.stream_writer,
            store=runtime.store
        )
        
        try:
            tool_result = await tools[tool_call["name"]].ainvoke(tool_call)
        except Exception as e:
            return f"Failed to run tool [{tool_call['name']}]: {e}"

        if isinstance(tool_result, Command):
            messages.extend(tool_result.update["messages"])
        else:
            messages.append(tool_result)

    final_response = await model_with_tools.ainvoke(input=messages) # <- Error raised here

    return Command(
        update={
            "messages": [
                ToolMessage(
                    content=final_response.text,
                    tool_call_id=runtime.tool_call_id
                ),
            ],
            "data": tool_result.update["data"] if isinstance(tool_result, Command) else {}
        }
    )

Exception:

Exception: <class 'botocore.exceptions.ParamValidationError'>(Parameter validation failed:
Invalid type for document parameter runtime, value: ToolRuntime(state={'messages': [HumanMessage(content='Run my other tool!', ...), type: <class 'langchain.tools.tool_node.ToolRuntime'>, valid types: <class 'str'>, <class 'int'>, <class 'bool'>, <class 'float'>, <class 'list'>, <class 'dict'>)

The tool gets ran no problem but getting final response blows up. Appears to only happen when the target tool has a runtime argument.

This will happen even if I don't add the tool result to the messages. I find that very strange as I'd expect the LLM to complain there's no tool_result for the tool id.

What's the appropriate way to pass state/context when handling tool execution cycle manually?

Originally created by @tahoward on GitHub (Oct 31, 2025). Original GitHub issue: https://github.com/langchain-ai/docs/issues/1219 ### Type of issue question ### Language Python ### Description Hello, I'm trying to execute a tool that I'd like runtime info passed to without "create_agent" and just invoking and handling the tool execution cycle manually. Example: ```python @tool("Other_Tool", description="Another tool.") async def other_tool(request, runtime: ToolRuntime): logger.info(f"Other_Tool_Runtime: {runtime}") data = runtime.state.get("data") if data is None: data = {} data[f"my_data_{len(data)}"] = request return Command( update={ "messages": [ToolMessage(content="Other_Tool Completed.", tool_call_id=runtime.tool_call_id)], "data": data } ) @tool("My_Tool", description="A sample tool.") async def my_tool(request, runtime: ToolRuntime): model_with_tools = model.bind_tools(tools=[ other_tool ]) tools: Dict[str, Callable] = { "Other_Tool": other_tool, } messages = [SystemMessage(content="You are an agent that runs other tool."), HumanMessage(content=request)] ai_message = await model_with_tools.ainvoke(input=messages) messages.append(ai_message) for tool_call in ai_message.tool_calls: tool_call['args']['runtime'] = ToolRuntime( state=runtime.state, context=runtime.context, tool_call_id=tool_call["id"], config=runtime.config, stream_writer=runtime.stream_writer, store=runtime.store ) try: tool_result = await tools[tool_call["name"]].ainvoke(tool_call) except Exception as e: return f"Failed to run tool [{tool_call['name']}]: {e}" if isinstance(tool_result, Command): messages.extend(tool_result.update["messages"]) else: messages.append(tool_result) final_response = await model_with_tools.ainvoke(input=messages) # <- Error raised here return Command( update={ "messages": [ ToolMessage( content=final_response.text, tool_call_id=runtime.tool_call_id ), ], "data": tool_result.update["data"] if isinstance(tool_result, Command) else {} } ) ``` Exception: ``` Exception: <class 'botocore.exceptions.ParamValidationError'>(Parameter validation failed: Invalid type for document parameter runtime, value: ToolRuntime(state={'messages': [HumanMessage(content='Run my other tool!', ...), type: <class 'langchain.tools.tool_node.ToolRuntime'>, valid types: <class 'str'>, <class 'int'>, <class 'bool'>, <class 'float'>, <class 'list'>, <class 'dict'>) ``` The tool gets ran no problem but getting final response blows up. Appears to only happen when the target tool has a runtime argument. This will happen even if I don't add the tool result to the messages. I find that very strange as I'd expect the LLM to complain there's no tool_result for the tool id. What's the appropriate way to pass state/context when handling tool execution cycle manually?
yindo added the langchainexternal labels 2026-02-17 17:19:20 -05:00
yindo changed title from [langchain]: Passing ToolRuntime to [GH-ISSUE #1219] [langchain]: Passing ToolRuntime 2026-06-05 17:25:28 -04:00
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: langchain-ai/docs#172