The more autonomy we give agents, the more deterministic code we rebuild around them. State machines, supervisors, sandboxes, merge gates. I keep seeing the same boundary in independently-built systems, and it isn't about intelligence. It's about authority.
tsukumo
Short version: the more autonomy we hand to agents, the more deterministic code we end up rebuilding around them. I keep running into the same seam in systems built by people who never talked to each other, and it isn't a story about model quality. It's about authority. An agent can exercise judgment: reason, plan, review, choose. That is not the same as holding the authority to turn a decision into a real change. Alignment tells an agent what it should do. Architecture decides what it can do. I'll point at niwa, an internal tool I build, where it makes the argument concrete.
Let me get the loaded phrase out of the way first, because someone will bring it up in the replies anyway.
"Code is law" is Lawrence Lessig's, and he meant it as a description: in software systems, the code is what actually constrains behavior, for better or worse. The crypto world turned it into a slogan, and then The DAO happened. An attacker drained around 3.6 million ETH through what they could plausibly call an intended feature of the contract. The code ran exactly as written. The community's response was to hard-fork Ethereum and reverse it, which is the whole ecosystem agreeing that the code being followed to the letter was the catastrophe, not the fix.
So if I'm going to reuse the phrase, I should be honest about what it does and doesn't mean. The DAO is not an argument against putting authority in code. It's an argument against putting unbounded authority in code with no gate and no way to intervene. That distinction is the whole essay. Code governing a system is not the same as code being sovereign over it. The boundary has to be bounded, and it has to be revocable.
The first wave of agentic systems chased one idea: give the model more. More tools, more context, more memory, more decisions, more agents orchestrating other agents. Autonomy as the goal.
Then you try to make one of these things actually run, and a second dynamic shows up.
The more cognitive capability you give an agent, the more deterministic machinery you build around it to make the capability safe to use. You add a state machine so the work can't skip a step. You add a supervisor so a stuck agent gets restarted instead of hanging. You put the merge behind a gate. You drop the agent into a sandbox. You move the durable state out of the agent entirely.
I've watched this happen in my own work, and I've watched it in projects built from completely different premises. That repetition is what this post is about.
Early on, most of us put the rules in the prompt. Never merge without review. Never read secrets. Always ask before doing X. Only do Y when Z.
Here's the problem. An instruction given to a probabilistic model is not a property of the system. There is a real, load-bearing difference between these two sentences:
You should not do X.
You cannot do X.
The first is a behavioral request. It shifts the distribution of what the model does. On a good day, with a clean context, it works. Under prompt injection, or after a long session where the instruction has scrolled out of the effective context, it degrades. The second sentence is a system property. It doesn't shift the odds. It removes the code path.
This is not a new idea. It's most of what computer security has been about for fifty years.
Linux doesn't ask a process nicely not to read a file it lacks permission for. The kernel refuses the syscall, and the process's intent never enters into it. A database doesn't request that a transaction respect a foreign key; it rejects the commit and the row never exists. Kubernetes rejects a non-conforming object at admission, before it's ever stored. An object-capability system doesn't check whether you're on a list; it hands you an unforgeable reference or it doesn't, and you can only act on what you hold.
We spent decades building isolation, access control, transactions, supervisors, schedulers, capability systems, and audit trails, all so that the important properties of a system don't depend on the good behavior of the thing running inside it. The question worth sitting with: why would we throw that away the moment the thing running inside can reason?
Behavioral request vs system property
Property
Prompt-level guardrail
Enforced boundary
Form
"You should not do X" in the system prompt
The code path for X does not exist for this actor
Fails under
Prompt injection, context loss, a confident wrong turn
A kernel/DB/VCS bug, not the model's mood
Analogue
A sign that says "authorized personnel only"
A door that only opens for a held key
Who decides
The model, at inference time
The system, at the gate
The reason this matters more with agents than with a plain program is uncomfortable, and I want to state it plainly rather than dress it up: an LLM agent is not just non-deterministic, it's steerable by its own inputs. A document it reads can carry an instruction. That's a property no ordinary process has. It makes "trust the process to behave" a weaker assumption than it already was, which is the opposite of a reason to relax the boundary.
I started noticing the same architecture elsewhere#
The project that made this click for me is LIZA, an open-source multi-agent system. I know the team, and I talk with one of their people regularly. I want to be careful here, because it would be easy and wrong to flatten LIZA into a version of what I build. It isn't. We start from different places and we're solving somewhat different problems. That's exactly why it's interesting.
LIZA's own framing is that it's a spec-driven system built for "doing things right on the first pass, with the auditability to prove it." Its architecture note is blunt about where the line sits, and it draws the same one this essay does, from the other direction. They arrived at that seam through hardening for on-call peace of mind. I arrived at it through a judgment-versus-authority obsession. Same seam, different road.
“LLM agents wrapped by code-enforced supervisors and working on isolated git worktrees. The supervisor does the deterministic code-enforced actions (worktree management, merges, TDD enforcement, etc), leaving the judgment to the agent.”
I read the code, not just the README, because the entire point of this essay is that the README is a behavioral claim and the code is the system property. Here's what's actually enforced in LIZA, with the parts I could verify:
Merge authority lives in code, not in a reviewer agent. A reviewer's approval is a precondition, not the act. The commit itself is a deterministic pipeline: it requires approved status, verifies the worktree HEAD still matches the commit that was approved (so nothing was slipped in after review), does a compare-and-swap merge with a guard against concurrent updates, runs integration tests, and rolls back on failure.
The reviewer's judgment is reduced to a typed verdict. The model's output collapses to APPROVED or REJECTED plus a reason. Everything downstream, quorum counting, an impact ratchet that refuses to silently downgrade severity, the cycle limit that escalates a stuck task, is plain code. The model decides whether. Code decides what that verdict is allowed to do.
The state machine has a hard transition guard. Task transitions are declared in config and validated at load. An attempt to move to a state that isn't a legal successor returns "invalid task transition." The model cannot invent a transition by asking for it.
State writes are single-writer, validated, and atomic. Every mutation goes through one locked path that validates the resulting state and refuses to persist an invalid one.
And, because I promised myself I'd stay honest: LIZA also has a prompt-level governance layer, a "behavioral contract" it leans on rhetorically, and that layer is exactly the kind of thing this essay is skeptical of. There's a TDD gate a doer can self-waive with a justification string. The pre-commit hook is documented as "a guard, not a lock" and fails open. LIZA converges with my thesis hardest precisely where it stops trusting the model: at the git and state kernel. Where it trusts the contract, it doesn't. That's not a knock on LIZA. It's the most useful data point in the whole comparison, because it shows the boundary isn't ideology. It's where the team decided a mistake was too expensive to leave to judgment.
One shared example is an anecdote. So before I introduce my own, here's the wider look I did, because two systems I like is exactly how you fool yourself into seeing a pattern that's really just your own taste reflected back.
I went through a spread of agent runtimes and frameworks and sorted each boundary into enforced in code versus requested via prompt. The enforced column is more crowded than the marketing would suggest, and the systems in it were built by teams that don't coordinate:
LangGraph models the workflow as a graph and its interrupt() genuinely suspends execution and freezes state until an explicit resume. The node's LLM can't skip the gate.
Temporal, Restate, DBOS, Cloudflare Durable Objects hold agent state outside the model as a journal or event log and deterministically replay it. The model cannot corrupt the record of what happened.
OpenHands and SWE-agent execute agent actions inside a real container. The security boundary is the container, not a line in the prompt.
The Claude Agent SDK has PreToolUse hooks that run as deterministic code before a tool call and can deny it outright, even in an otherwise permissive mode. That's a gate, not a suggestion.
E2B and Modal put untrusted agent code behind Firecracker microVMs and gVisor. Kernel-level isolation, the same machinery that runs serverless at the big clouds.
The honest counter-column matters just as much, and it's where a lot of "control" language lives. Prompt-orchestration handoffs, where the LLM simply picks the next agent, enforce nothing. Guardrails implemented as one model judging another model's output are probabilistic and can be jailbroken; that's a heuristic, not a property. MCP is a transport protocol, not a security boundary; the enforcement is whatever the host puts around it. Calling any of these a boundary is the exact confusion this essay is trying to clear up.
“Almost every "MIXED" system I looked at was the same shape: a deterministic shell around
an LLM-judged core. The model keeps the judgment. The shell keeps the authority.”
Which raises the actual question. Why? Why do independent teams, optimizing for different goals, keep rebuilding state machines and supervisors and capability boundaries around the model? Is this a handful of projects with similar taste, or the early outline of a general architecture?
That's when I should put my own cards on the table.
I kept hitting these boundaries while working with coding agents, and at some point I stopped trying to solve them inside the prompt and started building them into the terminal.
The result is niwa (庭, "garden"), an agentic terminal. It's a fork of WezTerm with an agent runtime, agentd, fused into the binary. The mental model is small: a tab is a project, a pane is an agent. Each pane can host a coding agent session, and agentd supervises the fleet, wake and sleep, context budget, lifecycle, reviews, and resets.
I'm not going to list features, because the features aren't the point and this isn't a launch. niwa is an internal daily driver. I use it to run the fleet that, among other things, helps build the things I ship. What's worth your attention is the authority model underneath it, because it's the same seam LIZA found from the other direction, and I want to show you the parts where I got it right and the parts where I haven't finished.
One design choice sets up everything else. In niwa, the relay carries all the content and the terminal carries only keystrokes. agentd does not read the agents' conversations or compose their work. Its only write into a pane is a fixed nudge, a literal "check your relay, handle your tasks, then continue." The agents fetch their own context and post their own results through a separate coordination bus. The daemon watches signals and governs the environment. That's already a split between cognition and control: the agent produces the work, the runtime governs its execution.
This is the clearest example in the system, and it's the direct mirror of what LIZA does.
When an agent thinks a task is done, it submits for review. agentd spins up an ephemeral reviewer: fresh context, the right review skill, a separate environment, adversarial by construction. The reviewer reads the work and returns a verdict.
The reviewer does not merge. It cannot. It writes a verdict file, and that's the extent of its power. The state machine and the merge authority live in the daemon.
text
doer → proposes completion
reviewer → exercises judgment (fresh context, adversarial)
agentd → validates the state transition is legal
agentd → executes the authorized merge (git merge --squash, under a merge lock)
The authority flow in niwa
On approve, the daemon performs the merge itself, serialized under a lock so two merges can't race. On reject, the findings go back to the doer for another round. After two rejects or a review timeout, it stops trying and escalates to a human. The reviewer decides whether the work is good. It does not decide what the system is allowed to do with that opinion.
When I finished this and then read LIZA's merge path, the resemblance was uncanny. Two codebases, one in Rust and one in Go, built by people with different mental models, both ending at: reviewer produces a typed verdict, deterministic code owns the commit, a tamper check sits between them. Neither of us designed for the other. We both stopped trusting the model at exactly the same place.
That proves nothing. It's text. Any agent can type any string. A completion claim isn't a completion, a verdict isn't an authorization, and a claimed identity isn't an identity.
niwa handles identity by not believing the claim. The daemon attributes every result by the outbox directory it was written to, and rewrites the author field to match the directory, overwriting whatever the agent declared. Identity becomes a property of where the write physically landed, not of what the payload asserts.
And here's the honest part, the part I'd want a skeptical engineer to hold me to. That directory boundary becomes a hard, kernel-enforced capability only when the sandbox is turned on, where each agent, behind macOS Seatbelt or Linux bubblewrap, can write to its own outbox and nothing else. The sandbox is built, and it's tested. Turning it on per agent is a deliberate choice, and I don't run it everywhere yet. With it off, outbox identity is a convention the runtime enforces on drain plus a nonce, not a wall an agent physically can't climb.
I'm telling you that on purpose. It's the cleanest illustration of this whole essay I have: the architecture is what makes the property enforceable, and turning it on is a separate, deliberate act. The gap between "we designed it to be enforceable" and "it is enforced, today, in this config" is the exact gap between architecture and a slogan. I'd rather show you the seam than paint over it.
The last piece is a shift in how I think about the workers themselves. I've stopped trying to keep an agent alive forever. Workers get spawned, reset, retired, and respawned. The context is cheap and throwaway. What has to survive lives outside the agent: tasks and messages on the relay, checkpoints in a doc store, a journal, receipts.
An agent, in this model, is disposable compute that reasons over durable external state. The industry already made this move once, with servers. We went from pets, the hand-nursed machine with a name, to cattle, the interchangeable instance you replace without ceremony, by pushing durable state out of the box and into a governed store. Agents rhyme with that.
I want to be careful with the analogy, though, because it's seductive and half-wrong. Cattle are deterministic. Reincarnate a container from the same image and you get the same behavior. An agent is stochastic and steerable; respawn it and it may do something different, and it can be nudged by its inputs. So the analogy licenses the architecture, stateless workers over durable state under a supervisor, but not the reliability. Containers made servers predictable. This does not make agents predictable. It makes their unpredictability survivable, by making sure the agent never holds the authority to make a mistake permanent.
There's a small, concrete instance of the same principle in how niwa resets a maxed-out agent. It avoids blind compaction. When an agent runs low on context, the watchdog asks for a checkpoint; the agent writes its continuation; the runtime verifies that file exists and is freshly written before it clears the session; a hook reinjects the state; the agent resumes clean. If the checkpoint isn't there, the runtime does not force the reset. It falls back to the safe path. The agent produces information. The runtime decides whether the precondition for the transition is actually met. Same shape as the merge gate, smaller stakes.
If I sketch what these systems have in common, it comes out as two planes.
The two planes. The cognitive plane (probabilistic — reasoning, planning, review) proposes; the control plane (deterministic — identity, permissions, state transitions, execution authority, isolation, audit) validates and commits. The agent decides whether the work is good; the system decides what that verdict is allowed to do.
A cognitive plane that is probabilistic: reasoning, planning, coding, investigation, review, interpretation. This is what the model is for, and it's genuinely good at it.
A control plane that is deterministic: identity, permissions, lifecycle, state transitions, execution authority, isolation, validation, escalation, audit. This is what code is for.
I don't want to coin a framework or sell you a product; the two-plane split above is a mental model, not a system I'm pitching. But it's a useful lens, and it's worth noting that in my own setup the control plane isn't hypothetical, it's assembled from tools I already run: a relay for durable coordination state, a doc store for external context, a session recorder for the audit trail. The point isn't the specific tools. It's that "put the authority in deterministic code" stopped being a slogan the moment it had to be actual running software with names and configs and edges I'm still hardening.
The reason none of this should feel novel is that the strongest version of the idea is decades old, and it's worth naming precisely so it doesn't sound like hand-waving.
The tightest analogy is the object-capability model: no ambient authority, you can only act on references you actually hold. seL4 is the existence proof that you can build a kernel with a machine-checked guarantee about exactly this, though even seL4 is verified against a spec under stated assumptions about the compiler and hardware, so "formally verified" is a precise claim, not a magic word. The pattern that maps most directly to agents, though, is propose versus commit. A Raft leader proposes a log entry; it's committed only once a quorum has durably stored it. A two-phase-commit coordinator owns the single commit decision. A pull request is a proposal; the merge gate is the authority. In every one of these, the actor can propose a state transition and the system owns the commit. "Agents propose transitions, they don't own them" is not a new principle. It's that one, with a probabilistic proposer.
propose ≠ commit
The oldest pattern in the room
In Raft, two-phase commit, write-ahead logs, and code review, the actor proposes and the system commits. Agents are the newest proposer, not a new pattern.
I'd be doing the exact thing I criticize, treating a claim as a property because I asserted it, if I didn't try to break this. Here are the objections I take seriously.
The Bitter Lesson. Rich Sutton's argument is that hand-built structure tends to get eaten by general methods plus more compute. My deterministic control plane is hand-built structure. And there's real evidence in the uncomfortable direction: minimal-scaffold coding agents, some barely more than a bash loop, are competitive with feature-heavy harnesses on SWE-bench, because strong models do better with less orchestration in the way. If reasoning scaffolds dissolve, why not authority scaffolds?
Here's the narrowing I think survives it, and I hold it honestly rather than defensively. The scaffolding that dissolves is the kind that substitutes for capability: reasoning chains, planning heuristics, prompt rigging. That should dissolve, and good riddance. The boundary that stays is the kind that governs a consequence the model has no authority to waive: money moving, a permission granted, a DROP TABLE, a force-push to main. That persists because it isn't about how smart the model is. It's about blast radius. Note that the same bash-loop agent that thins the reasoning harness still runs inside a container. The cognitive scaffold got thinner. The control plane didn't move.
Selection bias. Am I seeing convergence, or pattern-matching on systems I already like? Fair. So the honest form of the claim is not "this is a law" but "this is a falsifiable bet": as the stakes and irreversibility of an action rise, systems will re-grow a deterministic boundary around it, and where they don't, the blast radius will turn out to be trivial. There are real counter-examples to sit with, not wave away. Voyager, a GPT-4 agent that writes, runs, and commits its own skills into a persistent library, does better precisely because it owns more of the loop. Where the consequences are cheap and reversible, more model authority can win. My claim is bounded to the expensive, irreversible end.
The line is fuzzy. Tool selection is a kind of authority. Planning allocates future action. You cannot pre-encode which tool to call for an unseen task, so some authority has to live in the model. True. Judgment and authority are a gradient, not a clean fence, and I don't want to oversell the dichotomy. The design goal isn't to maximize the number of gates. It's to minimize the irreversible blast radius, and to accept that a gate has a false-block cost and a tail it can't foresee. A control plane that blocks everything novel is its own kind of failure.
I think the thesis holds when it's narrowed to authority over irreversible consequences. I think it's false if stated as "all structure persists." The Bitter Lesson and the bash-loop agents will eat the second version. They don't touch the first.
So I'll end where I'm genuinely unsure rather than on a tidy bow.
For a while, a lot of us assumed that making software more intelligent meant gradually removing the rigid structures around it. What seems to be happening is closer to the opposite. The more capable the component is of unpredictable, consequential decisions, the more the boundary around its authority matters. LIZA rebuilt that boundary. niwa rebuilt it. Thirty other systems rebuilt pieces of it. None of us coordinated.
Maybe that's taste. Or maybe we're collectively rediscovering the control-plane architecture of agentic software, the way the industry rediscovered the same isolation and transaction and supervision primitives every time a new kind of untrusted, powerful process showed up. I don't know yet. It's a bet, and I've told you how it could be wrong.
What I'm fairly sure of is the smaller claim underneath it. The LLM is not the runtime. It is not the kernel. It is not the authority. It's a probabilistic reasoning engine running inside a deterministic system, and the system is what governs it.
Code is still law. Just not sovereign.
If your team is putting agents into production and running into the judgment-versus-authority line, this is the kind of architecture work we do. No pitch here: if the essay was useful, that's enough.
What is the difference between judgment and authority for an AI agent?
Judgment is the model's ability to reason, plan, investigate, write code, and choose among strategies. Authority is the power to turn a decision into a real change to the system: merge the branch, grant the permission, move the money, run the migration. The argument here is that judgment can live in a probabilistic model while authority should live in deterministic code the model can propose to but cannot exercise on its own.
Why aren't prompt instructions like 'never merge without review' enough?
Because an instruction to a probabilistic model is a behavioral request, not a system property. 'You should not do X' and 'you cannot do X' are different guarantees. The first shifts the odds; the second removes the code path. A serious system enforces its invariants the way a database enforces a foreign key or a kernel enforces file permissions: the violating operation is refused, not discouraged.
Are AI agent frameworks converging on a common architecture?
There is a visible pattern, though I'd call it a hypothesis under test rather than a law. Across LangGraph, Temporal, OpenHands, the Claude Agent SDK, LIZA, niwa, and others, independently-built systems keep rebuilding the same primitives: explicit state machines, approval interrupts, external durable state, sandboxed execution, and capability-based permissions. The falsifiable version: as the stakes and irreversibility of an action rise, systems re-grow a deterministic boundary around it.
What is niwa?
niwa is an agentic terminal I build and use internally: a WezTerm fork with an agent runtime, agentd, fused into the binary. A tab is a project, a pane is an agent. It supervises a fleet of coding agents through a deterministic control plane: a review gate that merges daemon-side, an optional kernel sandbox per agent, and a checkpoint handshake for context resets. It is an internal daily driver, not a launched product.
Doesn't a deterministic control plane contradict the Bitter Lesson?
Partly, and that's the sharpest objection. Scaffolding that substitutes for capability, such as reasoning chains and planning heuristics, does tend to dissolve as models get stronger. A bare-loop coding agent can match a feature-heavy harness. But the boundary that stays is the one that governs consequences the model has no authority to waive: an irreversible write, a permission grant, a spend. That persists because it is about blast radius, not intelligence.