Overview
Cancellation allows agents to abort long-running operations before they complete. This is essential for operations like:- PDF generation for large documents (5-60 seconds)
- AI operations like summarization (3-30 seconds)
- Image processing (2-20 seconds)
- Large file exports (10-120 seconds)
Why Cancellation Matters
Design Rationale
Without cancellation, agents face a dilemma:- Wait: User might cancel the request, but operation keeps running
- Disconnect: Loses the entire session, must reconnect for next operation
Design Decisions
| Decision | Choice | Alternatives Considered | Rationale |
|---|---|---|---|
| Cancellation identifier | Auto-generated callId | Progress token, manual IDs | Every call should be cancellable, not just those with progress tracking. Auto-generation reduces developer burden. |
| JavaScript API | AbortSignal support | Custom cancel methods, Promise extensions | AbortSignal is a web standard that developers already know from fetch(). Reusing familiar patterns reduces learning curve. |
| Partial results | Not supported | Include partial data on cancel | For browser operations (PDF, images, canvas), partial results are rarely useful. A half-generated PDF is not a valid PDF. |
| Capability flag | Not required | cancellable: boolean per capability | If an operation completes before cancel arrives, no harm done. Adding flags creates unnecessary complexity. |
| Cancel acknowledgment | Cancel returns confirmation | Fire-and-forget | Confirmation lets agents know if cancellation succeeded, enabling better error handling and UX. |
What We Explicitly Chose NOT to Do
- No partial results — Half-processed outputs are typically useless for browser operations
- No
cancellablecapability flag — Adds complexity without clear benefit - No progress-token-based cancellation — Ties cancellation to progress, but you might want to cancel without tracking progress
Protocol Specification
Call ID
Every capability call includes acallId for identification:
callId is not provided, the agent-side library MUST generate a unique identifier (e.g., UUID).
Cancel Request (Agent → App)
Cancel Response (App → Agent)
Modified Call Response
When a call is cancelled, its response includes acancelled flag:
Using AbortSignal (Recommended)
The recommended agent-side API uses the standardAbortSignal pattern:
Why AbortSignal?
Developers already use this pattern withfetch():
App-Side Implementation
Apps implement cancellation usingAbortController internally:
Example: Cancellable PDF Generation
Transport-Specific Handling
Puppeteer/Playwright
postMessage
WebSocket
Edge Cases
| Scenario | Behavior |
|---|---|
| Cancel non-existent callId | Return { cancelled: false, reason: 'Operation not found' } |
| Cancel already-completed call | Return { cancelled: false, reason: 'Operation already completed' } |
| Cancel already-cancelled call | Return { cancelled: true } (idempotent) |
| Multiple cancels for same callId | All return same result (idempotent) |
| Call completes while cancel in flight | Call result returned normally, cancel returns { cancelled: false } |
| Cancel without active session | Return error { code: 'NOT_INITIALIZED' } |
Timing Considerations
- Cancel arrives before operation starts: Operation is skipped, response has
cancelled: true - Cancel arrives during operation: Operation is aborted, response has
cancelled: true - Cancel arrives after completion: Cancel response has
cancelled: false, original result is returned
Relationship to Timeout
Thetimeout option in calls is complementary to cancellation:
| Mechanism | Who decides | When triggered |
|---|---|---|
timeout option | Agent, at call time | Automatic, after specified duration |
AbortSignal | Agent, any time | Manual, based on external events |
cancelled: true in the response. Apps cannot distinguish between timeout-triggered and signal-triggered cancellation (and SHOULD NOT need to).
Using Both Together
Message Flow
Next Steps
Building ABP Apps
Build apps with cancellation support
API Reference
Full API specification
Error Handling
Cancellation error codes