Where agents belong in the loop
Reversibility, observability, blast radius. The criteria for handing off.
A typical engineering ticket comes in pieces: design a small feature, write the contracts, build the UI, add unit and end-to-end tests, run the database migration, deploy it. One common pattern is to hand the entire ticket to an AI coding agent and ask it to ship, and another is to keep agents away from it until the next model lands. Both treat the ticket as one job, and it is not one job. It is a stack of slices with very different reversibility, observability, blast radius, and substrate profiles, and each slice deserves its own placement decision.
This is a playbook for placing agents slice by slice, and the lever you control throughout is the substrate the agent runs on rather than the model itself.
Place agents per slice instead of per ticket
Stop treating a ticket as a single placement decision and make the call per slice instead. The answer can be agent, gated agent, or human, and it can vary across slices inside the same ticket.
The slice menu I carry into every placement conversation:
- spec gathering
- solution document
- contracts and schema
- UI implementation
- unit tests
- end-to-end tests
- code review
- database migrations
- deployment and rollout
- grunt-work automation (release notes, changelogs)
Each row scores differently: UI implementation scores high on reversibility and is well bounded by typed components, while database migrations score low on reversibility and high on blast radius. Treating the whole ticket as one job forces one decision onto very different work, and treating each slice separately gets you a different answer per row, in the same ticket, on the same model.
Score the slice on three criteria
Before handing a slice to an agent, score it on three things. All three are properties of the slice, and the model does not move any of them.
Reversibility. Can the action be undone in minutes, locally, without coordinating with someone else? Editing a file in a branch is reversible. Sending a message to a customer is not, and neither is dropping a database column. The faster and more local the rollback, the more autonomy a slice can carry.
Observability. Can a human read what the agent did fast enough, and clearly enough, to catch a wrong answer before damage is done? A diff is observable, while a multi-step tool sequence with side effects across systems is much less so. The worst case is output that looks fine, is wrong, and sits unnoticed for weeks.
Blast radius. How many records, customers, services, or dollars does one action touch? A sandbox with one synthetic record is small, and a production database write at scale is large. Blast radius is how big the regret is if you are wrong.
The mistake I see most often is scoring on one lens and skipping the others. A team optimizes for reversibility, decides it can roll back, and ignores observability, which is the lens that would have told anyone a rollback was needed, so the agent quietly produces wrong output for weeks while the rollback plan sits there, pristine and unused.
Even a capable model on a low-reversibility, low-observability slice still has to be gated, because nothing about the model raises the slice's score. Raising the score is substrate work.
Build the substrate; that's the lever you control
Watch two teams with the same model access work on the same slice: one team's agent ships useful work, the other's is unusable, and the difference is rarely the model.
Substrate is the environment the agent runs in, and it decides what the agent can be trusted with. Five components, all of them yours to control:
- Institutional memory the agent can read at runtime: the team's decisions, conventions, and in-flight context.
- General AI infrastructure: the IDE setup, the model access tier the org pays for, and the in-house automations already in place.
- Tool coverage: typed connectors into the systems the agent acts on (the design tool, the component library, the database, the build pipeline).
- Deterministic verification: typed contracts, lint, CI, and tests dense enough that the agent's output can be checked without a human in the path.
- Reviewer bandwidth: humans who can read agent output at the rate it arrives, without a queue silently growing behind them.
A few months back my team was choosing where to place an agent first. We picked UI implementation, because the slice scored well on reversibility (anything wrong shows up in a diff) and well on blast radius (a broken layout in a branch is the worst case). The first attempts were mediocre. We connected the IDE to the design tool the designers were already using, added a typed integration to the team's component library, and then tightened custom rules week after week to catch the mistakes the agent kept repeating. The model did not change once in those weeks, and by the end of the run a large fraction of the team's UI work had shifted from human-led to agent-led, on the same model that had been mediocre at the start.
Anthropic's measurement work on real agent traffic makes a similar point: by the 750th session, operators grant auto-approve about twice as often as new operators do on the same kinds of tasks. The criteria stay the same, and more slices pass them over time as evidence and substrate build up.
Waiting for the next model is the slowest version of this work, because the next model arrives into the same substrate gaps the current one has.
Be pessimistic on low-reversibility, iterative everywhere else
Your stance on a slice splits along reversibility.
Where reversibility is low (database migrations, irreversible deployments, anything irreversible by policy, external messages), keep the agent out of the final action until the guardrails are proven and the rollback path is bulletproof. The agent can still help with a draft, but the final action stays gated.
Where reversibility is high (UI work, unit tests, code review comments, document drafts), the default flips: put the agent in the loop now and tighten guardrails as you learn. An unhelpful agent comment costs the reviewer the moment it takes to skip it, and you can pay that price hundreds of times while you learn. A bad migration gives you no equivalent way to learn cheaply.
This asymmetry lets a team make progress without betting the business. My team introduced agent code review knowing the first iterations would be mostly noise. We told reviewers to skip the noise, tightened what the agent was allowed to comment on round after round, and watched the noise drop and the signal rise. The whole experiment stayed cheap for a reason that had nothing to do with us being careful: ignoring a comment costs a reviewer almost nothing.
It is easy to mistake "we have an agent here" for "the guardrails work". On a high-reversibility slice the guardrails still matter, but you get to build them in the open instead of perfecting them before anyone starts.
Design guardrails for human over-delegation as well as model error
Most guardrail design assumes the agent is the thing that fails, and sometimes the failing part is the operator.
A junior team member of ours started delegating everything, and whole slices that should have stayed on the per-slice menu were going to agents wholesale. The guardrails the team had built caught the pattern early, which I would like to credit to foresight, except that we had designed them for "model writes wrong code" and what they caught was "human handed off a slice that should not have left their desk".
So the guardrails have to catch human-side failures too. Some of the same mechanisms (review gates, contract enforcement, the deterministic verification above) double as a safety net against over-delegation, and if you design only for model error you miss the operator who hands off work that should have stayed with them. The people most likely to do that are the most junior on the team, which makes a certain amount of sense: the agent's output looks like the biggest upgrade to whoever can do the least without it, and spotting where that output is wrong is exactly the judgment a junior has not built yet.
Treat placement as perishable; re-tier as substrate grows
Whatever placement map you draw today will be wrong within a year.
That is not a flaw in the criteria, which stay stable. What grows is the number of slices that pass them, because the substrate keeps changing: a slice that was "do not hand off" twelve months ago can be a fully autonomous loop today, on a substrate that did not exist then.
The clearest example on my team is the loop that watches for crash signals, files a ticket, attempts a fix on a narrow class of bugs, and raises a PR. I would not have believed that loop was possible six to twelve months ago, and the criteria are not what changed. The five substrate components each crossed the bar one by one, and once every lens passed, the slice moved up a tier.
So make re-tiering routine: hold the criteria steady, and re-check which slices pass every quarter or whenever a substrate component changes (a new integration, a model upgrade). The conversation costs half an hour, and skipping it costs a map of where agents belong that goes quietly wrong one slice at a time.
When not to
A few zones stay out of bounds however well a slice scores on the three criteria.
Anything irreversible by policy (billing actions, PII handling, security-sensitive permission changes) is gated by the policy rather than by blast-radius math. The math may well say small impact, and the policy still says human in the loop. See security and privacy non-negotiables and the ethics of AI on a team.
Cost is a fourth lens I have skipped here, and cost, latency, reliability as first-class covers it. A slice can pass reversibility, observability, and blast radius and still fail on token economics, in which case the agent does not belong there yet.
Every section above is the same loop run from a different starting point:
- Decompose the ticket.
- Score each slice on reversibility, observability, and blast radius.
- Build the substrate.
- Hold the criteria steady.
- Re-tier when the substrate moves.
None of it waits on a better model. The model my team started the UI run with was the same one running at the end, and everything that improved in between was substrate we built.