Elevator pitch
What are you proposing to change?ACP v2 should support both whole-message updates and streamed message chunks for user messages, agent messages, and agent thoughts. Whole-message updates are upserts keyed by
messageId, while chunks append content to the message with the matching messageId.
Status quo
How do things work today and what problems does this cause? Why would we change things?ACP v1 primarily reports user, agent, and thought messages as chunks:
messageId.
What we propose to do about it
What are you proposing to improve the situation?ACP v2 should define whole-message session updates:
user_messageagent_messageagent_thought
messageId:
messageIdis required.contentand_metaare patch fields.- An omitted patch field leaves the previous value unchanged.
nullexplicitly clears or unsets the field.- Any concrete value replaces the previous value.
contentis replaced as a whole array, not appended.[]andnullboth clearcontent.- For a new
messageId, omitted fields use Client defaults.
user_message_chunkagent_message_chunkagent_thought_chunk
content item to the current content of the message with the matching messageId.
Interaction between updates and chunks
Clients apply message updates and chunks in the order they are received for eachmessageId.
If a message update includes content, that content array replaces all content currently stored for the message, including content accumulated from earlier chunks:
[C].
If chunks arrive after a message update, they append to the update’s current content:
[A, B].
If a message update omits content, it does not change the current content. This lets Agents update _meta or future optional fields without resending the whole content array:
Shiny future
How will things play out once this feature exists?Agents can choose the reporting style that matches the data they have:
- use whole-message updates for replay, accepted user messages, and already-complete model output;
- use chunks for streaming output;
- combine both when an Agent needs to seed content and then stream more, or correct/replace content after streaming.
Implementation details and plan
Tell me more about your implementation. What is your detailed implementation plan?
- Add the
user_message,agent_message, andagent_thoughtsession update variants to v2. - Require
messageIdon whole-message updates and chunks. - Represent
contentand_metaas three-state patch fields so omitted,null, and concrete values can be distinguished. - Document ordering semantics between whole-message updates and chunks in the protocol docs.
- Convert content-bearing whole-message updates to v1 by fanning out one v1 chunk per content block. This is equivalent only when the v1 side has not already received content for that
messageId; v1 has no way to replace earlier chunks. Patch-only updates,content: null,content: [], and_meta: nullcannot be represented by v1 chunks and should fail conversion rather than silently dropping the update.
Frequently asked questions
What questions have arisen over the course of authoring this document or during subsequent discussions?
Why are message updates upserts instead of required full snapshots?
Upserts let Agents update_meta or future optional message fields without resending the whole content array.
Why does content replace instead of append?
Appending is already represented by chunks. A whole-message update needs to be able to replay, correct, or replace the current content for a message. Making content a replacement array gives each update type a distinct behavior: message updates replace fields, chunks append content.
What happens when a message update arrives before any chunks?
The Client creates or updates the message for thatmessageId. Later chunks with the same messageId append to the current content.
What happens when chunks arrive before a message update?
The Client appends those chunks to the message for thatmessageId. A later message update with content replaces the accumulated content.
Revision history
- 2026-06-09: Initial draft.