How to access tool call id using runtime

I have a tool i am trying to access the tool call id using run time but i ma getting this error

**TypeError(“handle_site_selection() missing 1 required positional argument: ‘runtime’”)
**
My code

from langchain.tools import tool, ToolRuntime

@tool(“site_selection”, description=SITE_SELECTION_DESCRIPTION, args_schema=SiteSelectionInput )

def handle_site_selection(

country: str,

location: str,

system_capacity_kw: float,

capex_per_kw: float,

search_radius_km: float,

max_sites: int,

runtime: ToolRuntime,

) → Command:

“”" Perform site selection analysis for a project “”"

# Get the tool call id

tool_call_id = runtime.tool_call_id

## Return an update to the state with the site selection results

return Command(

update={

“messages”: [

ToolMessage(content=”site selection result”, tool_call_id=tool_call_id),],

    }

)

Hi @Jameskanyiri

The error means the runtime parameter is not being injected when your tool runs. There are two common causes and two clean fixes:

  • Cause A: Using @tool(..., args_schema=...) hides the runtime parameter from the tool’s inferred input schema, so the LangGraph ToolNode can’t detect it and doesn’t inject it.

  • Cause B: Invoking the tool outside of LangGraph’s ToolNode/agent flow (e.g., calling the function or tool directly) - injection only happens when tools are executed by the graph or the new v1 agents.

Pick one of the following fixes.

  1. Use ToolRuntime injection (remove args_schema and run via ToolNode/agent)
from langchain_core.tools import tool
from langchain.tools import ToolRuntime
from langgraph.types import Command
from langchain_core.messages import ToolMessage

@tool("site_selection", description=SITE_SELECTION_DESCRIPTION)
def handle_site_selection(
    country: str,
    location: str,
    system_capacity_kw: float,
    capex_per_kw: float,
    search_radius_km: float,
    max_sites: int,
    runtime: ToolRuntime,
) -> Command:
    tool_call_id = runtime.tool_call_id
    return Command(update={"messages": [ToolMessage("site selection result", tool_call_id=tool_call_id)]})

Ensure the tool is executed by a LangGraph ToolNode (or the new v1 create_agent) so ToolRuntime is constructed and injected, giving you runtime.tool_call_id.

  1. Keep args_schema but inject only the tool_call_id

Important: if you keep args_schema, the injected parameter must be defined on that schema. Add tool_call_id to SiteSelectionInput annotated with InjectedToolCallId, then accept it in your function.

from typing_extensions import Annotated
from pydantic import BaseModel
from langchain_core.tools import InjectedToolCallId

class SiteSelectionInput(BaseModel):
    country: str
    location: str
    system_capacity_kw: float
    capex_per_kw: float
    search_radius_km: float
    max_sites: int
    tool_call_id: Annotated[str, InjectedToolCallId]  # injected by the runtime
from langchain_core.tools import tool
from langgraph.types import Command
from langchain_core.messages import ToolMessage

@tool("site_selection", description=SITE_SELECTION_DESCRIPTION, args_schema=SiteSelectionInput)
def handle_site_selection(
    country: str,
    location: str,
    system_capacity_kw: float,
    capex_per_kw: float,
    search_radius_km: float,
    max_sites: int,
    tool_call_id: str,  # can be plain str; it's annotated in the schema
) -> Command:
    return Command(update={"messages": [ToolMessage("site selection result", tool_call_id=tool_call_id)]})

This keeps your custom schema and still injects the call id. You do not need a runtime parameter for this option. If you instead want to inject runtime while keeping args_schema, then the schema must include a runtime: ToolRuntime field (the injector detects a field named runtime or typed as ToolRuntime).

  1. Keep args_schema and inject runtime via the schema

If you want runtime while keeping a custom args_schema, define it on the schema and on the function. Also allow arbitrary types so Pydantic accepts ToolRuntime.

# Pydantic v2
from pydantic import BaseModel, ConfigDict
from langchain.tools import ToolRuntime

class SiteSelectionInput(BaseModel):
    model_config = ConfigDict(arbitrary_types_allowed=True)

    country: str
    location: str
    system_capacity_kw: float
    capex_per_kw: float
    search_radius_km: float
    max_sites: int
    runtime: ToolRuntime  # injected by ToolNode
# Pydantic v1
from pydantic import BaseModel
from langchain.tools import ToolRuntime

class SiteSelectionInput(BaseModel):
    class Config:
        arbitrary_types_allowed = True

    country: str
    location: str
    system_capacity_kw: float
    capex_per_kw: float
    search_radius_km: float
    max_sites: int
    runtime: ToolRuntime
from langchain_core.tools import tool
from langgraph.types import Command
from langchain_core.messages import ToolMessage

@tool("site_selection", description=SITE_SELECTION_DESCRIPTION, args_schema=SiteSelectionInput)
def handle_site_selection(
    country: str,
    location: str,
    system_capacity_kw: float,
    capex_per_kw: float,
    search_radius_km: float,
    max_sites: int,
    runtime: ToolRuntime,  # must be accepted by the function
) -> Command:
    tool_call_id = runtime.tool_call_id
    return Command(update={"messages": [ToolMessage("site selection result", tool_call_id=tool_call_id)]})

Thank you @pawel-twardziak

1 Like