Skip to content

Commit bf35ca1

Browse files
benbrandtclaude
andauthored
docs: reconcile v1.15 spec text, unstable RFDs and the proxy-chains RFD (#2743)
* docs(schema): restore the v1 meaning of Implementation.title and the tool-call intro The plain-language pass (#2730) changed two v1 passages beyond wording: - `Implementation.title` said it "should be readable by people", which adds a should-statement to the stable v1 spec and schema. Restore the v1.14.0 meaning ("optimized to be human-readable and easily understood") without the em dash. The v2 copy uses the same text. - The v1 tool-calls intro said Agents may use Client capabilities "while running a tool call", which reads as a new timing limit. Drop the temporal clause and keep the original "or". Co-Authored-By: Claude <noreply@anthropic.com> * docs(protocol): align v2 session/cancel text with the background-work rules #2738 narrowed `session/cancel` so listed background work keeps running and its permission requests stay open, but several v2 passages still stated the old rule. Update them in the stable and draft pages and the v2 schema: - prompt-lifecycle: add the missing "or" in the announce-before-listing rule (stable only, the draft already had it), scope "stop all tool call invocations" to the cancelled foreground work, put the `-32800` rule next to the prompts it covers, and state that a `subject` the Client does not recognize, such as a custom subject type, is answered with `cancelled`. - tool-calls, cancellation, migration: answer pending permission requests for the cancelled foreground work, not every request in the session. - Schema: `RequestPermissionOutcome::Cancelled`, the `session/request_permission` request and the `session/cancel` notification descriptions now state the narrowed rule and the custom subject case. Co-Authored-By: Claude <noreply@anthropic.com> * docs(unstable): reconcile session/status, auth/status and session/set_title with their RFDs - session/status: keep `-32002` for sessions the Agent does not know, and state the RFD's exception in the schema, the draft error pages and the RFD's own error rule: an Agent that cannot cheaply tell a saved session from an unknown one may return `saved`, and the later resume or load gets `-32002`. - auth/status: add it to the draft v2 list of requests that do not fail with `auth_required`, and put the RFD's MUST NOT in the schema. - session/set_title: refusing a session the Agent cannot safely update returns `-32602`, as an explicit exception to retitling any listed session, in the schema, the draft error pages and the RFD. Co-Authored-By: Claude <noreply@anthropic.com> * docs(rfd): resolve proxy-chains ambiguities and match the reference conductor Define, in the proxy-chains RFD and the proxy schema descriptions: - Errors the conductor returns itself (before initialization, failed chain start, `proxy/initialize` from outside, misplaced `proxy/successor`, malformed envelopes, a component that exited), separate from the pass-through rule for wrapped results. - Hop-local cancellation: `$/cancel_request` names a request on its own connection, is never forwarded, and each hop re-issues it. - Envelope `_meta` is hop-local and not copied into the unwrapped message. - Version selection along the chain, the proxy's obligation to forward `initialize` before answering, the proxy/initialize result built from the successor's (same `protocolVersion`), and repeated `proxy/initialize`. - "Unchanged" results and errors mean the same JSON value. - Wrapped `params` is an object, an array, or `null`. - Forwarding of unknown requests and notifications and where `-32601` comes from. Also link version negotiation for v1 and v2, replace the old `sacp-conductor` name, drop crash-handling claims the reference conductor does not implement, and add a revision-history entry. Co-Authored-By: Claude <noreply@anthropic.com> * docs(unstable): drop the saved-for-unknown and retitle-refusal exceptions Co-Authored-By: Claude <noreply@anthropic.com> * docs(protocol): let the Agent cancel permission requests on session/cancel in v2 The Agent knows which work each permission request belongs to, so on session/cancel it stops waiting for the cancelled work's requests and cancels them with $/cancel_request, as it already does for elicitations. Clients MAY answer them early. session/close cancels every pending permission request the same way. This removes the subject-based rules for which requests the Client answers. Co-Authored-By: Claude <noreply@anthropic.com> --------- Co-authored-by: Claude <noreply@anthropic.com>
1 parent 8fed1ac commit bf35ca1

31 files changed

Lines changed: 297 additions & 171 deletions

‎agent-client-protocol-schema/src/v1/agent.rs‎

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -207,7 +207,8 @@ pub struct Implementation {
207207
/// Intended for programmatic or logical use, but can be used as a display
208208
/// name fallback if title isn't present.
209209
pub name: String,
210-
/// Intended for UI and end-user contexts, so it should be readable by people.
210+
/// Intended for UI and end-user contexts and optimized to be human-readable
211+
/// and easily understood.
211212
///
212213
/// If not provided, the name should be used for display.
213214
#[serde_as(deserialize_as = "DefaultOnError")]
@@ -241,7 +242,8 @@ impl Implementation {
241242
}
242243
}
243244

244-
/// Intended for UI and end-user contexts, so it should be readable by people.
245+
/// Intended for UI and end-user contexts and optimized to be human-readable
246+
/// and easily understood.
245247
///
246248
/// If not provided, the name should be used for display.
247249
#[must_use]
@@ -453,6 +455,9 @@ crate::serde_util::default_on_null! {
453455
/// Request parameters for the `auth/status` method.
454456
///
455457
/// Queries the agent's current authentication state without changing it.
458+
///
459+
/// Agents MUST NOT reject it with `auth_required` (`-32000`), since Clients call it to learn
460+
/// whether authentication is required.
456461
#[serde_as]
457462
#[skip_serializing_none]
458463
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
@@ -6465,7 +6470,7 @@ pub enum ClientRequest {
64656470
/// Queries the agent's current authentication state.
64666471
///
64676472
/// This method is only available if the agent advertises the `auth.status` capability.
6468-
/// It MUST NOT change any agent state.
6473+
/// It MUST NOT change any agent state, and agents MUST NOT reject it with `auth_required`.
64696474
#[cfg(feature = "unstable_auth_status")]
64706475
AuthStatusRequest(AuthStatusRequest),
64716476
/// Creates a new conversation session with the agent.

‎agent-client-protocol-schema/src/v1/proxy.rs‎

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,10 @@ use crate::IntoOption;
2525
/// successor, which tells the component to run as a proxy. The params and the response are
2626
/// the same as for `initialize`. A conductor sends `initialize` to the final agent.
2727
///
28+
/// The params carry the protocol version the conductor selected: the client's requested
29+
/// version, unless the conductor supports only a lower one. Before answering successfully,
30+
/// the proxy MUST forward an `initialize` request to its successor through `proxy/successor`.
31+
///
2832
/// See the [Proxy Chains RFD](https://agentclientprotocol.com/rfds/proxy-chains).
2933
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
3034
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
@@ -56,8 +60,9 @@ impl From<InitializeRequest> for InitializeProxyRequest {
5660
///
5761
/// Response to `proxy/initialize`.
5862
///
59-
/// The same as the `initialize` response. The proxy answers with the capabilities of the
60-
/// chain from itself onward.
63+
/// The same as the `initialize` response. The proxy builds it from its successor's
64+
/// `initialize` response and answers with the capabilities of the chain from itself onward.
65+
/// It MUST NOT change `protocolVersion`.
6166
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
6267
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
6368
#[cfg_attr(feature = "schemars", schemars(extend("x-side" = "proxy", "x-method" = PROXY_INITIALIZE_METHOD_NAME)))]
@@ -94,8 +99,12 @@ impl From<InitializeResponse> for InitializeProxyResponse {
9499
/// deliver a message from the successor to the proxy. The envelope wraps one request: `method`
95100
/// and `params` are the wrapped request's method and params.
96101
///
97-
/// The result or error of the wrapped request is returned unchanged as the result or error
98-
/// of the `proxy/successor` request.
102+
/// The result or error of the wrapped request is returned unchanged, as the same JSON value,
103+
/// as the result or error of the `proxy/successor` request. Errors the conductor returns
104+
/// itself, for example because the successor has exited, are not wrapped results.
105+
///
106+
/// To cancel it, the sender sends `$/cancel_request` with the ID of this `proxy/successor`
107+
/// request on the same connection. Cancellation is never forwarded to another hop.
99108
///
100109
/// See the [Proxy Chains RFD](https://agentclientprotocol.com/rfds/proxy-chains).
101110
#[serde_as]
@@ -111,12 +120,14 @@ pub struct ProxySuccessorRequest {
111120
/// Params of the wrapped request, forwarded unchanged.
112121
///
113122
/// Optional. Omitted and `null` are equivalent and mean the wrapped request has no params.
123+
/// When present, it MUST be a JSON object or array, as JSON-RPC requires.
114124
/// The wrapped request's own `_meta` stays inside these params.
115125
#[cfg_attr(feature = "schemars", schemars(with = "Option<serde_json::Value>"))]
116126
#[serde(default)]
117127
pub params: Option<Arc<RawValue>>,
118128
/// Metadata for the `proxy/successor` envelope itself, separate from the wrapped
119-
/// message's `_meta`.
129+
/// message's `_meta`. It is hop-local: the conductor does not copy it into the message
130+
/// it unwraps.
120131
///
121132
/// The _meta property is reserved by ACP to allow clients and agents to attach additional
122133
/// metadata to their interactions. Implementations MUST NOT make assumptions about values at
@@ -184,12 +195,14 @@ pub struct ProxySuccessorNotification {
184195
/// Params of the wrapped notification, forwarded unchanged.
185196
///
186197
/// Optional. Omitted and `null` are equivalent and mean the wrapped notification has no params.
198+
/// When present, it MUST be a JSON object or array, as JSON-RPC requires.
187199
/// The wrapped notification's own `_meta` stays inside these params.
188200
#[cfg_attr(feature = "schemars", schemars(with = "Option<serde_json::Value>"))]
189201
#[serde(default)]
190202
pub params: Option<Arc<RawValue>>,
191203
/// Metadata for the `proxy/successor` envelope itself, separate from the wrapped
192-
/// message's `_meta`.
204+
/// message's `_meta`. It is hop-local: the conductor does not copy it into the message
205+
/// it unwraps.
193206
///
194207
/// The _meta property is reserved by ACP to allow clients and agents to attach additional
195208
/// metadata to their interactions. Implementations MUST NOT make assumptions about values at

‎agent-client-protocol-schema/src/v2/agent.rs‎

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -198,7 +198,8 @@ pub struct Implementation {
198198
/// Intended for programmatic or logical use, but can be used as a display
199199
/// name fallback if title isn't present.
200200
pub name: String,
201-
/// Intended for UI and end-user contexts, so it should be readable by people.
201+
/// Intended for UI and end-user contexts and optimized to be human-readable
202+
/// and easily understood.
202203
///
203204
/// If not provided, the name should be used for display.
204205
///
@@ -234,7 +235,8 @@ impl Implementation {
234235
}
235236
}
236237

237-
/// Intended for UI and end-user contexts, so it should be readable by people.
238+
/// Intended for UI and end-user contexts and optimized to be human-readable
239+
/// and easily understood.
238240
///
239241
/// If not provided, the name should be used for display.
240242
#[must_use]
@@ -454,6 +456,9 @@ crate::serde_util::default_on_null! {
454456
/// Request parameters for the `auth/status` method.
455457
///
456458
/// Queries the agent's current authentication state without changing it.
459+
///
460+
/// Agents MUST NOT reject it with `auth_required` (`-32000`), since Clients call it to learn
461+
/// whether authentication is required.
457462
#[serde_as]
458463
#[skip_serializing_none]
459464
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
@@ -7202,7 +7207,7 @@ pub enum ClientRequest {
72027207
/// Queries the agent's current authentication state.
72037208
///
72047209
/// This method is only available if the agent advertises the `auth.status` capability.
7205-
/// It MUST NOT change any agent state.
7210+
/// It MUST NOT change any agent state, and agents MUST NOT reject it with `auth_required`.
72067211
#[cfg(feature = "unstable_auth_status")]
72077212
AuthStatusRequest(Box<AuthStatusRequest>),
72087213
/// Creates a new conversation session with the agent.
@@ -7459,10 +7464,16 @@ pub enum AgentResponse {
74597464
pub enum ClientNotification {
74607465
/// Cancels a session's foreground work and its prompts not yet inserted.
74617466
///
7462-
/// Background work is not covered, but the Agent MAY stop it too.
7467+
/// Work in the latest `background` list is not covered and keeps running. The
7468+
/// Agent MAY stop background activity it does not list.
74637469
///
74647470
/// Upon receiving this notification, the Agent SHOULD stop all language model
7465-
/// requests and all tool call invocations as soon as possible.
7471+
/// requests and all tool call invocations of the cancelled foreground work as soon
7472+
/// as possible.
7473+
///
7474+
/// The Agent MUST stop waiting for pending `session/request_permission` requests of
7475+
/// the cancelled work and treat them as not approved. It SHOULD cancel each of them
7476+
/// with `$/cancel_request`.
74667477
///
74677478
/// After all ongoing operations have been successfully aborted and pending
74687479
/// updates have been sent, the Agent MUST send an idle `state_update` session

‎agent-client-protocol-schema/src/v2/client.rs‎

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3530,10 +3530,10 @@ pub enum RequestPermissionOutcome {
35303530
/// cancelled, the user dismissed the prompt, or the client declined it by policy.
35313531
/// Agents MUST NOT proceed with the operation.
35323532
///
3533-
/// When a client sends a `session/cancel` notification, it MUST respond to all
3534-
/// pending `session/request_permission` requests in that session with this
3535-
/// `cancelled` outcome, without answering any request twice. Requests in other
3536-
/// sessions are unaffected.
3533+
/// The client answers a request the agent cancels with `$/cancel_request` with
3534+
/// this outcome. After sending `session/cancel`, the client MAY also send it
3535+
/// without waiting for `$/cancel_request`, for a request it knows belongs to the
3536+
/// cancelled foreground work.
35373537
///
35383538
/// See protocol docs: [Cancellation](https://agentclientprotocol.com/protocol/v2/prompt-lifecycle#cancellation)
35393539
Cancelled(CancelledPermissionOutcome),
@@ -3977,8 +3977,9 @@ pub enum AgentRequest {
39773977
/// a potentially sensitive operation. The client should present the options
39783978
/// to the user and return their decision.
39793979
///
3980-
/// If the client cancels active session work via `session/cancel`, it MUST
3981-
/// respond to this request with the `cancelled` outcome.
3980+
/// After `session/cancel`, the agent stops waiting for requests of the cancelled
3981+
/// foreground work and SHOULD cancel them with `$/cancel_request`. The client
3982+
/// answers a cancelled request with the `cancelled` outcome.
39823983
///
39833984
/// See protocol docs: [Requesting Permission](https://agentclientprotocol.com/protocol/v2/tool-calls#requesting-permission)
39843985
RequestPermissionRequest(Box<RequestPermissionRequest>),

‎agent-client-protocol-schema/src/v2/proxy.rs‎

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,10 @@ use crate::IntoOption;
2525
/// successor, which tells the component to run as a proxy. The params and the response are
2626
/// the same as for `initialize`. A conductor sends `initialize` to the final agent.
2727
///
28+
/// The params carry the protocol version the conductor selected: the client's requested
29+
/// version, unless the conductor supports only a lower one. Before answering successfully,
30+
/// the proxy MUST forward an `initialize` request to its successor through `proxy/successor`.
31+
///
2832
/// See the [Proxy Chains RFD](https://agentclientprotocol.com/rfds/proxy-chains).
2933
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
3034
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
@@ -56,8 +60,9 @@ impl From<InitializeRequest> for InitializeProxyRequest {
5660
///
5761
/// Response to `proxy/initialize`.
5862
///
59-
/// The same as the `initialize` response. The proxy answers with the capabilities of the
60-
/// chain from itself onward.
63+
/// The same as the `initialize` response. The proxy builds it from its successor's
64+
/// `initialize` response and answers with the capabilities of the chain from itself onward.
65+
/// It MUST NOT change `protocolVersion`.
6166
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
6267
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
6368
#[cfg_attr(feature = "schemars", schemars(extend("x-side" = "proxy", "x-method" = PROXY_INITIALIZE_METHOD_NAME)))]
@@ -94,8 +99,12 @@ impl From<InitializeResponse> for InitializeProxyResponse {
9499
/// deliver a message from the successor to the proxy. The envelope wraps one request: `method`
95100
/// and `params` are the wrapped request's method and params.
96101
///
97-
/// The result or error of the wrapped request is returned unchanged as the result or error
98-
/// of the `proxy/successor` request.
102+
/// The result or error of the wrapped request is returned unchanged, as the same JSON value,
103+
/// as the result or error of the `proxy/successor` request. Errors the conductor returns
104+
/// itself, for example because the successor has exited, are not wrapped results.
105+
///
106+
/// To cancel it, the sender sends `$/cancel_request` with the ID of this `proxy/successor`
107+
/// request on the same connection. Cancellation is never forwarded to another hop.
99108
///
100109
/// See the [Proxy Chains RFD](https://agentclientprotocol.com/rfds/proxy-chains).
101110
#[serde_as]
@@ -111,12 +120,14 @@ pub struct ProxySuccessorRequest {
111120
/// Params of the wrapped request, forwarded unchanged.
112121
///
113122
/// Optional. Omitted and `null` are equivalent and mean the wrapped request has no params.
123+
/// When present, it MUST be a JSON object or array, as JSON-RPC requires.
114124
/// The wrapped request's own `_meta` stays inside these params.
115125
#[cfg_attr(feature = "schemars", schemars(with = "Option<serde_json::Value>"))]
116126
#[serde(default)]
117127
pub params: Option<Arc<RawValue>>,
118128
/// Metadata for the `proxy/successor` envelope itself, separate from the wrapped
119-
/// message's `_meta`.
129+
/// message's `_meta`. It is hop-local: the conductor does not copy it into the message
130+
/// it unwraps.
120131
///
121132
/// The _meta property is reserved by ACP to allow clients and agents to attach additional
122133
/// metadata to their interactions. Omitted and `null` are equivalent and mean no metadata.
@@ -184,12 +195,14 @@ pub struct ProxySuccessorNotification {
184195
/// Params of the wrapped notification, forwarded unchanged.
185196
///
186197
/// Optional. Omitted and `null` are equivalent and mean the wrapped notification has no params.
198+
/// When present, it MUST be a JSON object or array, as JSON-RPC requires.
187199
/// The wrapped notification's own `_meta` stays inside these params.
188200
#[cfg_attr(feature = "schemars", schemars(with = "Option<serde_json::Value>"))]
189201
#[serde(default)]
190202
pub params: Option<Arc<RawValue>>,
191203
/// Metadata for the `proxy/successor` envelope itself, separate from the wrapped
192-
/// message's `_meta`.
204+
/// message's `_meta`. It is hop-local: the conductor does not copy it into the message
205+
/// it unwraps.
193206
///
194207
/// The _meta property is reserved by ACP to allow clients and agents to attach additional
195208
/// metadata to their interactions. Omitted and `null` are equivalent and mean no metadata.

‎docs/protocol/v1/draft/initialization.mdx‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -357,9 +357,9 @@ Both Clients and Agents **SHOULD** provide information about their implementatio
357357
</ParamField>
358358

359359
<ParamField path="title" type="string">
360-
Intended for UI and end-user contexts, so it should be readable by people.
361-
Optional. Omitted and `null` are equivalent. If not provided, the name should
362-
be used for display.
360+
Intended for UI and end-user contexts and optimized to be human-readable and
361+
easily understood. Optional. Omitted and `null` are equivalent. If not
362+
provided, the name should be used for display.
363363
</ParamField>
364364

365365
<ParamField path="version" type="string" required>

0 commit comments

Comments
 (0)