diff --git a/agent-client-protocol-schema/src/v2/conversion.rs b/agent-client-protocol-schema/src/v2/conversion.rs
index 070a0c87..a33a07b3 100644
--- a/agent-client-protocol-schema/src/v2/conversion.rs
+++ b/agent-client-protocol-schema/src/v2/conversion.rs
@@ -1603,6 +1603,9 @@ impl TryToV1 for super::PlanEntryStatus {
Self::Pending => crate::v1::PlanEntryStatus::Pending,
Self::InProgress => crate::v1::PlanEntryStatus::InProgress,
Self::Completed => crate::v1::PlanEntryStatus::Completed,
+ Self::Cancelled => {
+ return Err(unknown_v2_enum_variant("PlanEntryStatus", "cancelled"));
+ }
Self::Other(value) => return Err(unknown_v2_enum_variant("PlanEntryStatus", &value)),
})
}
@@ -3189,6 +3192,9 @@ impl TryToV1 for super::ToolCallStatus {
Self::InProgress => crate::v1::ToolCallStatus::InProgress,
Self::Completed => crate::v1::ToolCallStatus::Completed,
Self::Failed => crate::v1::ToolCallStatus::Failed,
+ Self::Cancelled => {
+ return Err(unknown_v2_enum_variant("ToolCallStatus", "cancelled"));
+ }
Self::Other(value) => return Err(unknown_v2_enum_variant("ToolCallStatus", &value)),
})
}
@@ -10648,6 +10654,18 @@ mod tests {
);
}
+ #[test]
+ fn v2_cancelled_statuses_do_not_convert_to_v1() {
+ assert_v2_to_v1_error(
+ v2::ToolCallStatus::Cancelled,
+ "v2 ToolCallStatus variant `cancelled` cannot be represented in v1",
+ );
+ assert_v2_to_v1_error(
+ v2::PlanEntryStatus::Cancelled,
+ "v2 PlanEntryStatus variant `cancelled` cannot be represented in v1",
+ );
+ }
+
#[test]
fn v2_collection_conversion_fails_on_unrepresentable_items() {
let response = v2::InitializeResponse::new(
diff --git a/agent-client-protocol-schema/src/v2/plan.rs b/agent-client-protocol-schema/src/v2/plan.rs
index de51ff78..6ec1c499 100644
--- a/agent-client-protocol-schema/src/v2/plan.rs
+++ b/agent-client-protocol-schema/src/v2/plan.rs
@@ -514,6 +514,8 @@ pub enum PlanEntryStatus {
InProgress,
/// The task has been successfully completed.
Completed,
+ /// The task was cancelled before it completed.
+ Cancelled,
/// Custom or future plan entry status.
///
/// Values beginning with `_` are reserved for implementation-specific
@@ -541,6 +543,13 @@ mod tests {
assert_eq!(serde_json::to_value(&status).unwrap(), "blocked");
}
+ #[test]
+ fn plan_entry_status_recognizes_cancelled_variant() {
+ let status: PlanEntryStatus = serde_json::from_str("\"cancelled\"").unwrap();
+ assert_eq!(status, PlanEntryStatus::Cancelled);
+ assert_eq!(serde_json::to_value(&status).unwrap(), "cancelled");
+ }
+
#[test]
fn plan_update_content_preserves_unknown_variant() {
let content: PlanUpdateContent = serde_json::from_value(serde_json::json!({
diff --git a/agent-client-protocol-schema/src/v2/tool_call.rs b/agent-client-protocol-schema/src/v2/tool_call.rs
index 34f8b516..45dbf0fb 100644
--- a/agent-client-protocol-schema/src/v2/tool_call.rs
+++ b/agent-client-protocol-schema/src/v2/tool_call.rs
@@ -330,6 +330,8 @@ pub enum ToolCallStatus {
Completed,
/// The tool call failed with an error.
Failed,
+ /// The tool call was cancelled before it completed.
+ Cancelled,
/// Custom or future tool call status.
///
/// Values beginning with `_` are reserved for implementation-specific
@@ -1244,6 +1246,13 @@ mod tests {
assert_eq!(serde_json::to_value(&status).unwrap(), "deferred");
}
+ #[test]
+ fn tool_call_status_recognizes_cancelled_variant() {
+ let status: ToolCallStatus = serde_json::from_str("\"cancelled\"").unwrap();
+ assert_eq!(status, ToolCallStatus::Cancelled);
+ assert_eq!(serde_json::to_value(&status).unwrap(), "cancelled");
+ }
+
#[test]
fn tool_call_content_preserves_unknown_variant() {
let content: ToolCallContent = serde_json::from_value(serde_json::json!({
diff --git a/docs/protocol/v2/agent-plan.mdx b/docs/protocol/v2/agent-plan.mdx
index 8e7da726..960828db 100644
--- a/docs/protocol/v2/agent-plan.mdx
+++ b/docs/protocol/v2/agent-plan.mdx
@@ -95,6 +95,7 @@ Custom or future priority values can be used for display hints. Custom prioritie
- `pending`
- `in_progress`
- `completed`
+- `cancelled`
Custom or future status values can be used when Clients can preserve or display a generic plan-entry state. Custom statuses **MUST** begin with `_`; unknown non-underscore statuses are reserved for future ACP variants.
diff --git a/docs/protocol/v2/draft/agent-plan.mdx b/docs/protocol/v2/draft/agent-plan.mdx
index 4f46ec47..26ece2e4 100644
--- a/docs/protocol/v2/draft/agent-plan.mdx
+++ b/docs/protocol/v2/draft/agent-plan.mdx
@@ -161,6 +161,7 @@ Custom or future priority values can be used for display hints. Custom prioritie
- `pending`
- `in_progress`
- `completed`
+- `cancelled`
Custom or future status values can be used when Clients can preserve or display a generic plan-entry state. Custom statuses **MUST** begin with `_`; unknown non-underscore statuses are reserved for future ACP variants.
diff --git a/docs/protocol/v2/draft/schema.mdx b/docs/protocol/v2/draft/schema.mdx
index 86af8b06..64d440ec 100644
--- a/docs/protocol/v2/draft/schema.mdx
+++ b/docs/protocol/v2/draft/schema.mdx
@@ -6482,6 +6482,10 @@ See protocol docs: [Plan Entries](https://agentclientprotocol.com/protocol/v2/dr
The task has been successfully completed.
+
+ The task was cancelled before it completed.
+
+
Custom or future plan entry status.
@@ -9225,6 +9229,10 @@ See protocol docs: [Status](https://agentclientprotocol.com/protocol/v2/draft/to
The tool call failed with an error.
+
+ The tool call was cancelled before it completed.
+
+
Custom or future tool call status.
diff --git a/docs/protocol/v2/draft/tool-calls.mdx b/docs/protocol/v2/draft/tool-calls.mdx
index e6d9acae..86209370 100644
--- a/docs/protocol/v2/draft/tool-calls.mdx
+++ b/docs/protocol/v2/draft/tool-calls.mdx
@@ -339,6 +339,10 @@ Tool calls progress through different statuses during their lifecycle:
The tool call failed with an error
+
+ The tool call was cancelled before it completed
+
+
Custom or future status values can be used when Clients can display a generic progress state. Custom status values **MUST** begin with `_`; unknown non-underscore statuses are reserved for future ACP variants.
## Content
diff --git a/docs/protocol/v2/migration.mdx b/docs/protocol/v2/migration.mdx
index 9efdb304..dfc2577e 100644
--- a/docs/protocol/v2/migration.mdx
+++ b/docs/protocol/v2/migration.mdx
@@ -348,7 +348,7 @@ v1 had `tool_call` (create) and `tool_call_update` (modify). In practice the spl
}
```
-The patch semantics are the same three-state model as messages: omitted fields stay unchanged, `null` explicitly clears a field, and concrete values replace. Array fields such as `content` and `locations` are replaced wholesale when present. The field set (`title`, `kind`, `status`, `content`, `locations`, `rawInput`, `rawOutput`) and the `kind`/`status` values are unchanged from v1, though the enums are now extensible.
+The patch semantics are the same three-state model as messages: omitted fields stay unchanged, `null` explicitly clears a field, and concrete values replace. Array fields such as `content` and `locations` are replaced wholesale when present. The field set (`title`, `kind`, `status`, `content`, `locations`, `rawInput`, `rawOutput`) and `kind` values are unchanged from v1. The `status` enum adds `cancelled`, and both enums are now extensible.
### Streaming tool-call content
@@ -550,7 +550,7 @@ The v1 `plan` update was a flat entries list with no identity and no room to gro
-Stable v2 defines the `items` plan type. The entry shape (`content`, `priority`, `status`, all required) is unchanged from v1, and entry priorities and statuses are now extensible enums. Each `plan_update` for a given `planId` replaces that plan's entries, and the `planId` allows multiple plans per session and future plan content types (such as markdown or file-backed plans, which remain unstable) without another breaking change.
+Stable v2 defines the `items` plan type. The entry shape (`content`, `priority`, `status`, all required) is unchanged from v1. Entry priorities and statuses are now extensible enums, and `status` adds `cancelled`. Each `plan_update` for a given `planId` replaces that plan's entries, and the `planId` allows multiple plans per session and future plan content types (such as markdown or file-backed plans, which remain unstable) without another breaking change.
## Session setup and lifecycle
diff --git a/docs/protocol/v2/schema.mdx b/docs/protocol/v2/schema.mdx
index af57e9f2..89bed140 100644
--- a/docs/protocol/v2/schema.mdx
+++ b/docs/protocol/v2/schema.mdx
@@ -2846,6 +2846,10 @@ See protocol docs: [Plan Entries](https://agentclientprotocol.com/protocol/v2/ag
The task has been successfully completed.
+
+ The task was cancelled before it completed.
+
+
Custom or future plan entry status.
@@ -5010,6 +5014,10 @@ See protocol docs: [Status](https://agentclientprotocol.com/protocol/v2/tool-cal
The tool call failed with an error.
+
+ The tool call was cancelled before it completed.
+
+
Custom or future tool call status.
diff --git a/docs/protocol/v2/tool-calls.mdx b/docs/protocol/v2/tool-calls.mdx
index e9512f6c..6495353f 100644
--- a/docs/protocol/v2/tool-calls.mdx
+++ b/docs/protocol/v2/tool-calls.mdx
@@ -339,6 +339,10 @@ Tool calls progress through different statuses during their lifecycle:
The tool call failed with an error
+
+ The tool call was cancelled before it completed
+
+
Custom or future status values can be used when Clients can display a generic progress state. Custom status values **MUST** begin with `_`; unknown non-underscore statuses are reserved for future ACP variants.
## Content
diff --git a/docs/rfds/v2/plan-variants.mdx b/docs/rfds/v2/plan-variants.mdx
index f4dd76e7..64ec07d7 100644
--- a/docs/rfds/v2/plan-variants.mdx
+++ b/docs/rfds/v2/plan-variants.mdx
@@ -64,7 +64,7 @@ The stable v2 `plan_update` shape does not require a capability. The unstable pl
When converting a v1 single-plan update to v2, implementations should use the item-based `plan_update` shape with a stable synthetic plan ID of `main`.
-When converting v2 back to a v1 surface that does not support unstable plan operations, an item-based `plan_update` can be represented as the old v1 `plan` update by dropping the plan ID. Other plan content variants cannot be represented without the unstable v1 plan operations surface.
+When converting v2 back to a v1 surface that does not support unstable plan operations, an item-based `plan_update` whose entries use v1-representable priorities and statuses can be represented as the old v1 `plan` update by dropping the plan ID. Other plan content variants cannot be represented without the unstable v1 plan operations surface.
## Shiny future
diff --git a/docs/rfds/v2/tool-call-updates.mdx b/docs/rfds/v2/tool-call-updates.mdx
index 13630da6..fcae5ff1 100644
--- a/docs/rfds/v2/tool-call-updates.mdx
+++ b/docs/rfds/v2/tool-call-updates.mdx
@@ -94,7 +94,7 @@ There is a single way to update a tool call, removing lots of confusion from how
When converting v1 to v2, both v1 `tool_call` and v1 `tool_call_update` should map to v2 `tool_call_update`.
-When converting v2 back to v1, adapters can represent a v2 update as a v1 `ToolCallUpdate`. This is lossy for some explicit clear operations because v1 update fields cannot represent every distinction between omitted and `null`. Collection clears can be represented as empty arrays, but scalar/raw-field clears may have to be omitted when targeting v1. This will be a best-effort conversion.
+When converting v2 back to v1, adapters can represent compatible v2 updates as a v1 `ToolCallUpdate`. Conversion is also lossy for some explicit clear operations because v1 update fields cannot represent every distinction between omitted and `null`. Collection clears can be represented as empty arrays, but scalar/raw-field clears may have to be omitted when targeting v1. This will be a best-effort conversion.
`tool_call_content_chunk` cannot be represented by the stateless v2-to-v1 conversion helper because v1 tool-call content updates replace the whole content array rather than appending one item. A stateful bridge can choose to accumulate chunks and emit replacement arrays to v1 clients.
diff --git a/schema/v2/schema.json b/schema/v2/schema.json
index 5f7242a5..a987af0c 100644
--- a/schema/v2/schema.json
+++ b/schema/v2/schema.json
@@ -816,6 +816,11 @@
"type": "string",
"const": "failed"
},
+ {
+ "description": "The tool call was cancelled before it completed.",
+ "type": "string",
+ "const": "cancelled"
+ },
{
"title": "other",
"description": "Custom or future tool call status.\n\nValues beginning with `_` are reserved for implementation-specific\nextensions. Unknown values that do not begin with `_` are reserved for\nfuture ACP variants.",
@@ -4390,6 +4395,11 @@
"type": "string",
"const": "completed"
},
+ {
+ "description": "The task was cancelled before it completed.",
+ "type": "string",
+ "const": "cancelled"
+ },
{
"title": "other",
"description": "Custom or future plan entry status.\n\nValues beginning with `_` are reserved for implementation-specific\nextensions. Unknown values that do not begin with `_` are reserved for\nfuture ACP variants.",
diff --git a/schema/v2/schema.unstable.json b/schema/v2/schema.unstable.json
index 82ebe9d8..a8110a82 100644
--- a/schema/v2/schema.unstable.json
+++ b/schema/v2/schema.unstable.json
@@ -960,6 +960,11 @@
"type": "string",
"const": "failed"
},
+ {
+ "description": "The tool call was cancelled before it completed.",
+ "type": "string",
+ "const": "cancelled"
+ },
{
"title": "other",
"description": "Custom or future tool call status.\n\nValues beginning with `_` are reserved for implementation-specific\nextensions. Unknown values that do not begin with `_` are reserved for\nfuture ACP variants.",
@@ -6991,6 +6996,11 @@
"type": "string",
"const": "completed"
},
+ {
+ "description": "The task was cancelled before it completed.",
+ "type": "string",
+ "const": "cancelled"
+ },
{
"title": "other",
"description": "Custom or future plan entry status.\n\nValues beginning with `_` are reserved for implementation-specific\nextensions. Unknown values that do not begin with `_` are reserved for\nfuture ACP variants.",