> ## Documentation Index
> Fetch the complete documentation index at: https://zed-685ed6d6-auto-sync-registry.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Prompt Turn

> Understanding the core conversation flow

A prompt turn represents a complete interaction cycle between the [Client](/protocol/v1/draft/overview#client) and [Agent](/protocol/v1/draft/overview#agent), starting with a user message and continuing until the Agent completes its response. This may involve multiple exchanges with the language model and tool invocations.

Before sending prompts, Clients **MUST** first complete the [initialization](/protocol/v1/draft/initialization) phase and [session setup](/protocol/v1/draft/session-setup).

## Session Updates

Agents send `session/update` notifications to report streamed content, tool activity, and changes to session state. The `sessionUpdate` field inside `params.update` identifies the variant:

| `sessionUpdate` value | Description |
| - | - |
| `user_message_chunk` | A streamed chunk of a user message. |
| `agent_message_chunk` | A streamed chunk of the Agent's response. |
| `agent_thought_chunk` | A streamed chunk of the Agent's reasoning. |
| `subagent_update` | **Draft only.** Announces an owned child session or updates its parent-owned metadata and work state. Requires the Client's `subagents` capability. |
| `session_message` | **Draft only.** Creates or updates a [message addressed to another session](#session-directed-messages-unstable). Requires the Client's `subagents` capability. |
| `session_message_chunk` | **Draft only.** Appends content to a [session-directed message](#session-directed-messages-unstable). Requires the Client's `subagents` capability. |
| `tool_call` | A new [tool call](/protocol/v1/draft/tool-calls#creating). |
| `tool_call_update` | A change to a [tool call's status or results](/protocol/v1/draft/tool-calls#updating). |
| `plan` | The Agent's [execution plan](/protocol/v1/draft/agent-plan). |
| `plan_update` | **Draft only.** A [content update for a plan](/protocol/v1/draft/agent-plan#plan-operations) identified by ID. Requires the Client's `plan` capability. |
| `plan_removed` | **Draft only.** [Removal of a plan](/protocol/v1/draft/agent-plan#removing-plans) identified by ID. Requires the Client's `plan` capability. |
| `available_commands_update` | The set of [available slash commands](/protocol/v1/draft/slash-commands) is ready or has changed. |
| `current_mode_update` | The current [session mode](/protocol/v1/draft/session-modes#from-the-agent) has changed. |
| `config_option_update` | The session's [configuration options](/protocol/v1/draft/session-config-options#from-the-agent) have changed. |
| `session_info_update` | [Session metadata](/protocol/v1/draft/session-list#updating-session-metadata), such as the title or last update time, has changed. |
| `usage_update` | The session's [context window usage and cumulative cost](#session-usage-updates). |
| `notice` | **Draft only.** A live [advisory notice](#session-notices) that is not part of session history. Requires the Client's `session.notices` capability. |
| `compaction_update` | **Draft only.** Creates or updates a [context compaction](#session-compaction). Requires the Client's `session.compaction` capability. |
| `compaction_summary_chunk` | **Draft only.** Appends content to a [compaction's retained summary](#session-compaction). Requires the Client's `session.compaction` capability. |

This is the complete set of variants defined in the current draft [`SessionUpdate` schema](/protocol/v1/draft/schema#sessionupdate), which describes each payload in detail. Draft-only variants are unstable and may change or be removed. The walkthrough below illustrates common uses of these updates.

Session updates are not limited to active prompt turns. For example, Agents may advertise commands after creating a session, and replay user and Agent messages when [loading a session](/protocol/v1/draft/session-setup#loading-sessions).

### Session-directed messages (unstable)

When the Client advertises `subagents: {}`, the Agent may report outgoing and
incoming messages between sessions, separately from user-facing responses and
tool calls. The outer `params.sessionId` identifies the transcript being
updated. Every message and chunk requires a `messageId` scoped to that
transcript. Optional `senderSessionId` and `recipientSessionId` metadata
identify the participants. Include them on the first update when available;
later updates may omit them or add missing identities.

For example, an incoming message in the child can begin with a streamed chunk:

```json theme={null}
{
  "jsonrpc": "2.0",
  "method": "session/update",
  "params": {
    "sessionId": "child_session",
    "update": {
      "sessionUpdate": "session_message_chunk",
      "messageId": "received_message_1",
      "senderSessionId": "parent_session",
      "recipientSessionId": "child_session",
      "content": { "type": "text", "text": "Please investigate " }
    }
  }
}
```

Every chunk carries one normal `ContentBlock`; later chunks append content
for the same `messageId`. `session_message` can supply a whole
`content` array to replace accumulated content. Its optional `content` and
`_meta` fields leave prior values unchanged when omitted; `null` clears them.
`content: []` also clears content. Chunk metadata is local to the chunk, not a
message-level patch.

Clients can render "To …" with a recipient link or "From …" with a sender link.
Without sufficient participant metadata, use a generic inter-session
presentation and add links when the metadata arrives. Omitted or `null`
participant IDs mean not supplied and leave previously known identities intact.
The two views have independent message IDs. The Agent reports each side only
when observed; Clients must not synthesize an incoming entry from an outgoing
one or forward the content themselves. Neither view acknowledges completed
recipient processing. See the [Subagent Sessions RFD](/rfds/subagents#session-directed-messages)
for participant registration, history gaps, and ownership rules.

## The Prompt Turn Lifecycle

A prompt turn follows a structured flow that enables rich interactions between the user, Agent, and any connected tools.

<br />

```mermaid theme={null}
sequenceDiagram
    participant Client
    participant Agent

    Note over Agent,Client: Session ready

    Note left of Client: User sends message
    Client->>Agent: session/prompt (user message)
    Note right of Agent: Process with LLM

    loop Until completion
        Note right of Agent: LLM responds with<br/>content/tool calls
        Agent->>Client: session/update (plan)
        Agent->>Client: session/update (agent_message_chunk)

        opt Tool calls requested
            Agent->>Client: session/update (tool_call)
            opt Permission required
                Agent->>Client: session/request_permission
                Note left of Client: User grants/denies
                Client-->>Agent: Permission response
            end
            Agent->>Client: session/update (tool_call status: in_progress)
            Note right of Agent: Execute tool
            Agent->>Client: session/update (tool_call status: completed)
            Note right of Agent: Send tool results<br/>back to LLM
        end

      opt User cancelled during execution
          Note left of Client: User cancels prompt
          Client->>Agent: session/cancel
          Note right of Agent: Abort operations
          Agent-->>Client: session/prompt response (cancelled)
      end
    end

    Agent-->>Client: session/prompt response (stopReason)

```

### 1. User Message

The turn begins when the Client sends a `session/prompt`:

```json theme={null}
{
  "jsonrpc": "2.0",
  "id": 2,
  "method": "session/prompt",
  "params": {
    "sessionId": "sess_abc123def456",
    "prompt": [
      {
        "type": "text",
        "text": "Can you analyze this code for potential issues?"
      },
      {
        "type": "resource",
        "resource": {
          "uri": "file:///home/user/project/main.py",
          "mimeType": "text/x-python",
          "text": "def process_data(items):\n    for item in items:\n        print(item)"
        }
      }
    ]
  }
}
```

<ParamField path="sessionId" type="SessionId" required>
  The [ID](/protocol/v1/draft/session-setup#session-id) of the session to send this message to.
</ParamField>

<ParamField path="prompt" type="ContentBlock[]" required>
  The contents of the user message, e.g. text, images, files, etc.

  Clients **MUST** restrict types of content according to the [Prompt Capabilities](/protocol/v1/draft/initialization#prompt-capabilities) established during [initialization](/protocol/v1/draft/initialization).

  <Card icon="comments" horizontal href="/protocol/v1/draft/content">
    Learn more about Content
  </Card>
</ParamField>

### 2. Agent Processing

Upon receiving the prompt request, the Agent processes the user's message and sends it to the language model, which **MAY** respond with text content, tool calls, or both.

### 3. Agent Reports Output

The Agent reports the model's output to the Client via `session/update` notifications. This may include the Agent's plan for accomplishing the task:

```json expandable theme={null}
{
  "jsonrpc": "2.0",
  "method": "session/update",
  "params": {
    "sessionId": "sess_abc123def456",
    "update": {
      "sessionUpdate": "plan",
      "entries": [
        {
          "content": "Check for syntax errors",
          "priority": "high",
          "status": "pending"
        },
        {
          "content": "Identify potential type issues",
          "priority": "medium",
          "status": "pending"
        },
        {
          "content": "Review error handling patterns",
          "priority": "medium",
          "status": "pending"
        },
        {
          "content": "Suggest improvements",
          "priority": "low",
          "status": "pending"
        }
      ]
    }
  }
}
```

<Card icon="lightbulb" horizontal href="/protocol/v1/draft/agent-plan">
  Learn more about Agent Plans
</Card>

The Agent then reports text responses from the model:

```json theme={null}
{
  "jsonrpc": "2.0",
  "method": "session/update",
  "params": {
    "sessionId": "sess_abc123def456",
    "update": {
      "sessionUpdate": "agent_message_chunk",
      "messageId": "msg_agent_c42b9",
      "content": {
        "type": "text",
        "text": "I'll analyze your code for potential issues. Let me examine it..."
      }
    }
  }
}
```

The Agent **MAY** include an opaque, unique `messageId` on message chunks. Chunks with the same `messageId` belong to the same message; a changed `messageId` indicates a new message.

If the model requested tool calls, these are also reported immediately:

```json theme={null}
{
  "jsonrpc": "2.0",
  "method": "session/update",
  "params": {
    "sessionId": "sess_abc123def456",
    "update": {
      "sessionUpdate": "tool_call",
      "toolCallId": "call_001",
      "title": "Analyzing Python code",
      "kind": "other",
      "status": "pending"
    }
  }
}
```

#### Session Notices

<Note>
  Session notices are a Preview feature and are available only in the draft
  schema. Their wire contract may change before stabilization. See the [Session
  Notices RFD](/rfds/session-notices).
</Note>

The Agent **MUST NOT** send `notice` updates unless the Client advertised support
by supplying `clientCapabilities.session.notices: {}` in its `initialize`
request. Omitting `session` or `notices`, or setting either field to `null`,
means the Client does not advertise support.

When the capability is absent, the Agent may use an ordinary agent message
instead if the information should still be surfaced to the user. That fallback
is conversation content and follows normal message-history semantics.

When the Client advertises support, the Agent **MAY** send a live advisory
notice at any point while a session exists, including outside prompt processing:

```json theme={null}
{
  "jsonrpc": "2.0",
  "method": "session/update",
  "params": {
    "sessionId": "sess_abc123def456",
    "update": {
      "sessionUpdate": "notice",
      "severity": "warning",
      "title": "MCP server unavailable",
      "description": "Continuing without it."
    }
  }
}
```

`severity` is required and non-null and initially supports `info`, `warning`,
and `error`.
It is an open string enum: values beginning with `_` are reserved for
implementation-specific extensions, while other unknown values are reserved
for future ACP severities. Clients preserve unknown values and use a generic
notice presentation without inferring additional behavior from them.

`title` is required, non-null, non-empty plain text suitable for a compact
presentation. `description` is optional, nullable plain text with supporting
detail; omission and `null` both mean no description. `_meta` is an optional,
nullable object scoped to this event; omission and `null` both mean no event
metadata. Unlike compaction patch fields, these fields do not update or clear
an earlier notice.

Advertising support does not acknowledge delivery or guarantee display of an
individual notice. Agents must still behave as though a notice may not have
been received, displayed, or seen. A notice must not carry information required
for protocol correctness, authorization, user action, task completion, or
fatal-error reporting.

Clients own presentation and dismissal. They may use a toast, banner, inline
status region, notification center, or another accessible surface, and may
coalesce repeated notices. Severity is only a presentation hint; even `error`
does not fail a request, stop foreground work, change session state, or imply a
prompt stop reason. Dismissal is local and produces no acknowledgement or
removal event.

Notices have no ID or Agent-managed lifecycle. Each occurrence is an
independent live event, not conversation history, and **SHOULD NOT** be included
in session replay. If a condition remains relevant after reconnecting, the
Agent may emit a new notice.

#### Session Compaction

<Note>
  Session compaction is a Preview feature and is available only in the draft
  schema. Its wire contract may change before stabilization. See the [Session
  Compaction RFD](/rfds/session-compaction).
</Note>

The Agent **MUST NOT** send `compaction_update` or
`compaction_summary_chunk` unless the Client advertised support by supplying
`clientCapabilities.session.compaction: {}` in its `initialize` request.
Omitting `session` or `compaction`, or setting either field to `null`, means the
Client does not support these updates. This requirement applies to both live
updates and history replay.

When the capability is absent, the Agent may describe compaction through an
ordinary agent message instead. That fallback is conversation content, not an
ID-addressed compaction entity, and follows normal message-history semantics.

When the Client advertises support, the Agent **MAY** report context compaction
as one persistent, ID-addressed timeline entity. It first sends
`compaction_update` and may then append retained summary content with
`compaction_summary_chunk` before sending one terminal update for the same
`compactionId`:

```json theme={null}
{
  "jsonrpc": "2.0",
  "method": "session/update",
  "params": {
    "sessionId": "sess_abc123def456",
    "update": {
      "sessionUpdate": "compaction_update",
      "compactionId": "cmp_001",
      "status": "in_progress"
    }
  }
}
```

`compactionId` and `status` are required and non-null on every
`compaction_update`. The ID is an opaque, Agent-owned string, unique within the
session, and **MUST NOT** be reused for another compaction.

The first update fixes the entity's timeline position relative to other
ID-addressed entities: it follows entities first seen earlier and precedes
entities first seen later. Later updates and chunks patch the same entity in
place; they do not move it or split another entity around it.

| `status` | Meaning |
| - | - |
| `in_progress` | Compaction has started and has not finished. |
| `completed` | Compaction finished successfully. |
| `failed` | Compaction finished unsuccessfully. |
| `cancelled` | Compaction was cancelled before it finished. |

After emitting `in_progress`, the Agent **MUST** eventually send exactly one
terminal status (`completed`, `failed`, or `cancelled`) when the compaction
ends, unless the session or connection ends before delivery. A terminal status
may be the first update during replay or when the runtime exposes only
completed compactions.

`status` is an open string enum. Values beginning with `_` are reserved for
implementation-specific extensions; other unknown values are reserved for
future ACP statuses. Clients preserve unknown strings and present a generic
state without inferring lifecycle or control behavior.

If the retained summary is available incrementally, the Agent may append one
[content block](/protocol/v1/draft/content) at a time:

```json theme={null}
{
  "jsonrpc": "2.0",
  "method": "session/update",
  "params": {
    "sessionId": "sess_abc123def456",
    "update": {
      "sessionUpdate": "compaction_summary_chunk",
      "compactionId": "cmp_001",
      "content": {
        "type": "text",
        "text": "## Retained context\n\n"
      }
    }
  }
}
```

`compactionId` and `content` are required and non-null on each chunk. Agents
**MUST** send the first `compaction_update` before any chunk for that ID and may
send chunks only after `in_progress` and before a terminal update. Chunk `_meta`
is optional and nullable, is scoped to that chunk, and has no patch semantics:
omission and `null` both mean no chunk metadata.

A completed update may omit `summary` to retain the streamed content. A
non-streaming Agent can instead supply the complete summary, and a streaming
Agent can use the same field as an authoritative final replacement:

```json theme={null}
{
  "jsonrpc": "2.0",
  "method": "session/update",
  "params": {
    "sessionId": "sess_abc123def456",
    "update": {
      "sessionUpdate": "compaction_update",
      "compactionId": "cmp_001",
      "status": "completed",
      "summary": [
        {
          "type": "text",
          "text": "## Retained context\n\nThe user is updating the ACP schema."
        }
      ]
    }
  }
}
```

The following `compaction_update` fields are optional, nullable patches:

| Field | Type | Meaning |
| - | - | - |
| `summary` | `ContentBlock[]` | The unencrypted, user-displayable content retained by compaction. A non-empty array is only valid with `completed`. |
| `error` | `string` | A human-readable failure description, only valid with `failed`. |
| `_meta` | `object` | Extensible metadata for the compaction entity. |

For each patch field, omission leaves the stored value unchanged, `null` clears
it, and a concrete value replaces it. On a first-seen ID, omission and `null`
both start with no value. `summary: []` also clears the summary.

Clients apply updates and chunks in receive order for each ID. Chunks append
to the current summary; a concrete `summary` replaces all previously
accumulated content, and any subsequent chunks append to that replacement.
`summary: null` or `summary: []` clears accumulated content, including partial
output before failure or cancellation.

The summary is not the Agent's complete replacement history or generic status
text such as "Compaction completed". It should faithfully represent the
retained, user-displayable summary without internal prompt framing or hidden
instructions. Text blocks may contain Markdown. Agents should omit it when no
unencrypted summary is available or when disclosure would reveal context that
was not otherwise user-visible.

During [history replay](/protocol/v1/draft/session-setup#loading-sessions),
Agents use materialized `compaction_update` entries with the original IDs and
timeline positions rather than replaying the transient start/chunk/finish
sequence. A completed entry includes its full summary when available, so replay
replaces rather than duplicates content the Client already holds.

Replay does not implicitly reset omitted patch fields. If a materialized entry
should clear summary content the Client already holds, the Agent sends
`summary: null` or `summary: []`; omitting `summary` retains that content.

Compaction does not instruct the Client to discard earlier conversation
history; collapsing it is a local presentation choice. It also does not replace
[`usage_update`](#session-usage-updates), which reports current context-window
utilization and cost rather than a compaction boundary.

#### Session Usage Updates

The Agent **MAY** also report current session context and cumulative cost state with a `usage_update`:

```json theme={null}
{
  "jsonrpc": "2.0",
  "method": "session/update",
  "params": {
    "sessionId": "sess_abc123def456",
    "update": {
      "sessionUpdate": "usage_update",
      "used": 53000,
      "size": 200000,
      "cost": {
        "amount": 0.045,
        "currency": "USD"
      }
    }
  }
}
```

`used` and `size` are required and non-null token counts for the current session context. `cost` is optional and, if present, `amount` and `currency` are required. `currency` is an ISO 4217 currency code like `"USD"`.

### 4. Check for Completion

If there are no pending tool calls, the turn ends and the Agent **MUST** respond to the original `session/prompt` request with a `StopReason`:

```json theme={null}
{
  "jsonrpc": "2.0",
  "id": 2,
  "result": {
    "stopReason": "end_turn"
  }
}
```

Agents **MAY** stop the turn at any point by returning the corresponding [`StopReason`](#stop-reasons).

### 5. Tool Invocation and Status Reporting

Before proceeding with execution, the Agent **MAY** request permission from the Client via the `session/request_permission` method.

Once permission is granted (if required), the Agent **SHOULD** invoke the tool and report a status update marking the tool as `in_progress`:

```json theme={null}
{
  "jsonrpc": "2.0",
  "method": "session/update",
  "params": {
    "sessionId": "sess_abc123def456",
    "update": {
      "sessionUpdate": "tool_call_update",
      "toolCallId": "call_001",
      "status": "in_progress"
    }
  }
}
```

As the tool runs, the Agent **MAY** send additional updates, providing real-time feedback about tool execution progress.

While tools execute on the Agent, they **MAY** leverage Client capabilities such as the file system (`fs`) methods to access resources within the Client's environment.

When the tool completes, the Agent sends another update with the final status and any content:

```json theme={null}
{
  "jsonrpc": "2.0",
  "method": "session/update",
  "params": {
    "sessionId": "sess_abc123def456",
    "update": {
      "sessionUpdate": "tool_call_update",
      "toolCallId": "call_001",
      "status": "completed",
      "content": [
        {
          "type": "content",
          "content": {
            "type": "text",
            "text": "Analysis complete:\n- No syntax errors found\n- Consider adding type hints for better clarity\n- The function could benefit from error handling for empty lists"
          }
        }
      ]
    }
  }
}
```

<Card icon="hammer" horizontal href="/protocol/v1/draft/tool-calls">
  Learn more about Tool Calls
</Card>

### 6. Continue Conversation

The Agent sends the tool results back to the language model as another request.

The cycle returns to [step 2](#2-agent-processing), continuing until the language model completes its response without requesting additional tool calls or the turn gets stopped by the Agent or cancelled by the Client.

## Stop Reasons

When an Agent stops a turn, it must specify the corresponding `StopReason`:

<ResponseField name="end_turn">
  The language model finishes responding without requesting more tools
</ResponseField>

<ResponseField name="max_tokens">
  The maximum token limit is reached
</ResponseField>

<ResponseField name="max_turn_requests">
  The maximum number of model requests in a single turn is exceeded
</ResponseField>

<ResponseField name="refusal">The Agent refuses to continue</ResponseField>

<ResponseField name="cancelled">The Client cancels the turn</ResponseField>

## Cancellation

Clients **MAY** cancel an ongoing prompt turn at any time by sending a `session/cancel` notification:

```json theme={null}
{
  "jsonrpc": "2.0",
  "method": "session/cancel",
  "params": {
    "sessionId": "sess_abc123def456"
  }
}
```

The Client **SHOULD** preemptively mark all non-finished tool calls pertaining to the current turn as `cancelled` as soon as it sends the `session/cancel` notification.

The Client **MUST** respond to all pending `session/request_permission` requests with the `cancelled` outcome.

When the Agent receives this notification, it **SHOULD** stop all language model requests and all tool call invocations as soon as possible.

After all ongoing operations have been successfully aborted and pending updates have been sent, the Agent **MUST** respond to the original `session/prompt` request with the `cancelled` [stop reason](#stop-reasons).

<Warning>
  API client libraries and tools often throw an exception when their operation is aborted, which may propagate as an error response to `session/prompt`.

  Clients often display unrecognized errors from the Agent to the user, which would be undesirable for cancellations as they aren't considered errors.

  Agents **MUST** catch these errors and return the semantically meaningful `cancelled` stop reason, so that Clients can reliably confirm the cancellation.
</Warning>

The Agent **MAY** send `session/update` notifications with content or tool call updates after receiving the `session/cancel` notification, but it **MUST** ensure that it does so before responding to the `session/prompt` request.

The Client **SHOULD** still accept tool call updates received after sending `session/cancel`.

***

Once a prompt turn completes, the Client may send another `session/prompt` to continue the conversation, building on the context established in previous turns.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.