Skip to the content.

Out-of-band operator control — a closed control vocabulary for a running session

Once a session has started, how does a human change what it is doing? Today the usual answer is: type more prose into the same channel the agent reads as its task. That is in-band steering, and it has three structural problems. It is slow (you wait for a turn boundary and hope the model re-reads the new instruction). It is ambiguous (prose is interpreted, not applied — “actually, stop touching the auth module” may or may not land). And it is injection-shaped: a steering instruction delivered as task text is indistinguishable from task content, which is precisely the confusion fak’s kernel exists to prevent.

The alternative the rest of computing settled on decades ago is out-of-band control: a separate, addressable channel carrying a closed set of typed operations to a specific live execution, distinct from the data the execution is working on. TCP’s urgent pointer, Unix signals (SIGSTOP/SIGCONT/SIGTERM, nice, setrlimit), and Temporal’s signals/queries/updates are all the same shape: control that is not injected as more input.

This note expands that concept for agent loops, surveys where the field is (2025–26), benchmarks what fak already ships against it, and sequences the work to close the gap. The one-line thesis: fak already owns the hard parts of an out-of-band control plane; the frontier is a closed, structured control vocabulary to replace the freeform steer escape hatch, plus the operator surfaces to drive it and the witness that each op was actually applied.

Why fak is unusually well-positioned

The control-plane / data-plane split is not a new subsystem fak has to bolt on — it is fak’s founding thesis (the kernel sits between the agent and its tools and adjudicates every call). fak already ships every structural precondition the field says out-of-band control requires:

The state of the art (2025–26)

The field is converging on the same architecture from many directions. The survey below is condensed; each system expresses the same operations in its own dialect.

The ~15 canonical operations the field converged on

  1. Pause / interrupt — suspend at a safe boundary without ending.
  2. Resume — continue, optionally injecting a value the agent awaited.
  3. Cancel / abort — graceful stop with cleanup / compensation.
  4. Kill / terminate — forceful stop, no cleanup.
  5. Redirect-goal / reroute — change what the agent does next.
  6. Edit-state — mutate the agent’s working state out of band.
  7. Approve / deny (+ modify) — gate a specific pending action, optionally rewriting its arguments.
  8. Query-status — read live state / progress without mutating.
  9. Halt-on-policy (guardrail / tripwire) — automatic stop on a rule violation.
  10. Adjust-budget / limits — change resource or step ceilings mid-run.
  11. Adjust-autonomy-level — slide the oversight dial (approve-everything ↔ run-free).
  12. Prioritize / expedite — act on an urgent message ahead of the in-band queue.
  13. Re-attach / subscribe — reconnect an operator/peer to a running session’s stream.
  14. Signal / send-event — deliver a named, fire-and-forget message that triggers a handler.
  15. Fork / snapshot-and-branch — checkpoint durable state and spawn a divergent continuation.

Two structural constants underlie all of them: durable checkpointed state, and a separate addressable channel keyed by the execution id. fak has both.

What fak ships today (honest inventory)

Canonical op fak surface Status
Pause / Resume fak session pause/resume, fak signal pause/resume (turn-granular park, warm-KV resume seam) shipped (#1321)
Cancel / drain fak session stopDraining at the next boundary shipped
Throttle fak session throttle shipped
Query-status fak session ls/status/context, GET /v1/fak/session/{id}, /session/changes stream shipped
Adjust-budget fak session budget --turns/--tokens/--context-tokens (rev-fenced RMW) shipped
Adjust-pace fak session pace --max-tokens/--gap-ms (SessionPlanner.ApplyPace) shipped
Prioritize fak session priority <N> (scheduler re-sorts next boundary) shipped
Halt-on-policy adjudicator deny + loopmgr governor (WITNESS_COLLAPSE, REFUSAL_STORM, …) shipped
Signal / send-event fak signal steera2achan Session bus, spliced at boundary shipped, wiring flagged partial (#760)
Set-envelope (wall/spend/throughput) fak session envelope <spec> parses all axes parsed, only budget+pace applied
Kill / terminate fak fleet janitor --apply (process-tree kill); A2A tasks/cancel coarse / act-path simulated
Re-attach / subscribe /v1/fak/session/changes revision stream; resume is cold partial
Redirect-goal only freeform steer prose gap
Edit-state gap
Approve / deny (operator) reversibility gate is agent self-confirm (_fak_confirm), no operator inbox gap
Adjust-autonomy (mid-run) permission floor is fixed per session gap
Fork / live checkpoint sessionimage rehydrate is cold; no live snapshot verb gap

Surfaces: the control plane is CLI + HTTP today. The TUI (fak tui) is render-only (no mutation keybindings). The inbound Slack chatops door is epic #2259 (unshipped). trajctl — the goal-curve steering plane — has its ledger shipped but its live-nudge half unshipped and its CLI parked.

The core design move: a closed control vocabulary

The premise of this work is the goal’s own framing — replace prose mid-run with a structured set of controls. The eight-plus lifecycle/resource verbs above already do that for how much and how fast a session runs. The freeform steer is the one hole: to change what the agent does, or to tighten what it may touch, you still inject prose.

The move is to make the operator control surface a first-class closed vocabulary, exactly analogous to fak’s closed refusal vocabulary (dos.toml [reasons.*]). Each control op is a typed record with four fixed properties:

steer (freeform prose) stays — but demoted to the escape hatch. The structured verbs are the default, so routine control is auditable, capability-checked, refusable, and injection-resistant by construction; prose is the deliberate, logged exception.

The proposed vocabulary (grouped)

Honest fences

The spine and the fan-out

Spine (S): this note + a first-class control-op vocabulary type (the closed enum, the four per-op properties, and the existing verbs registered into it) with the generalized witness-of-applied contract. It unifies the fragmented surface (fak session drive-state, fak signal job-control + steer, fak steering — which is a code-quality scorecard, an unrelated name collision — and parked trajctl) under one named plane and one grammar.

Children (the gaps, worst-first):

  1. Structured redirect / set-objective — replace freeform steer for the common “change the goal” case.
  2. add-constraint — tighten the live policy on a running session (forbid-tool / add-deny / narrow-lane).
  3. Operator approve / deny inbox — resolve a pending reversibility/ESCALATE gate out of band (operator-driven HITL, not agent self-confirm).
  4. Graceful drain vs forceful terminate on the owned loop, with compensation; wire the A2A tasks/cancel act-path (de-simulate).
  5. set-autonomy — a mid-run permission-mode dial (approve-everything ↔ run-free).
  6. Live checkpoint / snapshot verb on a running session.
  7. fork — snapshot-and-branch a divergent continuation from a live checkpoint.
  8. Apply the envelope wall / spend / throughput axes live (finish parsed-not-applied).
  9. TUI control keybindings — mutate a running session from fak tui over the existing routes (turn the render-only console into a control pane).
  10. Fleet / lane-scoped broadcast — one control op to every session on a lane or wave.
  11. Wire the trajctl steering ladder (regime-gated auto-nudge over the control bus) and unpark its CLI — connect goal-curve control to this plane.
  12. Witness-of-applied + structured refusals for every control op (generalize the steer splice witness; add the closed reason set for illegal ops).
  13. subscribe / re-attach — an operator or peer re-attaches to a running session’s control + event stream (the A2A resubscribe equivalent), addressable by an external trace.
  14. Unify + document the operator control plane — one doctrine page, one front-door verb listing the closed vocabulary, and a fix for the naming fragmentation, so an agent or human can discover the whole surface in one place.