> ## Documentation Index
> Fetch the complete documentation index at: https://agentclientprotocol.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Tool Calls

> How Agents report tool call execution

Tool calls represent actions that language models request Agents to perform during a [session](/protocol/v2/draft/prompt-lifecycle). When an LLM determines it needs to interact with external systems—like reading files, running code, or fetching data—it generates tool calls that the Agent executes on its behalf.

Agents report tool calls through [`session/update`](/protocol/v2/draft/prompt-lifecycle#3-agent-reports-output) notifications, allowing Clients to display real-time progress and results to users.

Tool call updates may arrive while the Agent reports `idle`. They do not change the state.

While Agents handle the actual execution, they may use Client-mediated
interactions like [permission requests](#requesting-permission) to provide a
richer, more integrated experience.

## Reporting

When the language model requests a tool invocation, the Agent **SHOULD** report it to the Client with a `tool_call_update`:

```json theme={null}
{
  "jsonrpc": "2.0",
  "method": "session/update",
  "params": {
    "sessionId": "sess_abc123def456",
    "update": {
      "sessionUpdate": "tool_call_update",
      "toolCallId": "call_001",
      "title": "Reading configuration file",
      "name": "read_file",
      "kind": "read",
      "status": "pending"
    }
  }
}
```

<ParamField path="toolCallId" type="ToolCallId" required>
  A unique identifier for this tool call within the session
</ParamField>

<ParamField path="title" type="string">
  A human-readable title describing what the tool is doing. Agents **SHOULD**
  include the title the first time they report a `toolCallId`.
</ParamField>

<ParamField path="name" type="string">
  The programmatic name of the invoked tool, such as `read_file`. This
  identifies which tool is being used; `title` describes this invocation for
  users, while `kind` provides a coarse presentation category. Agents **SHOULD**
  include the name the first time they report a `toolCallId` when it is
  available.
</ParamField>

<ParamField path="kind" type="ToolKind">
  The category of tool being invoked.

  <Expandable title="kinds">
    * `read` - Reading files or data - `edit` - Modifying files or content -
      `delete` - Removing files or data - `move` - Moving or renaming files -
      `search` - Searching for information - `execute` - Running commands or code -
      `think` - Internal reasoning or planning - `fetch` - Retrieving external data
    * `other` - Other tool types (default)
  </Expandable>

  Tool kinds help Clients choose appropriate icons and optimize how they display tool execution progress.

  Custom or future tool kinds can be used when Clients can fall back to generic tool display behavior. Custom tool kinds **MUST** begin with `_`. Unknown non-underscore tool kinds are reserved for future ACP variants.
</ParamField>

<ParamField path="status" type="ToolCallStatus">
  The current [execution status](#status) (defaults to `pending`)
</ParamField>

<ParamField path="content" type="ToolCallContent[]">
  [Content produced](#content) by the tool call
</ParamField>

<ParamField path="locations" type="ToolCallLocation[]">
  [File locations](#following-the-agent) affected by this tool call
</ParamField>

<ParamField path="rawInput" type="object">
  The raw input parameters sent to the tool
</ParamField>

<ParamField path="rawOutput" type="object">
  The raw output returned by the tool
</ParamField>

The `tool_call_update` notification is an upsert keyed by `toolCallId`. For
existing tool calls, fields other than `_meta` leave the previous value
unchanged when omitted, explicitly clear or unset the value when `null`, and
replace the previous value when concrete values are sent. For a new
`toolCallId`, omitted fields use Client defaults. `content` and `locations` are
replaced as whole arrays; send `[]` or `null` to clear them. For `_meta`, omit
the field to leave it unchanged or set it to `null` to clear it. Use
`tool_call_content_chunk` when a tool produces content incrementally and the
Client should append each item instead of replacing the whole `content`
collection. Display-only terminal bytes use `terminal_output_chunk` instead.

## Updating

As tools execute, Agents send updates to report progress and results.

```json theme={null}
{
  "jsonrpc": "2.0",
  "method": "session/update",
  "params": {
    "sessionId": "sess_abc123def456",
    "update": {
      "sessionUpdate": "tool_call_update",
      "toolCallId": "call_001",
      "status": "in_progress",
      "content": [
        {
          "type": "content",
          "content": {
            "type": "text",
            "text": "Found 3 configuration files..."
          }
        }
      ]
    }
  }
}
```

All fields except `toolCallId` are optional in updates. Only the fields being changed need to be included.

## Streaming Content

As tools execute, Agents **MAY** stream individual content items with
`tool_call_content_chunk`:

```json theme={null}
{
  "jsonrpc": "2.0",
  "method": "session/update",
  "params": {
    "sessionId": "sess_abc123def456",
    "update": {
      "sessionUpdate": "tool_call_content_chunk",
      "toolCallId": "call_001",
      "content": {
        "type": "content",
        "content": {
          "type": "text",
          "text": "Found 3 configuration files..."
        }
      }
    }
  }
}
```

<ParamField path="toolCallId" type="ToolCallId" required>
  The ID of the tool call this content belongs to
</ParamField>

<ParamField path="content" type="ToolCallContent" required>
  A single [content item](#content) produced by the tool call
</ParamField>

Clients apply `tool_call_update` and `tool_call_content_chunk` notifications in
the order they are received for each `toolCallId`. A
`tool_call_content_chunk` appends its `content` item to the current tool-call
content. A later `tool_call_update` with `content` replaces all content
currently stored for that tool call, including content accumulated from earlier
chunks. Later chunks append to that replacement content. A `tool_call_update`
with `content: []` or `content: null` clears the tool-call content. A
`tool_call_content_chunk`'s `_meta`, when present, is chunk-scoped.

## Requesting Permission

The Agent **MAY** request permission from the user before proceeding with an operation, such as executing a tool call, by calling the `session/request_permission` method:

```json theme={null}
{
  "jsonrpc": "2.0",
  "id": 5,
  "method": "session/request_permission",
  "params": {
    "sessionId": "sess_abc123def456",
    "title": "Approve file edit?",
    "description": "Allow the agent to edit src/main.rs?",
    "subject": {
      "type": "tool_call",
      "toolCall": {
        "toolCallId": "call_001"
      }
    },
    "options": [
      {
        "optionId": "allow-once",
        "name": "Allow once",
        "kind": "allow_once"
      },
      {
        "optionId": "reject-once",
        "name": "Reject",
        "kind": "reject_once"
      }
    ]
  }
}
```

<ParamField path="sessionId" type="SessionId" required>
  The session ID for this request
</ParamField>

<ParamField path="title" type="string" required>
  Title shown with the permission prompt. This text is separate from any
  `toolCall` update and does not replace the tool-call title.
</ParamField>

<ParamField path="description" type="string">
  Optional explanation shown with the permission prompt. This text is separate
  from any `toolCall` update and does not replace tool-call content. Omitted or
  `null` means no separate permission description was provided.
</ParamField>

<ParamField path="subject" type="RequestPermissionSubject">
  Optional structured context about the operation requiring permission. For tool
  calls, use `type: "tool_call"` with a `toolCall` update containing details
  about the operation. Omitted or `null` means no structured subject was
  provided. Custom or future subject types may appear. Clients that do not
  understand a subject should preserve it when proxying and use the common
  prompt fields or decline according to policy.
</ParamField>

<ParamField path="options" type="PermissionOption[]" required>
  Available [permission options](#permission-options) for the user to choose
  from
</ParamField>

For a proposed command, the subject can describe the command directly:

```json theme={null}
{
  "title": "Run the test suite?",
  "subject": {
    "type": "command",
    "command": "cargo test",
    "cwd": "/home/user/project",
    "toolCallId": "call_001",
    "terminalId": "term_001"
  },
  "options": [
    {
      "optionId": "allow-once",
      "name": "Allow once",
      "kind": "allow_once"
    }
  ]
}
```

For `type: "command"`, `command` and `cwd` are required, and `cwd` **MUST** be
an absolute path. `toolCallId`, `terminalId`, and `_meta` are optional and
nullable; omission and `null` are equivalent and mean the value was not
provided. The IDs only associate the permission with displayed state and may be
unavailable before execution starts. Selecting an allow option authorizes the
Agent to execute the command; it does not ask the Client to execute anything.

The Client responds with the user's decision:

```json theme={null}
{
  "jsonrpc": "2.0",
  "id": 5,
  "result": {
    "outcome": {
      "outcome": "selected",
      "optionId": "allow-once"
    }
  }
}
```

Clients **MAY** automatically allow or reject permission requests according to the user settings.

If the current active work gets [cancelled](/protocol/v2/draft/prompt-lifecycle#cancellation), the Client **MUST** respond with the `"cancelled"` outcome:

```json theme={null}
{
  "jsonrpc": "2.0",
  "id": 5,
  "result": {
    "outcome": {
      "outcome": "cancelled"
    }
  }
}
```

<ResponseField name="outcome" type="RequestPermissionOutcome" required>
  The user's decision. Known outcomes are `cancelled` when the [active work was
  cancelled](/protocol/v2/draft/prompt-lifecycle#cancellation), and `selected`
  with an `optionId` for the selected permission option. Custom or future
  outcomes may appear; agents that do not understand the outcome MUST NOT treat
  it as approval.
</ResponseField>

### Permission Options

Each permission option provided to the Client contains:

<ParamField path="optionId" type="string" required>
  Unique identifier for this option
</ParamField>

<ParamField path="name" type="string" required>
  Human-readable label to display to the user
</ParamField>

<ParamField path="kind" type="PermissionOptionKind" required>
  A hint to help Clients choose appropriate icons and UI treatment for each option.

  * `allow_once` - Allow this operation only this time
  * `allow_always` - Allow this operation and remember the choice
  * `reject_once` - Reject this operation only this time
  * `reject_always` - Reject this operation and remember the choice

  Custom or future permission option kinds can be used as UI hints. Custom kinds **MUST** begin with `_`. Unknown non-underscore kinds are reserved for future ACP variants. Clients that do not understand a kind should preserve the value and use a generic permission option treatment.
</ParamField>

## Status

Tool calls progress through different statuses during their lifecycle:

<ResponseField name="pending">
  The tool call hasn't started running yet because the input is either streaming
  or awaiting approval
</ResponseField>

<ResponseField name="in_progress">
  The tool call is currently running
</ResponseField>

<ResponseField name="completed">
  The tool call completed successfully
</ResponseField>

<ResponseField name="failed">The tool call failed with an error</ResponseField>

<ResponseField name="cancelled">
  The tool call was cancelled before it completed
</ResponseField>

Custom or future status values can be used when Clients can display a generic progress state. Custom status values **MUST** begin with `_`; unknown non-underscore statuses are reserved for future ACP variants.

## Content

Tool calls can produce different types of content:

Tool call content `type` values can also be custom or future variants. Implementations should preserve unknown content payloads when storing, replaying, proxying, or forwarding tool calls, and otherwise render a generic content item or ignore the item if no safe display is available.

### Regular Content

Standard [content blocks](/protocol/v2/draft/content) like text, images, or resources:

```json theme={null}
{
  "type": "content",
  "content": {
    "type": "text",
    "text": "Analysis complete. Found 3 issues."
  }
}
```

### Display-only Terminals

A terminal content item references an Agent-owned terminal by ID:

```json theme={null}
{
  "type": "terminal",
  "terminalId": "term_001"
}
```

The item is only a display anchor. `terminalId` is required. Optional nullable
`_meta` is scoped to this content item; omission and `null` both mean that no
item metadata was provided. `terminalId` is unique within the session, remains
stable for the terminal's lifetime, and **MUST NOT** be reused for a different
terminal. It is independent of `toolCallId`, even when an Agent uses the same
string for both. The reference and the terminal's session updates may arrive in
either order, so Clients retain state for a first-seen `terminalId`.

Agents create and update stored terminal state with `terminal_update`:

```json theme={null}
{
  "sessionUpdate": "terminal_update",
  "terminalId": "term_001",
  "command": "cargo test",
  "cwd": "/home/user/project",
  "output": {
    "data": "cnVubmluZyB0ZXN0cw0K"
  },
  "exitStatus": {
    "exitCode": 0,
    "signal": null
  }
}
```

`terminal_update` is an upsert keyed by required `terminalId`. Other fields are
patches: omission leaves the previous value unchanged, `null` clears it, and a
concrete value replaces it. On a first-seen ID, omitted fields start unknown or
empty.

* `command` describes the command being run. Agents **SHOULD** provide it on the
  first update when applicable.
* `cwd` is the command's working directory and **MUST** be absolute when
  supplied.
* `output` is an authoritative replacement snapshot. Its required `data` is
  RFC 4648 base64-encoded bytes with JSON Schema `contentEncoding: "base64"`. A concrete
  snapshot is the complete byte sequence the Agent wants the Client to retain
  for the terminal at that point. It replaces all previously stored bytes;
  Clients **MUST NOT** merge or splice bytes from the previous snapshot into it.
  Optional nullable `output._meta` is scoped to that snapshot; omission and
  `null` both mean no snapshot metadata was provided.
* A concrete `exitStatus` marks the terminal as exited. Its optional nullable
  `exitCode` and `signal` report known exit information. Its optional nullable
  `_meta` is scoped to that exit information. For all three fields, omission
  and `null` both mean the value was not provided. Conventional POSIX signal
  names include `SIGTERM`, `SIGKILL`, and `SIGINT`; other platforms may use
  platform-specific names. Terminal exit and tool call status are independent.
* The top-level `_meta` is terminal-scoped and follows the same patch semantics.

For example, a process terminated by a POSIX termination signal can report
`"exitStatus": { "signal": "SIGTERM" }`.

For live output, Agents send `terminal_output_chunk`:

```json theme={null}
{
  "sessionUpdate": "terminal_output_chunk",
  "terminalId": "term_001",
  "data": "cGFzc2VkDQo="
}
```

`terminalId` and `data` are required. Each `data` value is an independently RFC
4648 base64-encoded byte chunk with JSON Schema `contentEncoding: "base64"`. Clients
decode each chunk separately and append the decoded bytes in received order for
that `terminalId`; they **MUST NOT** concatenate encoded strings before
decoding. Chunk boundaries may split UTF-8 code points or terminal escape
sequences, so decoders retain parser state across chunks. Optional nullable
`_meta` is chunk-scoped; omission and `null` both mean no chunk metadata was
provided.

### Diffs

File modifications shown as diffs. A diff always includes structured file
changes and can optionally include renderable patch text.

`changes` is authoritative for affected absolute paths and operations. `patch`,
when present, provides renderable text for some or all of those changes and MUST
be consistent with `changes`. Agents SHOULD provide `patch` whenever feasible.
Clients MUST handle diffs where `patch` is omitted or `null`.

```json theme={null}
{
  "type": "diff",
  "changes": [
    {
      "operation": "modify",
      "path": "/home/user/project/src/config.json",
      "fileType": "text",
      "mimeType": "application/json"
    }
  ],
  "patch": {
    "format": "git_patch",
    "text": "diff --git /home/user/project/src/config.json /home/user/project/src/config.json\n--- /home/user/project/src/config.json\n+++ /home/user/project/src/config.json\n@@ -1,3 +1,3 @@\n {\n-  \"debug\": false\n+  \"debug\": true\n }\n"
  }
}
```

<ParamField path="changes" type="DiffChange[]" required>
  Structured file changes described by this diff.
</ParamField>

<ParamField path="patch" type="DiffPatch">
  Optional renderable patch text. Agents SHOULD provide this whenever feasible.
  Omitted or `null` means no patch text was provided.
</ParamField>

<ParamField path="patch.format" type="string" required>
  Patch format. `git_patch`, the only ACP-defined value, is one or more `diff   --git` sections in Git's `--patch` (`-p`) text format. Paths MUST be absolute.
  Surrounding commit metadata and email envelopes MUST NOT be included.
</ParamField>

<ParamField path="patch.text" type="string" required>
  Renderable patch text in the format named by `patch.format`.
</ParamField>

<ParamField path="changes[].operation" type="string" required>
  File operation: `add`, `delete`, `modify`, `move`, or `copy`.
</ParamField>

<ParamField path="changes[].path" type="string" required>
  The absolute path after the operation. For deletes, this is the deleted path.
</ParamField>

<ParamField path="changes[].oldPath" type="string">
  The absolute path before the operation. Required for `move` and `copy`.
</ParamField>

<ParamField path="changes[].fileType" type="string">
  Optional file kind: `text`, `binary`, `directory`, or `symlink`.
</ParamField>

<ParamField path="changes[].mimeType" type="string">
  Optional MIME type for the file contents.
</ParamField>

Omit `patch` when there is no useful text patch, such as a same-path binary
update or symlink target change:

```json theme={null}
{
  "type": "diff",
  "changes": [
    {
      "operation": "modify",
      "path": "/home/user/project/assets/logo.png",
      "fileType": "binary",
      "mimeType": "image/png"
    }
  ]
}
```

## Following the Agent

Tool calls can report file locations they're working with, enabling Clients to implement "follow-along" features that track which files the Agent is accessing or modifying in real-time.

```json theme={null}
{
  "path": "/home/user/project/src/main.py",
  "line": 42
}
```

<ParamField path="path" type="string" required>
  The absolute file path being accessed or modified
</ParamField>

<ParamField path="line" type="number">
  Optional line number within the file
</ParamField>
