Skip to main content
Author(s): @benbrandt

Elevator pitch

What are you proposing to change?
Add ID-addressed compaction_update and compaction_summary_chunk session updates to ACP v1 and v2. Agents can report when context compaction starts, update that same timeline entity when it finishes, and optionally stream or materialize the user-displayable summary retained by the compaction.

Status quo

How do things work today and what problems does this cause? Why would we change things?
ACP can report current context-window utilization through usage_update, but it cannot report that an Agent is compacting its context or preserve the resulting boundary in session history. Agents currently have to omit compaction, use an implementation-specific update, or describe it through an ordinary agent message. An agent message is the wrong semantic shape. Agent runtimes also expose different amounts of compaction information. Some provide a stable lifecycle item and a user-displayable summary, while others expose only ordered start and completion signals, an encrypted result, or a summary through an optional hook.

What we propose to do about it

What are you proposing to improve the situation?
Add compaction_update and compaction_summary_chunk to SessionUpdate in ACP v1 and v2. The first notification for an ID creates a compaction entity at that position in the session timeline. Later updates and summary chunks with the same ID update that entity in place. A single compaction_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 example, an Agent can report that compaction has started:
If the summary is available incrementally, the Agent can stream content:
The Agent finishes the same entity by reusing its ID. A non-streaming Agent can include the complete summary, while a streaming Agent can use this field as an authoritative replacement of content received so far:

Identity and lifecycle

compactionId is an opaque, Agent-owned string. It is required, non-null, unique within the session, and never reused for another compaction. Clients initialize a first-seen compaction ID with status in_progress and unset optional fields, then apply the notification. status is required and non-null on every update. Its initial values are:
  • in_progress - Compaction has started and has not finished.
  • completed - Compaction finished successfully.
  • failed - Compaction finished unsuccessfully.
  • cancelled - Compaction was cancelled before it finished.
CompactionStatus is open in both protocol versions from its introduction and follows the v2 enum-extension rules. Values beginning with _ are reserved for implementation-specific extensions, while other unknown values are reserved for future ACP statuses. Clients preserve an unknown string and present an opaque generic state without inferring lifecycle or control behavior from it. The normal transition is in_progress to a terminal status. The Agent MUST report a terminal status when a reported compaction ends. The first notification fixes the entity’s timeline position in notification receive order: it follows previously received timeline content and precedes content first received later. Later patches or chunks for an ID-addressed entity update it in place; they do not move or split it around the compaction. A Client may render an in-progress indicator and replace it with a completed, failed, or cancelled presentation when the corresponding status arrives.

Optional fields and patch semantics

The update has three optional, nullable patch fields:
  • summary is an array of ContentBlock values containing the unencrypted, user-displayable summary content produced or retained by a compaction. It should faithfully represent the retained summary while excluding internal prompt framing or instructions. Text blocks may contain Markdown. It is not generic content such as Compaction completed.
  • error is a human-readable error description.
  • _meta is reserved for extensibility and follows ACP’s existing _meta rules.
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. For summary, both null and [] clear the current content.

Streaming summary content

compaction_summary_chunk contains a required, non-null compactionId and one required, non-null ContentBlock in content. Its optional nullable _meta, when present, is scoped to that chunk; omission and null both mean that the Agent supplied no chunk metadata. Clients apply compaction_update and compaction_summary_chunk notifications in receive order for each compactionId. A chunk appends its content block to the current summary. A later compaction_update with a concrete summary array replaces all content accumulated from earlier updates and chunks; subsequent chunks append to that replacement. summary: [] or summary: null clears the accumulated content. An update may omit summary to retain the content accumulated from chunks, or include the complete summary as an authoritative replacement. Agents should omit summary when no unencrypted, user-displayable summary is available or when exposing it could reveal context that was not otherwise user-visible.

History replay

History replay uses the same update, chunk, and patch semantics as live delivery. Replay does not implicitly reset omitted fields. Agents use replacement or clearing summary patches as needed to avoid duplicating content the Client already holds. The v1 capability gate applies to replay as well as live delivery.

Version-specific capability

For v1, add an optional compaction object to ClientSessionCapabilities:
The object appears at clientCapabilities.session.compaction in the v1 initialize request. Omitting session, setting session to null, omitting compaction, or setting compaction to null all mean the Client does not advertise support. Supplying {} for compaction means the Client implements the ID, update, chunk, placement, and replay semantics in this RFD. Agents must only send compaction_update or compaction_summary_chunk to a v1 Client that advertises this capability. V2 does not add or require a capability.

Shiny future

How will things play out once this feature exists?
Users can see context compaction begin and finish at the point where it occurred. Clients can keep one stable timeline row, optionally make the retained summary expandable, and accurately reconstruct historical compaction boundaries after reconnecting. Agents no longer need to turn an internal lifecycle event into conversational text. Implementations with rich provider data can expose the summary, while implementations with only lifecycle signals remain fully conformant.

Implementation details and plan

Tell me more about your implementation. What is your detailed implementation plan?

Implemented

The initial Preview protocol implementation landed in PR #2002:
  • Both protocol versions define CompactionId, CompactionStatus, CompactionUpdate, and CompactionSummaryChunk, with compaction_update and compaction_summary_chunk variants in their SessionUpdate unions.
  • V1 defines the optional ClientSessionCapabilities.compaction capability; v2 does not require a capability.
  • Both versions preserve unknown status strings and distinguish omitted, null, and concrete patch values.

Stabilization preparation

The completion change includes compaction in stable and draft schemas and protocol guides. See the v1 guide and v2 guide. It makes compaction available unconditionally and removes the unstable_session_compaction Cargo feature. Existing consumers must remove that feature from their dependency configuration. The wire shapes and v1 capability requirement are unchanged from Preview. Protocol v2 as a whole remains opt-in through unstable_protocol_v2; completing this RFD does not stabilize protocol v2. The schema crate does not provide cross-version conversion. SDKs supporting both versions should use explicit versioned implementations or purpose-specific runtime adapters rather than schema-level conversion helpers.

Preview validation

Agent and Client implementers should add or update examples and integration tests to exercise:
  • V1 capability enforcement for both live updates and replay, including Clients that omit the capability or send null.
  • Lifecycle transitions to completed, failed, and cancelled, including runtimes that only expose completed compactions.
  • Summary chunk ordering and first-seen ID initialization, authoritative replacement and clearing, completion with an omitted summary, chunks after terminal updates, and failure or cancellation after partial output.
  • History replay without duplicating accumulated summary content after reconnecting, including v1 message chunks without IDs on either side of a compaction boundary.
  • Unknown statuses and v2 updates, and safe omission of summaries that cannot be exposed to the user.
Cross-repository Agent/Client integration tests and interoperability results are not established by this schema repository. The completion review should include implementer feedback on these behaviors; core-team approval remains the final stabilization decision.

External implementation evidence

The Claude Agent adapter provides public v1 Agent-side implementation evidence:
  • PR #1134 added experimental compaction updates and summary streaming, released in 0.78.0.
  • PR #1154 added regression coverage and terminal cleanup for interrupted compactions, released in 0.80.0. It addressed cancellations, provider failures, and other interruptions that could otherwise leave an in_progress entity unfinished.
This is evidence that an Agent exercised and refined the lifecycle contract, not proof of Client presentation, history replay, or cross-implementation interoperability. Client-side validation remains a completion-review item.

Frequently asked questions

What questions have arisen over the course of authoring this document or during subsequent discussions?

Why is the capability required in v1?

Agents currently fall back to agent text because compaction can take a while and it is useful to tell the user what is happening. The capability lets an Agent send compaction_update when the Client supports it while preserving that fallback for older v1 Clients.

Does summary contain the Agent’s complete replacement history?

No. Some runtimes retain compaction output as multiple role-bearing model history items, potentially including developer instructions, retained user messages, or encrypted provider data. summary contains only the user-displayable projection of that result as content blocks, without internal framing or hidden instructions. It is optional because some runtimes expose no safe user-displayable projection.

Why is summary a ContentBlock[]?

ACP Clients already process ContentBlock values in Agent output. Reusing that shape preserves multiple or non-text blocks when a runtime exposes them without creating another content representation. A text-only runtime sends one text block, and a runtime with no user-displayable summary omits the field. The array is still a summary artifact, not a sequence of ACP messages and not a lossless encoding of the Agent’s internal replacement history.

Why can summary be streamed?

Some runtimes produce summary text incrementally, and ACP v2 already composes append-only content chunks with authoritative replacement snapshots for messages and tool calls. Compaction follows the same pattern. Runtimes that only expose a completed result send one compaction_update.

Should the Client collapse earlier messages after compaction?

That is a local presentation choice and is not implied by this update. The Client may visually mark or group the earlier portion of the transcript, but it must retain whatever history the surrounding session and replay contracts require.

How does this interact with usage_update?

They report different facts. compaction_update records a lifecycle boundary and optional retained summary. usage_update reports current context window utilization and cost. An Agent will commonly send a lower usage value after compaction, but neither update substitutes for the other.

What alternative approaches did you consider, and why did you settle on this one?

Agent messages - They are widely renderable, but they turn protocol activity into conversation content and cannot replace one stable entity in place. Separate start and finish events - Simple to emit, but force Clients to correlate events heuristically rather than updating one ID-addressed entity.

Revision history

  • 2026-07-22: Initial draft.
  • 2026-09-23: Moved to Preview; documented the implemented protocol support and remaining integration validation.
  • 2026-10-06: Prepared completion and stabilization; included compaction in stable artifacts, removed the unstable Cargo feature, expanded schema regression coverage, and clarified receive-order timeline placement and summary patch semantics independent of compaction status.