Skip to content

Commit 655e548

Browse files
authored
feat(unstable): Draft implementation of $/cancel_request notification (#303)
* Add request cancelled error code * Add notification struct * Add cancellation capabilities * Add notification to both sides * Add draft cancellation docs * Fix agent notification * Rename cancellation method to $/cancel_request Aligns with JSON-RPC convention of using $/ prefix for protocol-level methods, following the same pattern as Language Server Protocol. * Remove unstable cancel_request from agent/client capabilities The cancel_request notification is a protocol-level feature that both sides must implement, not a capability to be negotiated. Move it from agent/client capabilities to a new protocol_level module and update schema generation accordingly. Also enable --all-features flag for clippy in CI to catch issues in feature-gated code. * Update docs to reflect LSP behavior * Fix config check * add config flag for method
1 parent 07f7439 commit 655e548

File tree

12 files changed

+463
-149
lines changed

12 files changed

+463
-149
lines changed

.github/workflows/ci.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ jobs:
4949
config: ./typos.toml
5050

5151
- name: Lint
52-
run: cargo clippy
52+
run: cargo clippy --all-features
5353

5454
- name: Build
5555
run: cargo build --all-targets --all-features

Cargo.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,8 @@ categories = ["development-tools", "api-bindings"]
1414
include = ["/src/**/*.rs", "/README.md", "/LICENSE", "/Cargo.toml"]
1515

1616
[features]
17-
unstable = ["unstable_session_model", "unstable_session_list", "unstable_session_fork"]
17+
unstable = ["unstable_session_model", "unstable_session_list", "unstable_session_fork", "unstable_cancel_request"]
18+
unstable_cancel_request = []
1819
unstable_session_model = []
1920
unstable_session_list = []
2021
unstable_session_fork = []

docs/docs.json

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -76,9 +76,12 @@
7676
"protocol/transports",
7777
"protocol/schema",
7878
{
79-
"group": "Unstable",
79+
"group": "Draft: In Progress and May Change",
8080
"hidden": true,
81-
"pages": ["protocol/schema.unstable"]
81+
"pages": [
82+
"protocol/draft/cancellation",
83+
"protocol/draft/schema"
84+
]
8285
}
8386
]
8487
},
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
---
2+
title: "Cancellation"
3+
description: "Mechanisms for request cancellation"
4+
---
5+
6+
ACP uses JSON-RPC 2.0 for making requests and getting responses.
7+
8+
The JSON-RPC specification doesn't define any standard mechanism for request cancellation and keeps it up to the implementation.
9+
10+
## `$/cancel_request` Notification
11+
12+
In order to provide a consistent approach to cancellation, ACP defines a `$/cancel_request` notification that can be sent to cancel requests.
13+
14+
Cancellation will remain optional as it might not be implementable in all clients or servers. For example if the implementation uses a single threaded synchronous programming language then there is little it can do to react to a `$/cancel_request` notification.
15+
16+
When a `$/cancel_request` notification is received by a supporting implementation, the implementation:
17+
18+
- **MUST** cancel the corresponding request activity and all nested activities related to that request
19+
- **MAY** finish sending any pending notifications before responding
20+
- **MUST** send one of these responses for the original request:
21+
- A valid response with appropriate data (such as partial results or cancellation marker)
22+
- An error response with code [`-32800` (Request Cancelled)](./schema#errorcode)
23+
24+
The calling side **MAY** implement graceful cancellation processing by waiting for the response from the remote side.
25+
26+
Cancellation **MAY** also be done explicitly on a per-feature basis within the protocol to cover specific scenarios (e.g., cancellation of a [prompt turn](./prompt-turn#cancellation))
27+
28+
## Internal Cancellation
29+
30+
Requests can also be cancelled internally by the executing party without receiving `$/cancel_request`:
31+
32+
- **Client-side examples**: User closes IDE, switches to different project, file becomes unavailable
33+
- **Agent-side examples**: LLM context limit reached, internal timeout, resource constraints
34+
35+
When internal cancellation occurs, the executing party **MUST**:
36+
37+
- Send the same `-32800` (Cancelled) error response as if `$/cancel_request` was received
38+
- Ensure consistent behavior regardless of cancellation source
39+
40+
## Example: Cascading Cancellation Flow
41+
42+
```mermaid
43+
sequenceDiagram
44+
participant Client
45+
participant Agent
46+
47+
Note over Client,Agent: 1. Session prompt in progress
48+
Client->>Agent: session/prompt (id=1, "Analyze file X")
49+
Agent-->>Client: session/update (agent started processing)
50+
51+
Note over Client,Agent: 2. Agent makes concurrent requests
52+
Agent->>Client: terminal/create (id=2, "grep pattern file.txt")
53+
Agent->>Client: session/request_permission (id=3, "read sensitive file")
54+
55+
Note over Client,Agent: 3. Client cancels the prompt turn
56+
Client->>Agent: session/cancel (sessionId)
57+
58+
Note over Client,Agent: 4. Agent cascades cancellation internally
59+
Agent->>Client: $/cancel_request (id=2) [terminal request]
60+
Agent->>Client: $/cancel_request (id=3) [permission request]
61+
62+
Note over Client,Agent: 5. Client confirms individual cancellations
63+
Client->>Agent: response to id=2 (error -32800 "Cancelled")
64+
Client->>Agent: response to id=3 (error -32800 "Cancelled")
65+
66+
Note over Client,Agent: 6. Agent completes prompt cancellation
67+
Agent->>Client: response to id=1 (stopReason: "cancelled")
68+
```
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1235,6 +1235,66 @@ See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/exte
12351235
The signal that terminated the process (may be null if exited normally).
12361236
</ResponseField>
12371237

1238+
## Protocol Level
1239+
1240+
Defines the interface that ACP-compliant agents and clients must both implement.
1241+
1242+
Notifications whose methods start with '$/' are messages which are protocol
1243+
implementation dependent and might not be implementable in all clients or
1244+
agents. For example if the implementation uses a single threaded synchronous
1245+
programming language then there is little it can do to react to a
1246+
`$/cancel_request` notification. If an agent or client receives notifications
1247+
starting with '$/' it is free to ignore the notification.
1248+
1249+
<a id="$-cancel_request"></a>
1250+
### <span class="font-mono">$/cancel_request</span>
1251+
1252+
**UNSTABLE**
1253+
1254+
This capability is not part of the spec yet, and may be removed or
1255+
changed at any point.
1256+
1257+
Cancels an ongoing request.
1258+
1259+
This is a notification sent by the the side that sent a request to cancel that request.
1260+
1261+
Upon receiving this notification, the receiver:
1262+
1263+
1. MUST cancel the corresponding request activity and all nested activities
1264+
2. MAY send any pending notifications.
1265+
3. MUST send one of these responses for the original request:
1266+
1267+
- Valid response with appropriate data (partial results or cancellation marker)
1268+
- Error response with code `-32800` (Cancelled)
1269+
1270+
See protocol docs: [Cancellation](https://agentclientprotocol.com/protocol/cancellation)
1271+
1272+
#### <span class="font-mono">CancelRequestNotification</span>
1273+
1274+
**UNSTABLE**
1275+
1276+
This capability is not part of the spec yet, and may be removed or changed at any point.
1277+
1278+
Notification to cancel an ongoing request.
1279+
1280+
See protocol docs: [Cancellation](https://agentclientprotocol.com/protocol/cancellation)
1281+
1282+
**Type:** Object
1283+
1284+
**Properties:**
1285+
1286+
<ResponseField name="_meta" type={"object | null"} >
1287+
The _meta property is reserved by ACP to allow clients and agents to attach additional
1288+
metadata to their interactions. Implementations MUST NOT make assumptions about values at
1289+
these keys.
1290+
1291+
See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
1292+
1293+
</ResponseField>
1294+
<ResponseField name="requestId" type={<a href="#requestid">RequestId</a>} required>
1295+
The ID of the request to cancel.
1296+
</ResponseField>
1297+
12381298
## <span class="font-mono">AgentCapabilities</span>
12391299

12401300
Capabilities supported by the agent.
@@ -1892,6 +1952,16 @@ and use the reserved range (-32000 to -32099) for protocol-specific errors.
18921952
implementation-defined server errors.
18931953
</ResponseField>
18941954

1955+
<ResponseField name="-32800" type="int32">
1956+
**Request cancelled**: **UNSTABLE**
1957+
1958+
This capability is not part of the spec yet, and may be removed or changed at any point.
1959+
1960+
Execution of the method was aborted either due to a cancellation request from the caller or
1961+
because of resource constraints or shutdown.
1962+
1963+
</ResponseField>
1964+
18951965
<ResponseField name="-32000" type="int32">
18961966
**Authentication required**: Authentication is required before this operation
18971967
can be performed.

0 commit comments

Comments
 (0)