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 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 outerparams.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:
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 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, 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-generatedmessageId:
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. The response and updates describe the same insertion, but 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.
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:
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
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
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.
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.
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:
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 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 the Agent is ready to process a new prompt, it MUST reportidle with a state_update notification. When the transition ends foreground work, the Agent MUST include the corresponding StopReason:
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 thesession/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:
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.
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 correspondingStopReason 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
_; 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.
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 asession/cancel notification:
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.