/stop, an abort WebSocket frame, or a configurable per-turn timeout — all driven by the same InterruptController primitive the CLI uses for Ctrl-C.
Available since PraisonAI#3472. The gateway advertises
abort in the hello_ok capability handshake, accepts abort / message_abort WebSocket frames, honours /stop (or stop) in chat, and enforces a configurable per-turn timeout via gateway.per_turn_timeout.message_abort event to clients when a turn is cancelled, so a custom client can render the turn as “cancelled” instead of hanging or leaking a raw traceback.
Quick Start
1
Cancel from any chat client with /stop
Any chat client can cancel the in-flight turn by sending
/stop (or bare stop, case-insensitive). Reply is either {"type":"aborted","session_id":"..."} or {"type":"no_active_turn","session_id":"..."}.2
Cancel with an abort WebSocket frame
Send an
abort frame — requires the write operator scope (same as sending a message as the agent):reason is optional (defaults to "user") and is echoed back in the terminal turn message.3
Set a per-turn wall-clock ceiling
Set a wall-clock ceiling per turn in the gateway config. A timed-out turn’s terminal response is
0 (default) disables the timeout — behaviour is byte-identical to earlier releases."Turn cancelled: exceeded per-turn timeout.".4
Render the message_abort event on the client
When the gateway cancels a turn it emits a
message_abort event; treat it as a terminal outcome for that turn.Config: gateway.per_turn_timeout
Wall-clock ceiling for a single agent turn. When exceeded, the turn is cancelled cooperatively (via its InterruptController) and, if it does not unwind within a bounded grace window, the driving task is cancelled hard.
Three ways to set it:
Default
0.0 = disabled. Every turn runs to completion, exactly as in releases before #3472.Frame shapes
Client → Gateway
Abort frame — requires thewrite operator scope:
message_abort is accepted as an alias for type; reason is optional and defaults to "user".
Portable stop command — any client already joined to a session can cancel via the message channel:
stop (no slash, case-insensitive) is also accepted.
Gateway → Client (reply to abort)
Terminal turn message
The turn’s own response (delivered on the normalmessage channel) is a typed string:
The message_abort event
EventType.MESSAGE_ABORT is defined in praisonaiagents/gateway/protocols.py and serialises to the wire string "message_abort".
Because
EventType is a str Enum, EventType.MESSAGE_ABORT == "message_abort" compares True, so clients can match on the raw string without importing the enum.How It Works
Every turn runs through a per-turnInterruptController, so a /stop, an abort frame, or a timeout on one session never touches another session’s turn.
Why cancellation is cooperative
Why cancellation is cooperative
Cancellation always requests interruption via the turn’s
InterruptController first, so the agent stops at its next safe checkpoint and partial output is preserved. A hard task.cancel() fires only if the turn hasn’t unwound within 5 seconds (_ABORT_GRACE_SECONDS) — this bounds the case where a sync agent.chat running in a worker thread cannot be force-killed but must not keep mutating shared state after the queue advances.Fallback for older entry points
Fallback for older entry points
Agent entry points that predate
cancel_token= fall back to stamping agent.interrupt_controller on the shared attribute for the turn’s duration. This is best-effort and non-isolated — prefer keeping agents on the current SDK so per-turn isolation applies.Timeout is opt-in
Timeout is opt-in
per_turn_timeout defaults to 0.0, which means no wall-clock cancellation. Every turn runs to completion, exactly as in releases before #3472 — enabling the timeout is opt-in.Common Patterns
Real scenarios this page lets you pattern-match to:Related
Chat /stop Command
The chat-side twin of the gateway’s abort surface.
Handshake Protocol
Capability negotiation and the
hello_ok feature set.Gateway CLI
Process-level
praisonai gateway stop versus turn-level cancellation.Interactive TUI Ctrl-C
The terminal-side twin of the same cooperative primitive.

