turn no longer live (stopped or superseded).
Quick Start
Run a bot with interrupt mode
busy_mode="interrupt" and give the agent the send_message tool — the outbound liveness binding is automatic. No extra config.Scenario — /stop drops an in-flight outbound effect
/stop while the agent is about to post a late reply. The send never reaches the chat; the tool call returns a fail-closed result instead.Scenario — mid-send attachment upload halts
/stop while a 3-image upload is partway through. Files already uploaded stay; the remaining ones are skipped.How It Works
Each turn’sBotOutboundMessenger is bound to that turn’s InterruptController. Every outbound verb checks the controller before touching the router.
detail is the same string: turn no longer live (stopped or superseded).
What Triggers the Drop
Backward Compatibility
InterruptController (any bot using busy_mode). Without a controller the messenger is unbound and behaves exactly as before. Code that constructs BotOutboundMessenger without liveness= is unchanged, and nothing in the gateway YAML schema moves.Failure Semantics
Raising probe is treated as live
Raising probe is treated as live
ApprovalRegistry._reject_if_stale on the approval path.Mid-send attachment uploads re-check liveness
Mid-send attachment uploads re-check liveness
/stop only sets a flag — it does not cancel the running send coroutine. So liveness is re-checked before every attachment upload, and the remaining files are counted as skipped once the turn goes stale.Retained handles from a cancelled turn stay fail-closed forever
Retained handles from a cancelled turn stay fail-closed forever
/stop set and nothing clears. Any code still holding that turn’s messenger can never deliver through it again.Background workers after a normally-completed turn still deliver
Background workers after a normally-completed turn still deliver
deliver-backed subagents — keep delivering after the turn ends.Self-scheduling is unaffected
Self-scheduling is unaffected
Best Practices
Prefer busy_mode='interrupt' for the strongest benefit
Prefer busy_mode='interrupt' for the strongest benefit
busy_mode="interrupt", a superseding message (or /stop) drops the abandoned turn’s outbound effects so a late reply never lands after the user moved on.Custom integrators using BotSessionManager directly
Custom integrators using BotSessionManager directly
agent.interrupt_controller is an InterruptController at the time the turn’s messenger is created:Verifying locally
Verifying locally
send_message tool call under a turn, issue /stop from another message, and check the returned DeliveryResult:okisFalsedetailis"turn no longer live (stopped or superseded)"
Related
Bot Run Control
busy_mode + /stop side that fires the cancelApproval Turn Liveness
Send Message Tool
Send Policy
Outbound Media Delivery
Turn Protection Window
busy_mode="interrupt" queues during subagents and compaction
