Skip to main content
Draft — not yet ratified. This document is published for review. It describes the intended 1.0 behaviour, its wording is not final, and nothing here is covered by a compatibility promise until a version is frozen. Do not cite it as a stable reference.
A tool call is the agent asking for something to be done. When the tool is one the application advertised in its run input, the application executes it — which makes tool calls the protocol’s human-in-the-loop core: the agent proposes, the application disposes.

User Interaction Model

Applications typically surface a tool call as it streams — a card naming the tool, arguments filling in — and, for side-effectful tools, ask the user before executing. The protocol does not mandate any particular interaction model, but see Security Considerations below.

Events

Tool calls follow the streaming pattern, matched by toolCallId.

TOOL_CALL_START

Opens a call.
  • toolCallName names the tool being called.
  • parentMessageId is OPTIONAL and attaches the call to the assistant message that carries it. When the parent message is attributed to a subagent, the call MUST agree with that attribution — a tool call belongs to the message that carries it (see Subagents).

TOOL_CALL_ARGS

Extends the open call. delta carries the next piece of the call’s arguments; the concatenated deltas form the call’s argument text, conventionally a JSON document — but the protocol carries it as text and does not validate it, which is deliberate: providers emit malformed argument strings, and the application deciding what to do with one beats the transport killing the run. A consumer MUST NOT act on the arguments before TOOL_CALL_END: until the call closes, the text is a prefix of whatever the producer is sending, not the thing itself.

TOOL_CALL_END

Closes the call. The argument text is complete — closing establishes completeness, not validity. Whoever executes the tool parses it, and what to do with text that does not parse is the application’s decision, not a protocol violation. A closed call, like a closed message, MAY be reopened by a new TOOL_CALL_START with the same toolCallId, and further arguments append. A reopening start MUST agree with the call it reopens — the same toolCallName, the same parentMessageId, the same owner. A consumer is not required to detect a disagreement, and unlike a reopened text message, the protocol makes no promise about which of the two values a consumer that missed the violation ends up holding.

TOOL_CALL_CHUNK

The compact spelling. A consumer MUST expand chunks as the streaming pattern specifies: the first chunk MUST carry toolCallId and toolCallName, and a continuation repeating toolCallName or parentMessageId with a conflicting value is fatal.

TOOL_CALL_RESULT

Carries the result of a call. It is a message in its own right — a tool message with its own messageId — and does not reopen the call it answers.
A result MAY arrive in the same run as its call — an agent-executed tool — or never arrive in the stream at all: a client-executed tool’s result returns to the producer as a tool message in the next run’s input instead.

Frontend tools

The tools list in run input is the application’s: the agent proposes a call, the application executes it. The protocol has no mid-run channel from the consumer, so the answer can only cross a run boundary — which gives the round-trip its shape:
  • A producer that calls a frontend tool MUST NOT answer it: no TOOL_CALL_RESULT, no fabricated tool message. The result is the application’s to produce.
  • The producer finishes the run with the call unanswered — RUN_FINISHED, ordinary success outcome — and SHOULD do so promptly once nothing remains that does not depend on the result. Several frontend calls MAY be left unanswered by one run; the application answers them all at once.
  • After the run finishes, the application disposes of each unanswered frontend call — executing it, or declining it, with whatever consent its own rules require. A thread that continues MUST answer every one of them first: the next run’s messages carry a tool message per call, keyed by toolCallId — a failure is still an answer, as a tool message with error set, and a call the user declined is answered by saying so. An unanswered call leaves the agent mid-thought, and a history with a dangling call is one many models reject outright. Abandoning the thread answers nothing and violates nothing — the rule binds continuation, the same way resume coverage does.
This is a different round-trip from interrupts: an interrupt is the producer explicitly stopping to ask, answered by resume entries; a frontend tool call rides the ordinary message loop, answered by conversation history. A producer SHOULD call frontend tools only from the advertised list; a call naming a tool the input did not advertise is not by itself a protocol violation — what to do with it is the consumer’s decision. The producer’s own tools, executed agent-side, never needed advertising and answer in-stream via TOOL_CALL_RESULT.

Message Flow

A client-executed tool spans two runs:

Data Types

The event shapes are defined by the schema reference: ToolCallStartEvent, ToolCallArgsEvent, ToolCallEndEvent, ToolCallChunkEvent, ToolCallResultEvent. In conversation history a call appears as a ToolCall on an AssistantMessage, and a result as a ToolMessage. The advertised tools are Tool objects on RunAgentInput.

Error Handling

The streaming pattern’s sequence rules apply unchanged: continuing or closing a call that is not open, or reopening one that is, is fatal. A call left open when the run finishes is a violation.

Security Considerations

Tool calls are the protocol’s largest attack surface, because they turn model output into actions.
  • Arguments are model-generated and MUST be treated as untrusted input: validated against the tool’s declared parameter schema where one was advertised, scrutinised like any untrusted payload where none was, and never interpolated into shell commands, queries or markup unescaped.
  • Applications SHOULD obtain user consent before executing a side-effectful tool call, and MUST NOT represent a call as user-approved when it was not.
  • Tool results are data from wherever the tool got them. A consumer MUST NOT treat text inside a result as protocol material or as instructions carrying the user’s authority.
  • A call naming a tool that was not advertised SHOULD NOT be executed without the same scrutiny a new tool would get.