{"slug": "your-ai-agent-needs-a-cancellation-contract-not-just-a-stop-button", "title": "Your AI Agent Needs a Cancellation Contract, Not Just a Stop Button", "summary": "A developer argues that AI agents need a durable cancellation contract rather than a simple stop button, proposing a state machine with cancel versions and compare-and-set operations to prevent resurrected work and reconcile side effects. The approach separates cancellation from process liveness and requires checks at every work-creating boundary.", "body_md": "A stop button is not a cancellation protocol.\n\nIn a toy agent, “stop” can mean setting a boolean and waiting for the loop to exit. In a real agent, work may already be queued, claimed by another worker, inside a browser session, or waiting for an outbound side effect. If cancellation is not represented as durable state, a restart can resurrect work the operator thought they stopped.\n\nThe useful question is not “did the process receive SIGTERM?” It is:\n\nCan every layer prove whether this run may still start work, whether in-flight work must finish, and what happened to side effects that were interrupted?\n\nThis article turns cancellation into a small contract you can test.\n\nKeep cancellation separate from process liveness. A worker can be alive while its run is cancelled, and a worker can die before it records the cancellation.\n\nA minimal run state machine is:\n\nStore the state durably with a monotonically increasing cancel_version:\n\n```\nrun_id              status       cancel_version  updated_at\nrun_42              CANCELLING   3               2026-08-19T12:00:00Z\n```\n\nWorkers must carry the version they observed. A dispatch is valid only if the durable row still says ACTIVE with the same version. This closes the race where an operator clicks Stop after a worker checked the run but before it starts a tool call.\n\nA cancellation check only at the top of the agent loop is too weak. Check the contract at each boundary that can create work:\n\nThat last distinction matters. Cancelling a code-generation run does not automatically prove that an already-created notification was unsent. Execution and delivery need separate records.\n\nCooperative cancellation is the default: the worker notices the state change at safe checkpoints and exits cleanly. Forced cancellation is a deadline for the worker that does not cooperate.\n\nA practical sequence is:\n\n``` php\nACTIVE\n  -> CANCELLING (revoke admission and retries)\n  -> drain safe checkpoints\n  -> CANCELLED (if no in-flight effects remain)\n  -> UNKNOWN (if an external effect cannot be reconciled)\n```\n\nDo not mark a run CANCELLED merely because the worker process exited. A process can die after sending a request and before recording the response. For every external side effect, record an intent with a stable key before dispatch, then reconcile UNKNOWN using the provider’s lookup API, webhook, or an operator decision.\n\nA cancellation timeout should transition the run to UNKNOWN or CANCELLING_TIMEOUT, not silently to success or cancellation. That makes the ambiguity visible instead of converting it into duplicate work on restart.\n\nThe critical operation is a compare-and-set, not a read followed by a write:\n\n```\nUPDATE runs\nSET status = 'CANCELLING',\n    cancel_version = cancel_version + 1,\n    updated_at = CURRENT_TIMESTAMP\nWHERE run_id = :run_id\n  AND status = 'ACTIVE';\n```\n\nA worker dispatch can then require the exact version it observed:\n\n```\nUPDATE steps\nSET status = 'DISPATCHED', dispatch_version = :cancel_version\nWHERE step_id = :step_id\n  AND status = 'CLAIMED'\n  AND EXISTS (\n    SELECT 1 FROM runs\n    WHERE run_id = :run_id\n      AND status = 'ACTIVE'\n      AND cancel_version = :cancel_version\n  );\n```\n\nIf the update affects zero rows, the worker must not call the tool. It should release the claim and record CANCELLED_BEFORE_DISPATCH.\n\nA cancellation feature is incomplete until it survives these injected failures:\n\n| Failure | Expected evidence |\n|---|---|\n| Cancel between queue claim and dispatch | No tool request, or a reconciled effect record |\n| Worker pauses after the state check | Stale version is rejected at dispatch |\n| Process dies after provider request | Effect becomes UNKNOWN, then reconciles |\n| Retry timer fires after cancellation | Retry is rejected and recorded |\n| Cancellation store is unavailable | Fail closed for new effects; preserve the run as unresolved |\n| Browser action is mid-flight | No next mutation; current action is explicitly unresolved |\n| Controller restarts during drain | Durable CANCELLING state resumes the drain |\n\nFor each case, assert both safety and evidence: no unauthorized new effect, no lost cancellation intent, and a record an operator can explain later.\n\nIf you run an always-on OpenClaw or browser agent, a managed runtime such as [managed OpenClaw hosting on Ampere](https://ampere.sh/?utm_source=devto&utm_medium=article&utm_campaign=cancellation-contract) can be one deployment option to evaluate. It does not replace durable run state, fencing, credential scope, or reconciliation. Those remain properties of the agent control plane.\n\nBefore trusting a Stop button, verify that:\n\nThe practical goal is not instant termination. It is a system that can prove what was prevented, what was already in flight, and what still needs reconciliation. That is the difference between a UI button and an operational cancellation contract.\n\nIf you are building coding agents or automation that must survive restarts and operator intervention, follow for more concrete control-plane tests and failure drills.", "url": "https://wpnews.pro/news/your-ai-agent-needs-a-cancellation-contract-not-just-a-stop-button", "canonical_source": "https://dev.to/zira125/your-ai-agent-needs-a-cancellation-contract-not-just-a-stop-button-4k8n", "published_at": "2026-08-19 19:43:13+00:00", "updated_at": "2026-08-19 20:14:44.421483+00:00", "lang": "en", "topics": ["ai-agents", "ai-safety", "ai-infrastructure", "developer-tools"], "entities": [], "alternates": {"html": "https://wpnews.pro/news/your-ai-agent-needs-a-cancellation-contract-not-just-a-stop-button", "markdown": "https://wpnews.pro/news/your-ai-agent-needs-a-cancellation-contract-not-just-a-stop-button.md", "text": "https://wpnews.pro/news/your-ai-agent-needs-a-cancellation-contract-not-just-a-stop-button.txt", "jsonld": "https://wpnews.pro/news/your-ai-agent-needs-a-cancellation-contract-not-just-a-stop-button.jsonld"}}