Quick Start
1
Default — every turn runs on the current loop, no config
The gateway uses
InProcessTurnExecutor when nothing is set, so every turn runs on the current event loop exactly as today.2
Isolate a bad session's turn on its own worker
Select an isolated executor from a wrapper package (subprocess / container / remote) when you need blast-radius containment. Core ships only the seam and the safe in-process default — the wrapper ships concrete isolated executors.
How It Works
The gateway asks the executor toplace a session, runs the turn on that placement, and tears the placement down only when its worker wedges — never the whole process.
InProcessTurnExecutor is the default and reproduces today’s on-loop behaviour exactly: leaving the executor unset changes nothing and adds no dependency.
The Contract
TurnExecutorProtocol is a runtime-checkable protocol with three async methods.
TurnPlacement is a frozen dataclass — mutating any field raises dataclasses.FrozenInstanceError.
WorkerWedgedError is a plain Exception subclass. It is scoped: the gateway tears down only the offending placement and re-places its session — never a process-wide os._exit. Ordinary turn errors surface as the turn’s own exception and do not condemn the worker.
An isolated executor does not ship the live
turn callable (and its captured loop/agent state) across a process boundary. The worker owns the session via place() and rebuilds the turn from serialisable inputs on its own side; the passed turn is the gateway-side await point for the worker’s result.Configuration Options
The seam is a typed contract, not a config block. Reach for these SDK references for the full surface.TurnExecutorProtocol — auto-generated SDK reference.TurnPlacement — auto-generated SDK reference.InProcessTurnExecutor — auto-generated SDK reference.WorkerWedgedError — auto-generated SDK reference.limits on execute_turn is a typed Any today, accepted for protocol symmetry. It is inert in-process and honoured only by isolated executors — there is no limits= config class in core.Common Patterns
Three shapes cover almost every use.Best Practices
Fence with epoch, always
Fence with epoch, always
epoch is the fencing token. Bump it whenever a session’s worker is replaced, and refuse any turn carrying a stale epoch — that is what stops a reclaimed worker from executing against a session it no longer owns.Keep teardown scoped to one session
Keep teardown scoped to one session
teardown reclaims a single placement’s worker. A worker fault must fail scoped: tear down the offending placement and re-place its session, never the whole gateway. That is the whole point of the seam versus a process-wide os._exit.Reach for isolation only when you need blast-radius containment
Reach for isolation only when you need blast-radius containment
The in-process default is zero-cost and dependency-free but offers no isolation — a turn that wedges the loop still affects the process. Switch to an isolated executor (subprocess / container / remote) when one bad session must not degrade the rest.
Never cross a boundary with a live callable
Never cross a boundary with a live callable
An isolated worker owns the session via
place() and rebuilds the turn from serialisable inputs on its own side. Do not try to send the live turn callable across a process boundary — treat it as the gateway-side await point for the worker’s result.Related
Gateway Turn Lock
Sibling primitive — serialises turns per session across replicas.
Gateway Loop Watchdog
Detects a wedged event loop.

