How to Work With Agents in 2026
An agent fleet will hand you a month of plausible work every week. The developers pulling ahead in 2026 aren't the ones running the most agents — they're the ones who can tell fastest whether the work that came back is true.
That skill has a name in my notes: catching the false green. A red test tells you something. A green test that never ran your code tells you nothing while feeling like everything. Mine: agents in an isolated checkout resolved absolute paths back to the main checkout, edited files there, then ran the suite against the isolated copy. Every run passed, for days. The suite was honest; it just never looked at my code. The first question I ask of any result now isn't "did it pass" — it's "what exactly did it run, and where."
A year of running agents in anger taught me that lesson and a few dozen like it, in codebases that have to ship no matter what my tooling looks like. What follows is the compiled version — a field manual you can start using Monday morning, the part I could still be wrong about, and the reading list that got me here.
What I've distilled
The bottleneck moved. It used to be generation; it's now verification. Most of what follows is that one lesson wearing different clothes.
Fan out on reading, stay single-threaded on writing. Read-heavy work parallelizes beautifully: five agents mapping five subsystems finish in the time of the slowest, and the results merge cleanly because reading doesn't conflict. Parallel writers fragment context and make quietly incompatible decisions you pay for at integration time. If you must write in parallel, give each agent its own checkout and let one agent own each file. The boundary is read-versus-write, not task size.
Verify the harness before you believe the result. Measuring a bug recently, I built a results table that came back unanimous and completely wrong: my shell doesn't word-split an unquoted variable, so every variant I thought I was testing ran as one nonsense argument, and every row obligingly confirmed my hypothesis. A measurement that agrees with you on the first try deserves more suspicion than one that doesn't.
Use a cold reviewer. The agent that wrote the code inherits every assumption that produced the bug. A fresh one, given the diff and no history, finds what the author structurally cannot. Best cost-to-bugs-caught ratio I've found. The corollary: reviewers are sometimes wrong. I've had one confidently flag a fix that measurement later reversed, and another correctly refuse a fix I was pushing for. Reviews are evidence, not verdicts.
The loop with its real price tag: a planner produces six plans across four waves for 322.7k tokens, a separate checker tears into them for another 202.9k and returns three warnings, and a revision pass runs. Verifying cost more wall-clock than planning did — and it's the part that makes the rest trustworthy.
Structured contracts beat scraping prose. My delegation used to work by having a sub-agent write a summary and parsing it out of terminal output with string matching. That works until the model phrases things differently, then fails silently and tells you days later. Define the shape of the answer up front. Prose is for humans; machines should exchange schemas.
Measure continuously, or you'll believe your own fixes. A metric you read once is indistinguishable from good news. A job every morning grades the previous day's agent traffic. Recently it told me a broken feature had recovered — it hadn't; a change in how the scanner walked the message files made old records newly visible. What caught it: the number sat at exactly the same value for three days while sixteen new events should have moved it.
Don't default to your most expensive model. Hard reasoning and review get the expensive one; mechanical work does not. The cost difference is large and the quality difference on mechanical work is close to zero.
Principles are cheap to state and expensive to arrive at. What follows is the procedure layer they compile into — each entry earned by a specific failure.
The field manual
Nothing in this section is specific to my stack. I learned it across four unrelated codebases — a co-op game, a client's CMS and localization pipeline, this product, and the journal that runs my day — and the same failures kept resurfacing in all four.
1. Give every agent its own copy, then verify the isolation
Every agent that writes gets its own checkout; git worktrees make that nearly free. But isolation fails quietly, and the false green from the opening has a root cause worth naming: my own instruction files were the map they followed. The docs and memory files my agents read were full of absolute paths to the main checkout, so when an agent needed to find something, it searched the path it had been shown, found the wrong copy, and edited it. The fix wasn't restructuring the checkouts — it was a standing instruction to search from . and report relative paths, validated by re-running the exact task that had failed. Whatever you write down for your agents, they will follow it into a wall.
The habits that keep isolation real: after any edit, run git status in the copy that runs the tests — if your files don't show as modified there, the edit landed somewhere else and every green after it is noise. Each copy gets its own full dependency install; a cleverly shared node_modules resolves workspace packages back to the canonical source, and your edits silently stop mattering. And prune. Worktrees accumulate, and a pile of stale agent worktrees looks exactly like unshipped work — I once braced to recover "lost" changes that turned out to be three stale worktrees and some scratch files. Prune in the right order, though: in each worktree run git status for dirty files, then compare the local HEAD against the integration branch — git log origin/main..HEAD — for commits that never left the machine. A remote-ref comparison like git log origin/main..origin/branch proves the branch merged, not that the worktree is empty-handed: it never examines the worktree's HEAD at all, and git status only mentions unpushed commits when an upstream happens to be configured. Mine actually held one uncommitted rework worth rescuing; everything else dissolved when the remote comparison came back empty.
2. Make verification one command that adapts
The game project's gate is a script called ./vibe. The important part isn't what it runs — it's that it detects the situation and does the right thing. Editor open? It builds a disposable sandbox checkout and clones the 1.8 GB import cache in seven seconds via copy-on-write. Editor closed? It runs in place. Nobody learns two commands, so nobody picks the wrong one, and the gate actually runs.
Inside a gate, the details decide whether green means anything. Use a sentinel: the build tool only invokes the entry point you registered if compilation succeeded, so a printed marker is positive proof by construction — then classify results on multiple signals with an explicit infra-failure route, so "nothing recognizable happened" is never reported as pass or fail. A discovery-based suite must assert that it discovered something: a scene suite that enumerates zero scenes passes forever. Never pipe a gate command — typecheck | tail reports tail's exit status, and I've watched typecheck "pass" twice while failing with seven errors.
And find out what your CI actually runs before debugging against it. One backend had three test configs; the docs pointed at the one nothing used. An hour went into "fixing" flaky failures that CI had never seen, plus a shipped timeout fix that was inert. package.json scripts are the source of truth, not the repo's description of itself.
3. Test the artifact that ships, not a fixture that flatters
The clearest version: a game's spawn system had thorough tests, every one green, while the shipping scene was broken — two spawn points collapsed onto the same coordinates and floating off the ground. Every test had built its spawn points in code; none read the scene file players would actually load. The replacement test reads the authored scene, and its discovery loop deliberately mirrors the runtime's, with a comment explaining that it must match "or this file gates something the game does not do."
The same failure in web clothes: a value crossed a framework boundary and got URL-encoded twice; the reader threw, a catch returned null, and the feature shipped silently broken for weeks — surfacing as zero rows in someone else's report. Three separate test files were green the whole time, because all three hand-built the input single-encoded: a value production never produces.
One end-to-end test through the real writer beats three through a fixture. Route-stubbed browser tests share the flaw and hide it better — stubs resolve instantly, so every timing-shaped defect (empty states flashing before data, races on first load) is invisible until a real backend is behind the page.
When the question is about a live system, the live system is the oracle. A dispute about which locales were actually reachable survived two repo-diffing attempts — one produced a false finding, the other a false exoneration — and then died in four minutes of driving the production site. When a bug only reproduces in a deployed environment, prove the fix A/B/A: deploy the unfixed ref and measure the failure, deploy the fix and measure the pass, then deploy the unfixed ref again — the step everyone skips, and the one that rules out coincidence. Then restore the fix and verify it once more, because an experiment that ends on step three leaves the broken build serving users; run the whole dance in a production-like environment if you can't afford the window. And keep live end-to-end tests gated behind an env flag instead of deleting them; a mocked suite stays green straight through a dead upstream dependency.
4. Verification tools have carrying costs
I built an agent-run structural audit for game levels, on the theory that agents are bad at making a level look good and good at checking its structure. The theory held — it caught spawn points inside a building's footprint that two humans looking at the render had missed. I deleted it anyway. Its manifest hard-coded scene object names, so every legitimate layout pass broke it, and its findings started reading as regressions. Six hundred lines gone; the durable subset — spawn geometry — survives as a normal test in the gate. The rule that fell out: keep assertions that encode invariants; delete assertions that encode inventories. "A player must land on the ground" earns its keep forever. "These nine trees exist" is a tax on every change.
The cheaper sibling failure: a merge driver declared in .gitattributes since the project's first commit, and never actually installed on any machine. Git doesn't error on an undefined merge driver — it silently falls back to line-based merging, which shreds scene files. Every merge conflict for the life of the project had arrived pre-broken, and nobody knew the policy was failing. A declared policy isn't a policy until something verifies it's installed.
5. Run two review passes that can't overlap — then review the reviewer
The cold reviewer from earlier, operationalized: two passes with disjoint mandates. A quality pass scoped to exclude correctness (reuse, simplification, altitude — is each piece solved at the right layer), and an independent correctness pass from a different model family. Their findings barely overlap and both are real — the quality pass once caught a fourth, weakest reimplementation of an environment check that failed open on the platform most of the team used; the correctness pass caught the pipe trick from entry 2 in the wild — a sync script reporting "Already up to date" and exiting 0 against an unreachable remote.
When reviewing anyone's tests — agent or human — ask what the test structurally cannot catch. I reviewed a compare-and-swap — an update that must read and write in one atomic step — whose cited integration test lived in a closed PR, merged nowhere, and ran two sequentially-awaited updates. A sequential test cannot reach a race by construction, which is exactly how a non-atomic swap survived it.
Then hold the reviewers to the same standard as the code: verify findings against ground truth before acting on them. When both passes independently flag the same line, treat it as near-certain and move fast. Re-run the reviewer against your own fix delta before pushing; it once caught a regression the fixes themselves introduced. And the one irreversible step — the merge — is always a human's yes, even on a fully green report.
6. Default destructive operations to dry-run — and define "shipped"
A migration tool I wrote to repair split translation strings ran dry by default. The dry run caught two bugs in the tool's own classifier — it misread compact CJK translations as truncated, and flagged a complete Italian sentence as a fragment. A later re-check found worse: the API returned versions oldest-first, so --apply would have overwritten weeks of human corrections with resurrected machine translation. Both catches happened while the damage was still hypothetical, and dry-run-by-default is the only reason.
The other half is vocabulary. A fix was once announced as done eight minutes before the fixing commit existed — the "fresh sync" in the announcement had run on the old version and destroyed a week of hand-repairs. Merged, released, deployed, and reprocessed are four different claims; state which one you mean, with a timestamp. And watch where your gates sit in the pipeline: a disk-space preflight that ran before tagging failed by 0.3 GB, downstream steps reported "skipped" rather than "failed," and production served stale code for 37 hours while every dashboard looked calm. The remedy is mechanical: treat a skipped step in a release pipeline as a failed one and alert on it — a release run should end "published" or red, never quietly neither.
7. Memory is a curation problem, not a storage problem
My always-loaded global rules are about 120 lines. The memory behind them is four hundred–odd files, scoped to projects, skills, and specialist agents. That ratio is the design: a rule gets promoted into the always-on file only after it's been earned repeatedly, and it carries the date, the incident, and the human's actual words. A bare imperative gets pattern-matched; a rule with its reason attached can be judged at the edge cases.
The loop that keeps it honest is two-tier: a staging file the agent appends provisional notes to, and a reviewed playbook that a periodic audit promotes into — with verification against ground truth before promotion, and deletion for anything that fails. Recalled memories arrive labeled with their age, because memory is a point-in-time observation, not live state. Pointers rot: one agent produced a confident false finding by diffing a live repo against an archived one, because two old memory entries still named the dead repo as the place to look.
The counterexample sits in my own setup: a permission allowlist that accreted 61 frozen one-off approvals — entire scripts pinned verbatim as "allowed prefixes," never to match anything again. Same accumulation pressure as the memory system, no curation loop, pure liability. Storage is not the feature. Curation is the feature.
8. Build friction for the human, too
The strangest tool in my harness quizzes me. It tests my understanding against the written record — never against what an agent remembers saying — and the first run scored 4/8. Every miss was on machine-verified mechanics; every hit was a decision I'd made myself. That's the finding: your model of the system is weakest exactly where the machine did the verifying, and if you can't articulate why a gate is trustworthy, you won't notice when it stops being. The practice needs its own curation, too — this morning it asked me about a month-old resolved incident, and the correct response was to retire the question class, not to answer it.
The companion habit is labeling claims by evidence level — Opinion, Signal, Evidence, Validated, Measured — before acting on them. The sharpest catch it produced: "there is no capacity problem," written as fact, was Opinion dressed as Evidence, and it was refuted by a measurement that had been in my hands the whole time and lost out to a search result. When your own data disagrees with the web, believe your data.
Two smaller habits round it out. Automated summaries state their own evidence limits — "these sources were unavailable and are not being treated as clear" — so absence of alarm never reads as all-clear. And corrections stack visibly on top of the claims they supersede rather than replacing them, so the next session, human or agent, doesn't re-derive a conclusion the record already killed.
What I run
Here's what those practices add up to at my desk. A gateway runs a handful of long-lived agents, each with its own personality, memory, and tools rather than a fresh instance I reconfigure every session. They remember last week, and they remember each other. Scheduled jobs drive work overnight, spawning specialist sub-agents into isolated checkouts to run scoped tasks and open pull requests, so I wake to something to react to instead of a cold start.
What the overnight loop hands back, on a phone before I've opened a laptop: one decision that actually needs me, three things that are stuck and why, what the night shift shipped, and what's in flight and who owns it.
Delegation runs the same way down a level. An agent dispatches a specialist, the specialist reports back, and the thing that stops is the part that needs a human:
A read-only architecture scout returns, and the agent stops at the gate: approve this shape and it gets split into parts and filed as real work. The stop is the feature.
Then the part that makes it a system rather than a pile of scripts: every morning a headless job grades all of it. Today — 712 model generations, 88 traces, 150 scheduled runs, zero watchdog kills, zero context overflows, zero auth failures. The green numbers are the boring half. The useful half: a cheaper background agent logged nine generations that each died in under a millisecond, before a token reached a provider. Its credit balance had hit zero. That's a billing problem wearing an AI costume, and I only know which because something counts.
One build from last month changed how I think about the rest. My hunch was that agents should be live 3D characters reflecting what each is doing, not names and status badges. The 3D was the easy half. The hard half was that "what this agent is doing right now" had to stop being a vibe and become a contract — a fixed vocabulary of phases as an integer enum that three separate codebases must agree on. Deciding what an agent should look like forced me to say precisely what states an agent can be in.
Where I'm taking it
Everything above is scaffolding I built by hand, one paper cut at a time — and the practices need nothing from my product; steal them for whatever harness you run. Or skip the year of paper cuts: I'm building Vibery so the discipline comes built in. That's the pitch. Here's the bet behind it, and how much of it I can actually back.
The pain that motivates it isn't coding — it's coordination. Run enough agents and you become their message bus: carrying context between them, remembering what the overnight job decided, noticing two of them about to do the same work. Commanding a fleet is fun; being its message bus is exhausting, and it worsens with every agent you add. (Local-first, too — your agents, your keys, your data, your machine — which leaves no lock-in to fall back on, so the only reason anyone keeps using it is that it's better.)
The bet: the game isn't a skin on the harness. It's the shared model. Gamification is points bolted onto work that was going to happen anyway — a veneer pointed at one party. A twin — a lossy simulation of the real engineering system — runs in both directions: I read the game state to decide what to do next, and the agents read the same state to decide what they do next. A score that exists only to motivate a human is a dark pattern with extra steps; a score both parties optimize against, in one vocabulary, is a control surface that happens to be fun. And compression is the mechanism, not a compromise — you can't hold forty concurrent agents in your head, but you can hold engineering is busy, the deck is clear, something's on fire in ops.
Here's what exists today. The Commander's Log, on production, this morning:
Real state, not a mockup: a failing workflow, the exact merge that caused it, and three things I can do about it — one of which is to ask the ops agent.
It works and I use it daily. But it's rows, cards, a badge, a number — a good dashboard wearing the vocabulary of a game. So I audited how far the twin actually goes rather than trusting my own README. Agent presence is wired: one payload crosses into the 3D world every ten seconds, and the crew really do stand in rooms and sit down to work. The work stops at the border — ships, pull requests, XP, rank all live in the web UI and never reach the world. The most instructive finding: a channel exists for pushing a code red into the station, and both ends are built — the web composes the command, Unity dims the lights and sounds the alarms — but they don't talk: the web sends to one object and the handler lives on another. Each half is perfectly correct alone, so no test caught it. The single path by which real trouble was supposed to become visible in the world has never once fired.
The tell: the code red washes the panels red, and the world behind them carries on unaffected. The dashboard knows. The station doesn't.
Same story on the agent side. The scoreboard is real and specific — 15.5M tokens today, attributed per agent — and every agent has a tool that reads its own progression. Nothing tells them to use it, and nothing consumes it. The read path exists; the feedback loop doesn't.
So here's the hypothesis, written so it can fail. Wrapping a multi-agent system in an integrated game layer makes managing many agents easier, more enjoyable, and measurably more effective than a terminal or a purpose-built harness. Three predictions: legibility — time to answer "what changed overnight, who's blocked, what needs me" beats the terminal and stays roughly flat as the fleet grows; capacity — the number of concurrent agents I can run before I become the bottleneck rises, the one I care most about because it's the pain I actually have; outcomes — agents treating game state as an objective rather than a readout produce a measurable delta against the same fleet with that signal removed.
The cleanest falsifier is also the cheapest: turn the game layer off and see whether anything changes. Today nothing would, because the loop isn't closed. That isn't a defense; it's the baseline I have to beat. And the real opponent isn't nothing — it's a good terminal: fast, composable, scriptable, no loading screen. If it wins, it should win.
How much do I know? The bottleneck being verification is measured — my own numbers keep saying it. The twin making agents easier to manage at scale is an opinion, untested by construction, since the loop that would test it isn't connected yet. Everything here is the design for the experiment, not its result. I'm building for the solo builder first because I'm the user, so I can't lie to myself about whether it works — but nothing about "a fleet of agents doing work you need to see, steer, and trust" is specific to code, and with a team the twin stops being a private dashboard and becomes a shared world model a group can point at.
The reading list
All of it stands on other people's work. One of my own agents runs a rolling landscape scan and files it to shared storage, so this list maintains itself; these are the pieces that actually changed how I operate, rather than everything that crossed the wire.
The primary texts. Anthropic's Building Effective Agents is still the clearest statement of the workflow-versus-agent distinction, and the reason I stopped reaching for an agent where a pipeline would do. Effective Context Engineering for AI Agents reframed my whole prompt architecture around keeping the smallest high-signal working set in context — that post is directly responsible for an audit that found one of my agents 24% over its own system-prompt budget. Managed Agents is the cleanest articulation of decoupling the brain from the hands. OpenAI's prompt engineering guide is unglamorous and still correct: instructions first, show the output shape, say what to do rather than only what not to.
The protocol layer. Model Context Protocol is the closest thing we have to a standard for giving agents hands, and the AAIF's MCP is growing up on the stateless RC is worth reading before you build session logic you'll have to unbuild.
Evals, and their limits. SWE-bench is saturated at the top — leaders cluster in the high eighties and above on Verified, which is why the Steel leaderboard and BenchLM are more useful than a single number, and why Terminal-Bench matters: it measures the thing I actually do all day. Treat all of them as weak evidence about your codebase.
The operational reality nobody writes about. Your agent changed under the model is the piece I most wish I'd read a year earlier. A model id is not a version. Your harness can change under you without a single line of your code moving, which is the strongest argument I know for owning your own evals.
The framework landscape, if you're choosing: Composio's side-by-side of the major SDKs is the least breathless comparison I've found, and Supervisor-Skills is worth a read on delegation structure specifically.
Published 2026-08-02. Updated 2026-08-05 — added the field manual. Updated 2026-08-06 — rewritten front to back: the lessons now lead, the reading list closes, and the product section runs at half its former length.