Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion docs/docs.json
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,7 @@
"rfds/custom-llm-endpoint",
"rfds/model-config-category",
"rfds/plan-operations",
"rfds/message-id",
{
"group": "v2 Draft",
"expanded": true,
Expand All @@ -202,7 +203,6 @@
"rfds/v2/enum-variant-extension",
"rfds/v2/client-filesystem-terminal-capabilities",
"rfds/v2/plan-variants",
"rfds/message-id",
"rfds/streamable-http-websocket-transport"
]
}
Expand Down
14 changes: 10 additions & 4 deletions docs/protocol/v1/draft/schema.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -3512,7 +3512,7 @@ See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/v1/d
<ResponseField name="content" type={<a href="#contentblock">ContentBlock</a>} required>
A single item of content
</ResponseField>
<ResponseField name="messageId" type={"string | null"} >
<ResponseField name="messageId" type={<><span><a href="#messageid">MessageId</a></span><span> | null</span></>} >
**UNSTABLE**

This capability is not part of the spec yet, and may be removed or changed at any point.
Expand Down Expand Up @@ -4869,6 +4869,12 @@ See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/v1/d
Human-readable name identifying this MCP server.
</ResponseField>

## <span class="font-mono">MessageId</span>

Unique identifier for a message within a session.

**Type:** `string`

## <span class="font-mono">MultiSelectItems</span>

Items for a multi-select (array) property schema.
Expand Down Expand Up @@ -7160,7 +7166,7 @@ See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/v1/d
<ResponseField name="content" type={<a href="#contentblock">ContentBlock</a>} required>
A single item of content
</ResponseField>
<ResponseField name="messageId" type={"string | null"} >
<ResponseField name="messageId" type={<><span><a href="#messageid">MessageId</a></span><span> | null</span></>} >
**UNSTABLE**

This capability is not part of the spec yet, and may be removed or changed at any point.
Expand Down Expand Up @@ -7194,7 +7200,7 @@ See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/v1/d
<ResponseField name="content" type={<a href="#contentblock">ContentBlock</a>} required>
A single item of content
</ResponseField>
<ResponseField name="messageId" type={"string | null"} >
<ResponseField name="messageId" type={<><span><a href="#messageid">MessageId</a></span><span> | null</span></>} >
**UNSTABLE**

This capability is not part of the spec yet, and may be removed or changed at any point.
Expand Down Expand Up @@ -7228,7 +7234,7 @@ See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/v1/d
<ResponseField name="content" type={<a href="#contentblock">ContentBlock</a>} required>
A single item of content
</ResponseField>
<ResponseField name="messageId" type={"string | null"} >
<ResponseField name="messageId" type={<><span><a href="#messageid">MessageId</a></span><span> | null</span></>} >
**UNSTABLE**

This capability is not part of the spec yet, and may be removed or changed at any point.
Expand Down
2 changes: 1 addition & 1 deletion docs/protocol/v2/draft/prompt-turn.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,7 @@ The Agent then reports text responses from the model:
}
```

The Agent **MAY** include an opaque `messageId` on message chunks. Chunks with the same `messageId` belong to the same message; a changed `messageId` indicates a new message.
The Agent **MUST** include an opaque `messageId` on message chunks. Chunks with the same `messageId` belong to the same message; a changed `messageId` indicates a new message.

If the model requested tool calls, these are also reported immediately:

Expand Down
38 changes: 14 additions & 24 deletions docs/protocol/v2/draft/schema.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -3074,12 +3074,8 @@ See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/v2/d
<ResponseField name="content" type={<a href="#contentblock">ContentBlock</a>} required>
A single item of content
</ResponseField>
<ResponseField name="messageId" type={"string | null"} >
**UNSTABLE**

This capability is not part of the spec yet, and may be removed or changed at any point.

A unique identifier for the message this chunk belongs to.
<ResponseField name="messageId" type={<a href="#messageid">MessageId</a>} required>
A unique identifier for the message this chunk belongs to.

All chunks belonging to the same message share the same `messageId`.
A change in `messageId` indicates a new message has started.
Expand Down Expand Up @@ -4383,6 +4379,12 @@ See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/v2/d
Human-readable name identifying this MCP server.
</ResponseField>

## <span class="font-mono">MessageId</span>

Unique identifier for a message within a session.

**Type:** `string`

## <span class="font-mono">MultiSelectItems</span>

Items for a multi-select (array) property schema.
Expand Down Expand Up @@ -6706,12 +6708,8 @@ See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/v2/d
<ResponseField name="content" type={<a href="#contentblock">ContentBlock</a>} required>
A single item of content
</ResponseField>
<ResponseField name="messageId" type={"string | null"} >
**UNSTABLE**

This capability is not part of the spec yet, and may be removed or changed at any point.

A unique identifier for the message this chunk belongs to.
<ResponseField name="messageId" type={<a href="#messageid">MessageId</a>} required>
A unique identifier for the message this chunk belongs to.

All chunks belonging to the same message share the same `messageId`.
A change in `messageId` indicates a new message has started.
Expand Down Expand Up @@ -6740,12 +6738,8 @@ See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/v2/d
<ResponseField name="content" type={<a href="#contentblock">ContentBlock</a>} required>
A single item of content
</ResponseField>
<ResponseField name="messageId" type={"string | null"} >
**UNSTABLE**

This capability is not part of the spec yet, and may be removed or changed at any point.

A unique identifier for the message this chunk belongs to.
<ResponseField name="messageId" type={<a href="#messageid">MessageId</a>} required>
A unique identifier for the message this chunk belongs to.

All chunks belonging to the same message share the same `messageId`.
A change in `messageId` indicates a new message has started.
Expand Down Expand Up @@ -6774,12 +6768,8 @@ See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/v2/d
<ResponseField name="content" type={<a href="#contentblock">ContentBlock</a>} required>
A single item of content
</ResponseField>
<ResponseField name="messageId" type={"string | null"} >
**UNSTABLE**

This capability is not part of the spec yet, and may be removed or changed at any point.

A unique identifier for the message this chunk belongs to.
<ResponseField name="messageId" type={<a href="#messageid">MessageId</a>} required>
A unique identifier for the message this chunk belongs to.

All chunks belonging to the same message share the same `messageId`.
A change in `messageId` indicates a new message has started.
Expand Down
2 changes: 1 addition & 1 deletion docs/protocol/v2/draft/session-setup.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -175,7 +175,7 @@ Followed by the agent's response:
}
```

If the Agent provides message IDs during replay, each `messageId` is an opaque, unique identifier for the replayed message.
During replay, the Agent **MUST** include an opaque, unique `messageId` for each replayed message.

When **all** the conversation entries have been streamed to the Client, the
Agent **MUST** respond to the original `session/load` request.
Expand Down
34 changes: 34 additions & 0 deletions docs/protocol/v2/schema.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -1443,6 +1443,13 @@ See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/v2/e
<ResponseField name="content" type={<a href="#contentblock">ContentBlock</a>} required>
A single item of content
</ResponseField>
<ResponseField name="messageId" type={<a href="#messageid">MessageId</a>} required>
A unique identifier for the message this chunk belongs to.

All chunks belonging to the same message share the same `messageId`.
A change in `messageId` indicates a new message has started.

</ResponseField>

## <span class="font-mono">Diff</span>

Expand Down Expand Up @@ -1980,6 +1987,12 @@ See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/v2/e
Human-readable name identifying this MCP server.
</ResponseField>

## <span class="font-mono">MessageId</span>

Unique identifier for a message within a session.

**Type:** `string`

## <span class="font-mono">PermissionOption</span>

An option presented to the user when requesting permission.
Expand Down Expand Up @@ -2904,6 +2917,13 @@ See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/v2/e
</ResponseField>
<ResponseField name="content" type={<a href="#contentblock">ContentBlock</a>} required>
A single item of content
</ResponseField>
<ResponseField name="messageId" type={<a href="#messageid">MessageId</a>} required>
A unique identifier for the message this chunk belongs to.

All chunks belonging to the same message share the same `messageId`.
A change in `messageId` indicates a new message has started.

</ResponseField>
<ResponseField name="sessionUpdate" type={"string"} required>
The discriminator value. Must be `"user_message_chunk"`.
Expand All @@ -2927,6 +2947,13 @@ See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/v2/e
</ResponseField>
<ResponseField name="content" type={<a href="#contentblock">ContentBlock</a>} required>
A single item of content
</ResponseField>
<ResponseField name="messageId" type={<a href="#messageid">MessageId</a>} required>
A unique identifier for the message this chunk belongs to.

All chunks belonging to the same message share the same `messageId`.
A change in `messageId` indicates a new message has started.

</ResponseField>
<ResponseField name="sessionUpdate" type={"string"} required>
The discriminator value. Must be `"agent_message_chunk"`.
Expand All @@ -2950,6 +2977,13 @@ See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/v2/e
</ResponseField>
<ResponseField name="content" type={<a href="#contentblock">ContentBlock</a>} required>
A single item of content
</ResponseField>
<ResponseField name="messageId" type={<a href="#messageid">MessageId</a>} required>
A unique identifier for the message this chunk belongs to.

All chunks belonging to the same message share the same `messageId`.
A change in `messageId` indicates a new message has started.

</ResponseField>
<ResponseField name="sessionUpdate" type={"string"} required>
The discriminator value. Must be `"agent_thought_chunk"`.
Expand Down
23 changes: 14 additions & 9 deletions docs/rfds/message-id.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -114,13 +114,14 @@ For agent message chunks, the Agent also generates and includes a `messageId`:

The `messageId` field would be:

- **Optional** on `agent_message_chunk`, `user_message_chunk`, and `agent_thought_chunk` updates
- **Optional in v1** on `agent_message_chunk`, `user_message_chunk`, and `agent_thought_chunk` updates. An omitted `messageId` and an explicit `null` are equivalent and both mean the Agent did not provide a message ID for that chunk.
- **Required in v2** on `agent_message_chunk`, `user_message_chunk`, and `agent_thought_chunk` updates. The field MUST be present and MUST be a non-null string.
- **Agent-generated** - the Agent is the only participant that creates protocol message IDs
- **Unique per message** within a session
- **Stable across chunks** - all chunks belonging to the same message share the same `messageId`
- **Opaque** - Implementations treat it as an identifier without parsing its structure

If an Agent supports message IDs and emits an accepted or replayed user message through `session/update`, it SHOULD include `messageId` on that user message update.
In v1, if an Agent supports message IDs and emits an accepted or replayed user message through `session/update`, it SHOULD include `messageId` on that user message update. In v2, every streamed user, agent, and thought message chunk MUST include a `messageId`.

## Shiny future

Expand Down Expand Up @@ -168,11 +169,14 @@ Example future editing capability:
### Phase 1: Core Protocol Changes

1. **Update schema** (`schema/schema.json`):
- Add optional `messageId` field (type: `string`) to `ContentChunk` (used by `AgentMessageChunk`, `UserMessageChunk`, `AgentThoughtChunk`)
- Add optional `messageId` field (type: `string`) to v1 `ContentChunk` (used by `AgentMessageChunk`, `UserMessageChunk`, `AgentThoughtChunk`)
- Add required `messageId` field (type: `string`) to v2 `ContentChunk`

2. **Update Rust SDK** (`rust/client.rs` and `rust/agent.rs`):
- Add `message_id: Option<String>` field to `ContentChunk` struct
- Update serialization to include `messageId` in JSON output when present
- Add a dedicated `MessageId` newtype
- Add `message_id: Option<MessageId>` field to the v1 `ContentChunk` struct
- Add `message_id: MessageId` field to the v2 `ContentChunk` struct
- Update serialization to include `messageId` in JSON output when present for v1 and always for v2

3. **Update TypeScript SDK** (if applicable):
- Add `messageId` field to corresponding session update types
Expand All @@ -195,9 +199,9 @@ Example future editing capability:

### Backward Compatibility

The `messageId` field is **optional** to ensure this is a non-breaking change. Agents SHOULD include the `messageId` field on message chunks they can identify, but it is not required for v1 compatibility. Features that rely on `messageId` (such as future message editing capabilities) will implicitly require the field to be present - Agents that don't provide it simply won't support those features.
The `messageId` field is **optional in v1** to ensure this is a non-breaking change. Agents SHOULD include the `messageId` field on message chunks they can identify, but it is not required for v1 compatibility. Features that rely on `messageId` (such as future message editing capabilities) will implicitly require the field to be present - Agents that don't provide it simply won't support those features.

Making this field required will be considered for a future v2 version of the protocol after wide adoption.
The field is **required in v2**, where breaking protocol changes are allowed. v2 agents MUST include `messageId` on every streamed message chunk, and v2 clients can reject chunks where the field is omitted or `null`.

## Frequently asked questions

Expand Down Expand Up @@ -245,9 +249,9 @@ This matches other protocol identifiers (`sessionId`, `terminalId`, `toolCallId`

### Should this field be required or optional?

The field is **optional** for v1 to ensure backward compatibility. Agents SHOULD include `messageId`, but it is not required. Features that depend on `messageId` (such as message editing) will implicitly require it - if an Agent doesn't provide `messageId`, those features simply won't be available.
The field is **optional** for v1 to ensure backward compatibility. Agents SHOULD include `messageId`, but it is not required. In v1, omitting `messageId` and sending `null` are equivalent and both mean no message ID was provided.

Making this field required will be considered for a future v2 version of the protocol.
The field is **required** for v2. The key MUST be present and its value MUST be a non-null string.

### What format should message IDs use?

Expand Down Expand Up @@ -278,6 +282,7 @@ Future RFDs may propose extending `messageId` to other update types if use cases

## Revision history

- **2026-06-03**: Moved the RFD out of the v2 Draft group while keeping v2-specific behavior; added a dedicated `MessageId` type, and made v2 require message IDs on streamed message chunks while v1 keeps optional message IDs for compatibility
- **2026-06-02**: Updated the proposal so message IDs are Agent-generated only, removed client-provided prompt IDs and prompt response acknowledgments, and removed the UUID requirement in favor of opaque strings
- **2026-02-17**: Added "Message ID Acknowledgment" section to clarify that presence/absence of `userMessageId` in response indicates whether the Agent recorded the ID; clarified that UUID format is MUST (not SHOULD) since both sides generate IDs; renamed response field to `userMessageId` for clarity (request keeps `messageId`)
- **2026-01-29**: Updated to allow both clients and agents to generate message IDs using UUID format
Expand Down
3 changes: 1 addition & 2 deletions docs/rfds/v2/overview.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,6 @@ Current RFDs accepted as Drafts that are targeting v2 release
- [Enum Variant Extension](./enum-variant-extension.mdx)
- [Client Filesystem and Terminal Surface](./client-filesystem-terminal-capabilities.mdx)
- [Plan Variants](./plan-variants.mdx)
- [Message IDs](../message-id.md)
- [Fork from specified IDs](../session-fork.mds)
- [Remote Transports](../streamable-http-websocket-transport.mdx)

Other RFDs will progress separately and are not dependent on breaking changes (specifically the new prompt lifecycle) and can land in either or both v1 and v2.
Expand All @@ -44,6 +42,7 @@ Other RFDs will progress separately and are not dependent on breaking changes (s
- Agents should expose mode-like and model-related state through [Session Config Options](../session-config-options.mdx) instead of dedicated mode or model selector APIs.
- Remove the v1 Client filesystem and terminal execution surface from v2. This includes `clientCapabilities.fs`, the top-level `clientCapabilities.terminal` field, `fs/*` methods, `terminal/*` methods, and terminal tool-call content. Terminal authentication remains separate under `clientCapabilities.auth.terminal`.
- Make [plan variants](./plan-variants.mdx) the default v2 plan shape by replacing the old `plan` session update with item-based `plan_update`.
- Require [message IDs](../message-id.mdx) on streamed message chunks.
- Follow JSON-RPC 2.0 batch request and notification behavior.

### RFDs to be Written
Expand Down
4 changes: 2 additions & 2 deletions docs/rfds/v2/prompt.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ The agent will respond once the prompt has been _accepted_, not when the turn is
}
```

Given there will need to be some more exploration for Message IDs in general, I won't tie that RFD to this one unnecessarily. The accepted user message notification becomes the natural point to provide the ID if the agent has one.
Given there will need to be some more exploration for Message IDs in general, I won't tie that RFD to this one unnecessarily. The accepted user message notification becomes the natural point to provide the required v2 message ID.

Queueing messages (still an ongoing discussion) would also fit much nicer in this pattern. Either by adding additional parameters or a separate method, we can allow a client to submit queued messages and either cancel or edit them before they get accepted without having to mess with the turn semantics of the previous prompt request approach. Again, queueing is decidedly not part of this RFD, but it seems to fall more naturally into this semantic change in the prompt request.

Expand Down Expand Up @@ -119,7 +119,7 @@ And also send the notification:
}
```

The client can then make sure the prompt sits nicely in the feed at the right place, and also allows for multiple clients to be attached to the same session because they would receive a user message that they didn't prompt. If the agent includes a `messageId` in that notification, the client can use that agent-provided ID for future message-specific operations.
The client can then make sure the prompt sits nicely in the feed at the right place, and also allows for multiple clients to be attached to the same session because they would receive a user message that they didn't prompt. The agent-provided `messageId` in that notification gives the client the ID for future message-specific operations.

This is a new message type as well. Not a `user_message_chunk` but just a `user_message` that allows for sending the entire message at once. For v2 we will make sure to allow for the agent to do the same on their messages as well, providing both full and partial streaming update patterns for a given message.

Expand Down
Loading