Basic tool creation with @tool decorator
The simplest way to create a tool in Python is with the @tool decorator. Type hints are required as they define the tool's input schema. The function's docstring becomes the tool's description that helps the model understand when to use it.
JavaScript tool creation with zod schema
In JavaScript, create tools using the tool() function from langchain with zod to define the input schema. Pass an object with name, description, and schema properties.
Tool naming conventions
Prefer snake_case for tool names (e.g., web_search instead of Web Search). Some model providers have issues with or reject names containing spaces or special characters. Stick to alphanumeric characters, underscores, and hyphens for improved compatibility across providers.
Custom tool name with @tool decorator
Override the default tool name (which comes from the function name) by passing a string to the @tool decorator: @tool('custom_name'). Access the tool name via the .name attribute.
Custom tool description with @tool decorator
Override the auto-generated tool description using the description parameter: @tool('tool_name', description='Custom description text'). This provides clearer guidance to the model.
Advanced schema definition with Pydantic models
Define complex tool inputs using Pydantic BaseModel with Field annotations. Pass the Pydantic model to the args_schema parameter of @tool. Use Literal types for constrained string options and boolean/integer fields for structured validation.
Advanced schema definition with JSON schema
Define complex tool inputs using JSON schema objects with type, properties, and required fields. Pass the schema dictionary to the args_schema parameter of @tool decorator.
Reserved parameter names in tools
The parameter names 'config' and 'runtime' are reserved and cannot be used as tool arguments. Using these names will cause runtime errors. Use the @ToolRuntime parameter instead to access reserved functionality.
ToolRuntime parameter provides runtime context access
Tools can access runtime information through the @ToolRuntime parameter. ToolRuntime provides access to: state (short-term memory), context (immutable configuration), store (long-term memory), stream_writer (real-time updates), execution_info (thread ID, run ID, attempt number), server_info (LangGraph Server metadata), config (RunnableConfig), and tool_call_id (unique identifier for the current tool invocation).
Access state with ToolRuntime
Add runtime: ToolRuntime to the tool signature. Use runtime.state to read the current conversation state, including messages and custom fields. The runtime parameter is hidden from the model and does not appear in the tool schema sent to the model.
Update state from a tool
Use @Command to update the agent's state from within a tool. Include a ToolMessage in the update so the model can see the result of the tool call. When tools update state variables, define a reducer for those fields to handle conflicts from concurrent tool calls.
Access context with ToolRuntime
Access context through runtime.context. Context provides immutable configuration data passed at invocation time such as user IDs and session details. Pass context alongside a thread_id so the conversation is persisted across turns.
Long-term memory store access with ToolRuntime
Access the BaseStore through runtime.store. The store uses a namespace/key pattern to organize data (e.g., store.get((namespace,), key) and store.put((namespace,), key, value)). The store provides persistent storage that survives across conversations, unlike state which is short-term.
Access execution info from tools
Access thread ID, run ID, and retry state from runtime.execution_info. Properties include thread_id, run_id, and node_attempt. Requires deepagents>=0.5.0 or langgraph>=1.1.5.
Access server info from tools on LangGraph Server
When running on LangGraph Server, access server metadata via runtime.server_info. Provides assistant_id, graph_id, and user information. Returns None when not running on LangGraph Server. Requires deepagents>=0.5.0 or langgraph>=1.1.5.
Tool return value: string
Return a string when the tool should provide plain text for the model to read. The return value is converted to a ToolMessage. The model sees the text and decides what to do next. No agent state fields are changed unless the model or another tool does so later. Use this when the result is naturally human-readable text.
Tool return value: object
Return an object (dict) when the tool produces structured data that the model should inspect. The object is serialized and sent back as tool output. The model can read specific fields and reason over them. Does not directly update graph state. Use when downstream reasoning benefits from explicit fields instead of free-form text.
Tool return value: multimodal content
Tools can return multimodal content as a list of content blocks. Each block is a dict with 'type' and corresponding properties. Return [{"type": "text", "text": "..."}, {"type": "image", "url": "..."}] for mixed content. The model must support the modalities being returned.
Tool return value: Command
Return a @Command when the tool needs to update graph state. Include a ToolMessage in the update whose tool_call_id matches the current tool call. For Python, use runtime.tool_call_id for the tool_call_id parameter. Every tool call in the message history must have a corresponding ToolMessage.
Tool return direct behavior
Set return_direct=True on a tool to short-circuit the agent loop. The agent returns the tool's output immediately without sending it back through the model. When the model calls multiple tools in one step, the agent only exits if every tool in that batch has return_direct=True. Mixed parallel calls with some return_direct=True and others without will route back to the model.
When to use return_direct=True
Use return_direct=True when: the tool's output is the complete, user-ready answer (e.g., a lookup returning ready-to-display results), you want to avoid an extra model call when no additional reasoning is needed, or you need deterministic, unmodified output where the model cannot rephrase or act on the result.
When NOT to use return_direct=True
Do not use return_direct=True for tools whose results require further reasoning, summarization, or chaining with other tool calls. The model does not process the output so it cannot provide value-add.
Command with return_direct requires ToolMessage
A tool with return_direct=True can also return a @Command to update state before exiting. When the Command targets the current graph, include a ToolMessage in Command.update matching the tool call's tool_call_id. Omitting it causes ToolNode to raise a ValueError. To write to parent graph instead, set graph=Command.PARENT and the ToolMessage requirement is lifted.
Dynamic tool selection: filtering pre-registered tools
When all possible tools are known at agent creation time, pre-register them and dynamically filter which ones are exposed to the model. Filter based on state (authentication, message count), store (user preferences, feature flags), or runtime context (user permissions). Use middleware with wrap_model_call to override request.tools.
Dynamic tool selection: runtime registration
When tools are discovered or created at runtime (from MCP server, user data, remote registry), use two middleware hooks: wrap_model_call to add dynamic tools to the request, and wrap_tool_call to handle execution of dynamically added tools. The wrap_tool_call hook is required because the agent needs to know how to execute tools that weren't in the original list.
Headless tools overview
Headless tools are tool definitions (name, description, argument schema) registered on the server with the agent, while the implementation is registered only on the client and executed after an interrupt/resume handshake. Unlike ordinary tools that run on the server, the implementation runs where the user's app runs (typically the browser).
When to use headless tools
Use headless tools when the work depends on environment, device, or UI that only exists on the client. Examples: Browser APIs (Geolocation, IndexedDB, Clipboard, Canvas 2D, file pickers, Battery API), privacy/locality concerns (data stays on device), latency reduction (no extra server round trip), structured safe effects (many small typed tools instead of arbitrary code).
Headless tools pattern in Python
In Python, create a headless tool by calling tool(name=..., description=..., args_schema=...) from langchain.tools with only schema, no implementation. Register it with create_agent or LangGraph graph. Handle the interrupt payload when invoked. Resume after the action is performed elsewhere.
Headless tools pattern in JavaScript
In JavaScript, define the tool with tool({ name, description, schema }) for metadata/validation only with no implementation. Attach behavior with .implement(async (args) => { ... }), which returns a headless tool implementation (definition + execute function). Register the definition with createAgent/graph so the model sees it. Pass the implementation to streaming hook's tools option.
Headless tools module structure
Put tool definitions and implementations in separate modules. Import the shared definition file from both server agent and frontend so names and schemas stay aligned. Keep client-only execute logic in implementation modules the server never loads.
Headless tools lifecycle and onTool callback
Use the optional onTool callback to observe lifecycle events (start, success, error) for headless tools. This enables UI feedback such as spinners or toasts during tool execution.
Prebuilt tools and toolkits
LangChain provides a large collection of prebuilt tools and toolkits for common tasks like web search, code interpretation, database access, and more. These ready-to-use tools can be directly integrated into agents without writing custom code. See the tools and toolkits integration page for a complete list organized by category.
Server-side tool use
Some chat models feature built-in tools executed server-side by the model provider. These include capabilities like web search and code interpreters that don't require defining or hosting tool logic. Refer to individual chat model integration pages and tool calling documentation for details.
Tools under the hood
Under the hood, tools are callable functions with well-defined inputs and outputs that get passed to a chat model. The model decides when to invoke a tool based on conversation context and what input arguments to provide.
LangSmith tool tracing and debugging
Trace tool calls and debug errors with LangSmith. Follow the tracing quickstart to get set up. LangSmith Engine monitors traces, detects issues, and proposes fixes.