How tool calling works
When a LangGraph agent decides it needs external data, it emits one or more tool calls as part of an AI message. Each tool call includes:- name—the tool being invoked (e.g.
"get_weather","calculator") - args—the structured arguments passed to the tool
- id—a unique identifier linking the call to its result
ToolMessage. The useStream hook unifies all of this into a single
toolCalls array you can render directly.
Setting up useStream
The first step is wiring upuseStream to your agent backend. The hook returns
reactive state including a toolCalls array that updates in real time as the
agent streams.
Define a TypeScript interface matching your agent’s state schema and pass it as a type parameter to useStream for type-safe access to state values. In the examples below, replace typeof myAgent with your interface name:
The ToolCallWithResult type
Each entry in thetoolCalls array is a ToolCallWithResult object:
| Property | Description |
|---|---|
call.id | Unique ID matching the AI message’s tool_calls entry |
call.name | The name of the tool (e.g. "get_weather") |
call.args | Structured arguments the agent passed to the tool |
result | The ToolMessage response, available once the tool finishes |
state | Lifecycle state: "pending" while running, "completed" on success, "error" on failure |
Filtering tool calls per message
An AI message may trigger multiple tool calls, and your chat may contain many AI messages. To render the right tool cards under each message, filter by matchingcall.id against the message’s tool_calls array:
Building specialized tool cards
Rather than dumping raw JSON, build dedicated UI components for each tool. Usecall.name to select the right card:
Weather card example
Loading and error states
Always handle the pending and error states to give users clear feedback:Type-safe tool arguments
If your tools are defined with structured schemas, you can use theToolCallFromTool utility type to get fully typed args:
Rendering tool calls inline with streaming text
Tool calls often arrive interleaved with streamed text. TheuseStream hook
keeps toolCalls in sync with the stream, so pending cards appear as soon as
the agent emits the call—before the tool has finished executing.
This means users see:
- The AI’s text as it streams in
- A loading card the moment a tool call is emitted
- The card updates to show the result once the tool completes
Tool calls update in place. The same
call.id transitions from "pending" to
"completed" (or "error"), so your UI simply re-renders the same component
with new state.Handling multiple concurrent tool calls
Agents can invoke several tools in parallel. ThetoolCalls array will contain
multiple entries with state: "pending" simultaneously. Each resolves
independently, so your UI should handle partial completion gracefully:
Best practices
Follow these guidelines when building tool call UIs:
- Always handle all three states—
pending,completed, anderror. Users should never see a blank card. - Parse results safely—tool results arrive as strings. Wrap
JSON.parse()in a try/catch and show a fallback on parse failure. - Provide a generic fallback—not every tool needs a bespoke card. Render a collapsible JSON view for unknown tool names.
- Show the tool name and args during loading—users want to know what the agent is doing, even before the result arrives.
- Keep cards compact—tool cards sit inline with chat messages. Avoid overwhelming the conversation with oversized widgets.
Connect these docs to Claude, VSCode, and more via MCP for real-time answers.

