Skip to content

new RFD: Create agent_message_clear.md#465

Open
steve02081504 wants to merge 7 commits intoagentclientprotocol:mainfrom
steve02081504:main
Open

new RFD: Create agent_message_clear.md#465
steve02081504 wants to merge 7 commits intoagentclientprotocol:mainfrom
steve02081504:main

Conversation

@steve02081504
Copy link
Contributor

@steve02081504 steve02081504 commented Feb 6, 2026

Elevator pitch

The current Agent Communication Protocol (ACP) treats agent_message_chunk as a strictly append-only operation. This proposal introduces a new session update type, agent_message_clear, which allows agents to clear the accumulated streamed content. This enables support for non-monotonic streaming scenarios—such as iterative refinement, post-processing, and speculative decoding—without causing UI clutter or redundant message history.

Status quo

Currently, the agent_message_chunk session update is strictly cumulative. The client concatenates all received chunks into the agent's message with no mechanism to clear or replace what has already been streamed. This is problematic for agents where content generation is non-monotonic:

  1. Post-processing / reformatting: Backends applying progressive Markdown rendering or XML tag balancing may need to reformat intermediate text.
  2. Delegating agent frameworks: Frameworks like fount receive full accumulated states rather than deltas. When internal processing occurs (e.g., hiding tool-calls), the new state is no longer a simple prefix of the old one.
  3. Iterative Refinement & Diffusion-based Models: These models refine entire text blocks over multiple steps rather than generating tokens linearly.
  4. Speculative decoding with rollback: Inference engines may need to retract tokens if a drafted branch is rejected.
  5. Display vs. Context Divergence: An agent might stream a simplified preview and wish to replace it with a final richly-formatted version.

Current Workarounds:

  • Separator & Re-push: Agents append a visual separator (like ---) and re-send the entire text. This causes UI clutter, flicker, and massive context waste in transcripts.
  • Non Stream: Agents stop streaming until the full text done. This makes the UI feel "frozen" or laggy.

What we propose to do about it

We propose adding a new session update type: agent_message_clear.

This update instructs the client to immediately clear the accumulated streamed content for the current agent message in the given session. Subsequent agent_message_chunk updates will then start appending from an empty state. (The ACP spec already supports multiple sessions on the same connection via repeated session/new; all session-scoped notifications and methods carry a sessionId, so "current" is unambiguous per session.)

Key characteristics:

  • Simplicity: It follows the existing "full-replacement" semantics found in plan updates and tool_call_update content.
  • Minimal Scope: It introduces a single new SessionUpdate variant without changing existing logic.
  • Graceful Degradation: Clients that do not recognize this update will ignore it, defaulting to the current (concatenated) behavior.

Shiny future

In the shiny future, agent UIs will be fluid and reactive.

  • Clean Recovery: If an agent makes a "mistake" in its stream or needs to reformat a table on the fly, it can do so invisibly to the user's permanent history.
  • Next-Gen Support: ACP will natively support diffusion-style language models that "paint" or "de-noise" a response over time.
  • Framework Harmony: Developers using high-level frameworks (like fount) can push full-state updates safely, knowing the protocol handles the "reset" efficiently.
  • Optimized Context: Chat transcripts will remain concise and readable, free of "Separator & Re-push" artifacts.

Implementation details and plan

Protocol Change

Add agent_message_clear to the SessionUpdate variant list. When message IDs are in use (unstable today), the update may include an optional messageId to clear a specific message; otherwise it clears the current message in the session.

JSON-RPC Example (clear current message):

{
  "jsonrpc": "2.0",
  "method": "session/update",
  "params": {
    "sessionId": "sess_abc123",
    "update": {
      "sessionUpdate": "agent_message_clear"
    }
  }
}

With optional messageId (when message ID is supported):

{
  "jsonrpc": "2.0",
  "method": "session/update",
  "params": {
    "sessionId": "sess_abc123",
    "update": {
      "sessionUpdate": "agent_message_clear",
      "messageId": "msg_uuid_here"
    }
  }
}

Usage Pattern

  1. Agent sends agent_message_chunk with text "Drafting...".
  2. Agent determines the draft needs replacement.
  3. Agent sends agent_message_clear.
  4. Agent sends agent_message_chunk with the final, polished content.

Implementation Plan

  1. Phase 1: Update the ACP schema to include agent_message_clear.
  2. Phase 2: Implement handling in reference clients to clear the local buffer for the active message.
  3. Phase 3 (Optional): Consider adding agent_thought_clear if agents require similar non-monotonic behavior for internal reasoning blocks.

Frequently asked questions

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

Several designs were evaluated:

Design Reason for Rejection
agent_message_replace While atomic, it requires a new content structure and results in very large payloads for long messages if sent frequently.
replace: true flag Overloads the existing chunk type and makes partial-replace semantics ambiguous.
Offset-based patching While bandwidth-efficient, it introduces significant complexity for both agent developers and client implementers (similar to Operational Transforms).

agent_message_clear was chosen because it is the most consistent with existing ACP patterns (like plan updates) and provides the best balance between implementation simplicity and functional power.

How does this affect backward compatibility?

It is fully backward-compatible. A legacy client will simply ignore the unknown agent_message_clear notification. The result is that the user sees the old text and new text concatenated, which is identical to the current "Separator" workaround.

Does this replace the entire message history?

No. It only clears the "accumulated streamed content" of the current active agent message in the session. It does not affect previously finalized messages in the chat history.

What about message IDs and "replace by id"?

The spec already has message IDs (currently unstable): agent_message_chunk and related updates can carry an optional messageId; see the Message ID RFD and schema.unstable.json. Review feedback suggested building on this so we know which message to clear, and an alternative design: allow agent_message (full message) in addition to agent_message_chunk, with an id—when the client sees a full message with an existing id, it would replace all previous chunks/text for that id, similar to tool call updates.

This RFD should align with that existing mechanism: agent_message_clear can take an optional messageId; when present, the client clears the accumulated content for that message id; when absent, it clears the "current" message (same as today's implicit semantics). That way we build on top of the new message ids as suggested. The "full agent_message with id for replace" design remains a viable alternative or future extension.

Revision history

  • 2026-02-07: Initial draft by steve02081504.
  • 2026-03-15: Updated per review: multi-session clarification; build on existing (unstable) message IDs; optional messageId on agent_message_clear; replace-by-id alternative noted.

@steve02081504 steve02081504 requested a review from a team as a code owner February 6, 2026 13:31
steve02081504 added a commit to steve02081504/python-sdk that referenced this pull request Mar 1, 2026
steve02081504 added a commit to steve02081504/kotlin-sdk that referenced this pull request Mar 1, 2026
Copy link
Member

@benbrandt benbrandt left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I feel like this should build on top of the new message ids so we know which to clear.

Another option would be to allow for agent_message in addition to agent_message_chunk with an id and if we see a full message with an existing id it would replace all previous chunks/text for that id, similar to tool calls.

thoughts?

@steve02081504
Copy link
Contributor Author

I feel like this should build on top of the new message ids so we know which to clear.

Another option would be to allow for agent_message in addition to agent_message_chunk with an id and if we see a full message with an existing id it would replace all previous chunks/text for that id, similar to tool calls.

thoughts?

I don't think the existing ACP spec has the concept of message IDs yet — currently a single stdio link can only correspond to one agent session, so messages are inherently unique.
Discussing a new feature like this in the RFD feels a bit out of scope for now.
That said, if ACP ever expands to let a single client support multiple concurrent conversations, I’m 100% on board with adding message IDs and I’d happily vote with both hands and both feet :D

@benbrandt
Copy link
Member

The spec already supports multiple sessions on the same connection. In fact we are now using this in Zed, and all of the agents as far as I know support it.

You can call session/new multiple times and all notifications + session related methods require a session id

@steve02081504
Copy link
Contributor Author

The spec already supports multiple sessions on the same connection.

coool, good to know :D

@steve02081504 steve02081504 requested a review from benbrandt March 15, 2026 15:47
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Draft Proposal

Development

Successfully merging this pull request may close these issues.

3 participants