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 sendsession/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
SessionUpdate schema, which describes each payload in detail. 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.
Live-only notices SHOULD NOT be replayed, even when
preserved as unknown updates.
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.
Entity IDs
Messages, tool calls, terminals, and plans are entities that the Agent creates and then updates by ID across multiple session updates. An entity is identified by its type together with its ID, not by its ID alone:
An ID is unique among entities of the same type within a session, not across all entity types, so the same string can identify one entity of each type. User messages, Agent messages, and Agent thoughts are separate types even though they share the
messageId field. For example, an Agent may report a thought and a response derived from the same model output with the same messageId; they remain two distinct entities.
The Agent MUST NOT reuse an ID for a different entity of the same type within a session. Clients MUST key entities by both type and ID. An update applies only to the entity of its own type: an agent_thought whose messageId matches an existing Agent message creates or updates a thought and leaves the message unchanged. Likewise, a field that references an entity identifies an entity of one specific type; for example, the messageId returned by session/prompt identifies a user message.
Foreground and Background Work
Foreground work is the Agent’s active response or workflow in the session, including model processing, tool execution, and waiting for user action needed to continue that work. The Agent MUST treat that work as foreground whether it was started by a user prompt or by the Agent, for example to pursue an ongoing goal, continue earlier work, or act on a completed background task. Background activity runs independently of the active response or workflow. A detached task continuing to run, its progress or completion updates, and session metadata updates do not by themselves start foreground work. If the Agent begins a response or workflow to act on a background result, that work is foreground work. The same lifecycle requirements apply regardless of what started foreground work:- The Agent MUST report
runningwhen foreground work starts or resumes. - While foreground work is blocked on user action, the Agent SHOULD report
requires_action. - When foreground work ends, the Agent MUST report
idle, even if background activity continues, and SHOULD include the corresponding stop reason.
session/prompt request or a synthetic user message. State updates describe the session’s foreground work, not individual model exchanges, tool calls, or prompt requests.
For example, when a background task completes and the Agent starts a follow-up response:
requires_action. If it belongs only to independent background activity, the session may remain idle. Resolving a permission request does not itself imply running: the Agent MUST report running if foreground work starts or resumes as a result. See Requesting Permission.
Prompt Lifecycle
A typical prompt-driven flow enables rich interactions between the user, Agent, and any connected tools. The diagram shows one possible ordering; see Insertion and ordering.1. User Message
The Client sends a user message withsession/prompt:
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: the Agent has logically added a user message to the ACP conversation, with amessageId and a position relative to other messages. Receipt, queueing, and assigning an ID are not insertion.
The Agent MUST respond successfully once the message is inserted, without waiting for foreground work to finish, and MUST NOT do so before insertion. Once inserted, it MUST NOT return an error response, even if failure or request cancellation occurs before the response is sent. It returns the messageId; subsequent work outcomes are reported as described in Failures and Cancellation.
An adapter can use a runtime’s user-message echo or insertion event as evidence of insertion. For a locally handled command that the runtime does not record, it can instead insert a live-only ACP user message.
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.user_message update with the full content array or streamed user_message_chunk updates. All updates for that message MUST use the returned messageId and MUST NOT precede insertion. Clients MUST tolerate the updates arriving before or after the response.
(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.
The same insertion boundary applies when closing the session cancels a pending prompt: if closing prevents insertion, the request receives -32800 (Request Cancelled); if the message has already been inserted, it receives a successful messageId response. Prompt responses need not precede the close response.
Insertion and ordering
running reports foreground work, not insertion. It may precede insertion, the prompt response, and user-message updates, for example while a foreground hook runs. It does not acknowledge a pending prompt’s insertion.
Prompts that are never inserted
If a request is rejected before insertion, including by a hook or early failure, the Agent MUST return a JSON-RPC error response and MUST NOT emit user-message updates for that submission. Request cancellation before insertion uses-32800.
The foreground lifecycle applies independently of the request outcome: report idle when no foreground work remains, not merely because a prompt was rejected. A failed foreground hook can therefore require both a prompt error response and an idle update. If no foreground work started, rejection requires no state transition.
3. Agent Reports Output
When foreground work starts or resumes, the Agent MUST send astate_update notification with state: "running":
session/update notifications. This may include the Agent’s plan for accomplishing the task:
Learn more about Agent Plans
agent_message update with the full content array:
Message IDs
The Agent MUST include an opaquemessageId 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
contentleaves the current content unchanged, so Agents can update other optional fields without resending content. - A message update with
contentreplaces all content currently stored for that message, including content accumulated from earlier chunks. - A message update with
content: []orcontent: nullclears the message content. - A chunk appends its
contentto 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.
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:
agent_thought updates patch fields for the same thought messageId; agent_thought_chunk updates append new content.
Session Notices
No Client capability is required in v2. Clients that do not implementnotice
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 user-facing 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
No Client capability is required in v2. The Agent MAY report context compaction as one persistent, ID-addressed timeline entity. A singlecompaction_update with status: "completed" is
sufficient; reporting progress is optional. Summary content is also optional.
It may be sent all at once in the summary field or streamed using
compaction_summary_chunk for the same compactionId.
For example, an Agent can report that compaction has started:
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.
Clients initialize a first-seen compaction ID with status in_progress and unset
optional fields, then apply the notification.
The first notification fixes the entity’s timeline position in receive
order: it follows previously received timeline content and precedes content
first received later. Later updates and chunks for an ID-addressed entity patch
it in place; they do not move or split it around the compaction.
The Agent MUST report a terminal status when a reported compaction ends.
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.
Chunk _meta is optional and nullable, is scoped to that chunk, and has no
patch semantics: omission and null both mean no chunk metadata.
An 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 replacement of content received
so far:
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,
compaction updates and summary chunks follow the same semantics as live delivery.
Replay does not implicitly reset omitted patch fields. Agents use replacement
or clearing summary patches as needed to avoid duplicating content the Client
already holds.
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 ausage_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 foreground work ends, the Agent MUST reportidle with a state_update notification and SHOULD include the corresponding StopReason:
state_update session update. They SHOULD include the corresponding StopReason.
5. Tool Invocation and Status Reporting
Before proceeding with execution, the Agent MAY request permission from the Client via thesession/request_permission method.
While foreground work is blocked on a permission response or other user action, the Agent SHOULD report requires_action. When foreground work resumes, the Agent MUST report running. A permission request for independent background activity does not by itself change the foreground state; see Foreground and Background Work.
Once permission is granted (if required), the Agent SHOULD invoke the tool and report a status update marking the tool as in_progress:
tool_call_content_chunk:
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.
Tools execute on the Agent. Clients may expose tools through MCP servers supplied during session setup. v2 does not define Client file-system or terminal-execution capabilities. Client interactions such as elicitation remain subject to their own negotiated capabilities.
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 SHOULD specify the correspondingStopReason on an idle state_update session update. If the Agent knows it is idle but cannot determine why the work stopped, it may omit the stop reason. Clients MUST recognize idle as the end of foreground work even when the stop reason is omitted, null, malformed, or unknown; without a recognized stop reason, Clients cannot infer how the work ended.
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
_; unknown non-underscore stop reasons are reserved for future ACP variants.
Failures
When foreground work ends because something failed, the Agent MUST reportidle and SHOULD include the error stop reason. This includes pre-insertion work and failures before any model output. The prompt’s response still follows the insertion boundary. This stop reason carries the failure in an error field beside stopReason, which the Agent SHOULD include:
Error
The failure that ended foreground work, as a JSON-RPC error object with
required
code and message and optional data. Optional and nullable:
omission and null both mean the Agent supplied no failure details.error belongs to the error stop reason; beside any other stop reason it is an unknown field. Clients may show message to the user and can handle code as they would for an error response: for example, -32000 (authentication required) can prompt the user to authenticate before sending another prompt.
Before reporting the failure, the Agent SHOULD give each tool call that the failed work left unfinished a terminal status, using failed for calls that did not complete. A failure does not undo the insertion or any side effects the work already had, such as tools that ran. Sending the prompt again submits a new message.
The error stop reason is only for failures that end foreground work:
- A failure before the user message is inserted requires a JSON-RPC error response to
session/prompt, whether or not it also ends foreground work. - A failure the Agent recovers from while work continues, such as a retried model request or a failed tool call, is reported with a notice or a tool call whose status is
failed, and does not change the state. - Errors raised while aborting cancelled work are reported with the
cancelledstop reason, as described in Cancellation. - A failure in background activity while the Agent is
idleis not a stop reason, since no foreground work ended.
Session States
state_update reports foreground work, whether or not a prompt started it.
Foreground work is in progress.
No foreground work is active. Background activity may continue.
Foreground work is blocked on user action.
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 asession/cancel notification:
-32800 as described in request cancellation. Once the message is inserted, the prompt request still succeeds with its messageId; cancellation does not undo that insertion.
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.
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.