Skip to main content
A prompt starts or contributes to foreground work in a session. The Agent may continue that work until it reports idle, including across multiple model exchanges and tool invocations. session/prompt lasts until the Agent inserts the user message into the ACP conversation. This is what acceptance means for a prompt. The response returns that message’s messageId; the Agent reports its content and placement, foreground state, output, and completion through session/update notifications. Before sending prompts, Clients MUST first complete the initialization phase and 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: This is the complete set of standard variants defined in the current draft SessionUpdate schema, 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. The protocol also supports custom and future variants. Clients that do not understand an update should preserve its raw payload when storing, replaying, proxying, or forwarding session history, and otherwise ignore it or display it generically. Preserving a payload does not make it durable session history. In particular, live-only notices SHOULD NOT be replayed, even when a Client carries them through the unknown-update fallback. They may be forwarded live or retained for local diagnostics instead. Session updates are not limited to prompt-driven foreground work. For example, Agents may advertise commands after creating a session, and background activity may emit updates while the Agent is idle.

Session-directed messages (unstable)

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 session_message or session_message_chunk requires 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:
Chunks append normal message content for the same IDs. A session_message upsert may replace the whole content array or update message metadata. Omission leaves either field unchanged; null clears it. content: [] also clears accumulated content. Chunk _meta is scoped to that chunk and does not patch message metadata. 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.

Prompt Lifecycle

A typical prompt-driven flow enables rich interactions between the user, Agent, and any connected tools.

1. User Message

The Client sends a user message with session/prompt:
SessionId
The ID of the session to send this message to.
ContentBlock[]
The contents of the user message, e.g. text, images, files, etc.Clients MUST restrict types of content according to the Prompt Capabilities established during initialization.
Learn more about Content

2. Prompt Accepted

Acceptance means insertion, not receipt, queueing, or processing completion. The Agent MUST respond successfully once it has inserted the user message into the ACP conversation, without waiting for foreground work to finish. It MUST NOT send a successful response merely because it has received the input or assigned an ID. Requests rejected before insertion use a JSON-RPC error response. The response contains the inserted user message’s agent-generated messageId:
MessageId
required
The opaque ID of the inserted user message. This field is a required, non-null string; omission and explicit null are invalid.
The Agent MUST also report the inserted user message through a user_message update with the full content array or streamed user_message_chunk updates. All updates for that message MUST use the returned messageId. The response and updates describe the same insertion, but Clients MUST tolerate the updates arriving before or after the response.
The Client uses the JSON-RPC response ID to identify its submission, then associates it with (sessionId, messageId). If the message update arrived first, the Client reconciles with that existing message rather than creating a duplicate. Agents MUST assign distinct message IDs to distinct inserted submissions, even if their content is identical; Clients must not infer the association from content or arrival order. Insertion is not a promise of durable storage or model consumption. Every inserted input, including a locally handled command, is reported live, but Agents are not required to persist it or retain it for any minimum period. If the message is retained and replayed, the Agent MUST use the same ID. See Resuming Sessions. A successful prompt response is not an idle signal. Session work and notifications continue independently of the completed prompt request. If the response is lost, the submission’s outcome remains uncertain: replay may omit live-only or discarded messages, and a retry can create another submission.

3. Agent Reports Output

When foreground work starts or resumes, the Agent MUST send a state_update notification with state: "running":
The language model MAY respond with text content, tool calls, or both. 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:
Learn more about Agent Plans
The Agent can report the model’s text response as an agent_message update with the full content array:
The Agent MUST include an opaque messageId on message updates and message chunks. User, agent, and thought messages can each be reported either as a message update with a full content array or as streamed chunks. user_message, agent_message, and agent_thought updates are upserts keyed by messageId: omitted content leaves the existing message content unchanged, content: null clears it, and concrete content arrays replace the previous content. Chunk updates with the same messageId append content; a changed messageId indicates a new message. Clients apply message updates and chunks in the order they are received for each messageId:
  • A message update without content leaves the current content unchanged, so Agents can update other optional fields without resending content.
  • A message update with content replaces all content currently stored for that message, including content accumulated from earlier chunks.
  • A message update with content: [] or content: null clears the message content.
  • A chunk appends its content to whatever content is current for that message, whether that content came from an earlier message update or earlier chunks.
  • A chunk’s _meta, when present, is chunk-scoped.
For example, if an Agent sends agent_message with content: [A], then sends agent_message_chunk with B, the rendered message content is [A, B]. If it later sends another agent_message with content: [C], the rendered content becomes [C]; the earlier full content and chunks are replaced. Subsequent chunks append to [C]. For streaming agent text, the Agent can use agent_message_chunk updates:
The Agent can report internal reasoning with the same message-update or chunk patterns. agent_thought updates patch fields for the same thought messageId; agent_thought_chunk updates append new content.
If the model requested tool calls, these are also reported immediately:

Session Notices

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.
No Client capability is required in v2. Clients that do not implement notice may preserve it through the unknown-update fallback and ignore it or present it generically; this does not give it replay semantics. At any point while a session exists, including outside prompt processing, the Agent MAY send a live advisory notice:
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. Clients may ignore them, and Agents must 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

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.
No Client capability is required in v2. 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:
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. 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 at a time:
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:
The following compaction_update fields are optional, nullable patches: 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, 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, 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:
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. Report Completion

When the Agent is ready to process a new prompt, it MUST report idle with a state_update notification. When the transition ends foreground work, the Agent MUST include the corresponding StopReason:
Agents MAY stop foreground work at any point by sending an idle state_update session update with the corresponding StopReason.

5. Tool Invocation and Status Reporting

Before proceeding with execution, the Agent MAY request permission from the Client via the session/request_permission method. While foreground work is blocked on a permission response or other user action, the Agent SHOULD report requires_action. When work resumes, the Agent SHOULD report running. Once permission is granted (if required), the Agent SHOULD invoke the tool and report a status update marking the tool as in_progress:
As the tool runs, the Agent MAY send additional updates, providing real-time feedback about tool execution progress. The Agent streams complete incremental content items with tool_call_content_chunk:
Clients append each tool_call_content_chunk to the current content for that toolCallId. A later tool_call_update with content replaces the accumulated content. Display-only terminal bytes use terminal_output_chunk, not tool_call_content_chunk. See Display-only Terminals for their per-terminal byte ordering and snapshot semantics. While tools execute on the Agent, they MAY leverage Client capabilities negotiated during initialization. When the tool completes, the Agent sends another update with the final status and any content:
Learn more about Tool Calls

6. Continue Conversation

The Agent sends the tool results back to the language model as another request. The cycle returns to step 3, continuing until the language model completes its response without requesting additional tool calls or foreground work is stopped by the Agent or cancelled by the Client.

Stop Reasons

When an Agent stops foreground work, it must specify the corresponding StopReason on an idle state_update session update:
The Agent has no more work to perform after the language model finishes responding without requesting more tools
The maximum token limit is reached
The maximum number of model requests for the foreground work is exceeded
The Agent refuses to continue
The Client cancels active work
Custom or future stop reasons can be used when Clients can display a generic stopped state. Custom stop reasons MUST begin with _; unknown non-underscore stop reasons are reserved for future ACP variants.

Session States

state_update reports foreground work. For exposed subagents, Agents SHOULD also mirror the same snapshot in the immediate parent’s subagent_update.state. This keeps the parent’s roster and the child’s own stream informed about one logical state; duplicate snapshots do not represent additional work or usage.
Foreground work is in progress.
The Agent is ready to process a new prompt.
Foreground work is blocked on user action.
Draft only. The Agent cannot currently determine foreground activity. For example, a remote child feed may be lost while ACP remains connected.
Agents report unknown on actual loss of observability, not merely after silence. Clients must no longer present a prior running or requires_action as confirmed live activity, though they may retain the last-known state for context. A subsequent running, requires_action, or idle replaces unknown for the same session. unknown is neither a work outcome nor a closure or cancellation, and does not resolve pending requests or automatically revoke child mutation capabilities; the Agent updates those capabilities separately if a control becomes unavailable. Background activity MAY continue and emit other session/update notifications while the Agent reports idle. These notifications do not change the state.

Cancellation

Clients MAY cancel active session work at any time by sending a session/cancel notification:
The Client SHOULD preemptively mark all non-finished tool calls pertaining to the current active work 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 send an idle state_update session update with the cancelled stop reason.
API client libraries and tools often throw an exception when their operation is aborted, which may otherwise be surfaced as a generic failure.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 report the semantically meaningful cancelled stop reason on a state_update notification, so that Clients can reliably confirm the cancellation.
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 sending the idle state_update session update that reports cancellation. The Client SHOULD still accept tool call updates received after sending session/cancel.
After the Agent reports idle, the Client may send another session/prompt to continue the conversation, building on the established session context.