As built · 2026-08-04 · running now
01You make decisions. Everything else drives itself. One picture:
Matrix names, one sentence: the Architect builds the world, the Worker goes in, the Operator stays on the line — and you answer the questions. Dashed means a dumb process — no model, cannot rot, survives a reboot.
Who does what
02Live in AgentFlow — now a section of PropFlow at /agents. Answer decisions, skim each task's timeline, say "I don't like what X is doing." Nothing else is your job.
Builds the world for each task — pulls transcripts, Slack, code. Writes the criterion into task.json. Spawns the pair, arbitrates. Event-woken, never looping.
Holds the criterion. The only role that loops — and it ends the loop when the task closes. Raises the questions only you can answer, then executes your answer.
Does the task. No self-nudge — it keeps only a Stop gate, so it cannot finish on a lie. Doesn't manage itself; its transcript is the report.
A fifth piece has no card because it is not a role: the Supervisor, a launchd daemon that mints the first Operator for any unwatched task, revives dead ones, and pings a session that is idle with unread mail. Your rounds now route through the Operator rather than straight at the Worker — the criterion only moves with the Operator's knowledge.
Left to right, one task
03Every task now writes its own timeline: one append-only line per checkpoint, in your language, at ~/.claude/jobs/tasks/<task>/events.jsonl. You asked, opening a task: "I was expecting the operator to fill me in… I see nothing." A layer that judges and records nothing is indistinguishable from one that isn't there. The reviewer at the end still exists — the Operator isn't a second reviewer, it's the one that makes sure the task gets to the reviewer.
Both daemons are live · launchd
04Solid boxes are smart sessions; dashed are dumb processes — cannot rot, survive reboots. Both daemons are real launchd services now: the Digester rides inside agentflow-relay, the Supervisor is its own. It mints as well as revives — it used to only revive, so a task that never had an Operator never got one. The Worker stops every 2–4 minutes; a dumb tail keeps STATE.md fresh for pennies. The feed you skim is derived from files, never narrated — the app can't become the source of truth.
Owner-first routing · shipped, controlled both directions
05Why this slide exists: you approved the Camellia Saturday rule at noon and it sat unexecuted for hours — delivered, but executing it was nobody's job. Then the first fix leaked: the dock rendered questions by text only, so the hook could not tell who had asked and fell back to the Architect every time. Both are closed. If the owner dies, its successor adopts the block — the id is preserved, so the answer it was adopted to receive still lands. An answered question always has a live executor.
Your words: "the only thing really looping is the operator, right?"
06Three sessions run a task. One of them holds a loop — and it lets go of it when the task closes.
The rule that makes this safe to say out loud: the gate is not the loop. Arming a gate costs nothing and stops a session declaring itself finished on a lie; arming a watcher is a poll that bills a model every few minutes. Three loops per task was three times the cost for one job — and the two extra ones outlived their tasks, which is how a machine ends up full of watchers nudging work that closed hours ago.
Your question: "always on? every 10 seconds?"
07Measured: a real Worker produced 1,064 messages in 17.7 hours — a stop every 2–4 minutes. Any per-stop smart cadence turns the Operator into a second full-price model that compacts away its own criterion by early afternoon. Cost as amended: ~10–15% of its Worker.
propflowai.co/agents · PR #5376, draft · read-only end to end
08You asked for "ideally a one-for-one copy, so if we update PropFlow we could just pull it in." A literal clone is the version of that which decays — two shells drift and the sync nobody runs is what keeps them together. A route has nothing to pull in, because the shell IS the shell. Side nav, top bar, house auth, the same drawer. One genuinely new component: the terminal. Read-only is structural — the relay has no code that can type, kill or resize a pane, and the app proxies three GETs and one stream. The old standalone viewer at /a/agentflow is retired; it is a tombstone pointing here.
Five skeptics before a line was written — and the rulings held
09Both preconditions the attack found are closed. Loop state was one global slot — a second Operator stole the first's on its first command; it is per-session now, and two loops armed at once leave each other alone. And a raise published before saving its ledger row, so a failed publish silently erased the question; it writes ahead now.
Every step landed with an executed control
10Per-session gate + registry; raises save before they publish. Proved: two loops armed at once, neither steals the other's. Then narrowed again — only the Operator arms one at all.
Lives inside agentflow-relay, tailing every paired Worker into STATE.md. Proved: a wedged session flips to STALLED within a minute, zero model tokens.
It mints first Operators, not just revivals. Answers go owner-first. Proved: controls in both directions — live owner executes, dead owner is adopted.
Next: you type a task into AgentFlow and a session exists
The + button writes an intake file through the relay — a file on disk, never a keystroke into a terminal, the same shape as the ask path that already works — and the Supervisor picks it up and mints the pair. The new row arrives through the normal roster. Deliberately not in #5376: that PR's criterion says "read-only end to end", and a POST route would contradict it. Intake is its own PR, with its own criterion, and the write-surface question gets raised then rather than assumed now.
Three honest risks — all still open
The Fable line is a convention. Nothing mechanically stops an Operator settling a question that was really yours. Every self-resolve is logged and visible — reviewable, not prevented.
Hang detection is a heuristic. A 20-minute build, a permission prompt, and a true hang look identical in a stale transcript. The Digester will sometimes cry wolf.
Steering can land late. A parked "don't do that" is read at the next inbox drain — possibly after the thing it forbade. "Ignored" and "hasn't read it yet" look the same.
Proposed · 2026-08-05 · NOT as-built — full design at /a/operators-on-temporal.html
11Your question: "perhaps operators and the architect should be on Temporal?" The answer argued in the companion deck: Operator yes, Worker no, Architect not yet.
What dies: operator liveness/respawn (alive.ts, spawn.ts), block adoption, operator mail-rescue and mail-wake, operator auto-compact. What stays: the Digester, worker spawn/compaction, intake validation, and — deliberately — task.json + events.jsonl as the contract and the human timeline. This page's feed does not change shape.
Proposed · 2026-08-05 · NOT as-built — ships first, independent of the operator move
12Read-only stays the default: the one write path is a Temporal signal through a named, tested route — and the read-only invariant test gets amended by name, not worked around. Decision page: /a/operators-on-temporal.html, last slide.
Answered 2026-08-03, 22:57 — kept here, not restated
13This was the question, and it is still live — change the answer and the machinery reads the change. Nothing here is a re-ask.
All three steps landed inside a day, and the design changed twice more after you approved it: rounds now route through the Operator, and the loop narrowed from three per task to one. The next call is not on this page — it arrives when the intake PR opens and asks how much write surface AgentFlow should have. The full attack dossier (five skeptics, per-claim rulings, file:line citations) is preserved if you want the long version.