Part 1 · Laws 01–05
Context & Reliability
How agents see the world, and where they break.
01 Law of Context Decay Most agent failures start with the wrong context.

The principle
Most bad outputs come from missing, stale, or conflicting context, not from a model that can't think. The model often reasons fine over the picture it was handed and still lands wrong, because the picture was wrong to begin with. Bad context produces confident bad answers.
Why it happens
A model treats the context window as the world. If that window contains a stale record, a missing constraint, or two facts that conflict, the model has no reliable built-in sense that one is old or suspect. Preference tuning can make this worse by nudging the model toward the framing it was given. The result is not always weak reasoning. Often it is competent reasoning over a bad picture of reality. A stronger model can still fail if the context it sees is stale, partial, or contradictory.
Watch for
- The same question gives different answers depending on which session or document was loaded first.
- Outputs confidently reference facts that are real but out of date, or contradict a source you know is in the window.
- Bumping to a larger or newer model produces no measurable accuracy gain on the failing cases.
In practice
Your support agent keeps insisting a customer's subscription is active when it was cancelled last week, so the team files a ticket to upgrade to a smarter model. The real culprit: the RAG pipeline pulls a 30-day-old cached account snapshot, and the agent reasons flawlessly over stale data. Before swapping models, log the exact context the agent saw on three bad runs; you will usually find a contradiction or a stale record, not a dumb model. Fix the freshness and the 'reasoning bug' evaporates.
Apply it
- On every bad run, dump and read the exact context the model saw before blaming the model.
- Stamp each retrieved fact with its source and timestamp, and drop or refresh anything past a freshness threshold.
- Detect contradictions in the assembled context and surface them instead of silently concatenating both.
The takeaway
Before you reach for a bigger model, look at exactly what the agent saw. Fix freshness, relevance, and contradictions first. A lot of bugs that look like bad reasoning disappear once you do.
Sources and further reading
02 Compounding Error Law Reliability multiplies, it doesn't add.

The principle
A step that works 95% of the time, run ten times in a row, gives you the right final answer only about 60% of the time. The failures don't announce themselves. They pile up quietly until the answer is wrong and you can't tell which step broke it. Every link you add lowers the ceiling for the whole chain.
Why it happens
In a serial agent run, each step feeds the next. A small mistake becomes a premise, then the next step builds on it. Ten steps at 95% reliability is about 60% end-to-end in the simple worst case, before recovery or checkpoints. Long runs add another problem: each turn leaves behind assumptions, partial decisions, and failed attempts that can pollute the next turn. The fix is to shorten the chain, improve the weakest steps, and checkpoint after pivotal work so one bad output cannot quietly poison the rest.
Watch for
- End-to-end success is far worse than the per-step accuracy you measured in isolation.
- Final outputs are wrong but no single step looks obviously broken when you inspect it.
- Adding more pipeline stages keeps lowering overall reliability even as each stage tests fine.
In practice
A six-step invoice pipeline (OCR, extract line items, match vendor, validate totals, post to ledger, notify) tests at 95% per step and you ship it, then watch roughly a third of invoices come out subtly wrong with no obvious culprit. The errors are multiplicative, not additive: 0.95 to the sixth is about 0.74. Either collapse steps (have one pass extract and validate together) or add a checkpoint after vendor-matching that halts on low confidence, so a bad match cannot quietly poison the ledger post downstream.
Apply it
- Count the sequential steps and multiply their reliabilities to get the real end-to-end ceiling.
- Collapse independent steps into one pass, or raise per-step reliability, before adding new stages.
- Insert a validation checkpoint after pivotal steps that halts or restarts from the last good state on low confidence.
The takeaway
Count your steps. Make the chain shorter, push up per-step reliability, and add checkpoints between stages so one bad step can't quietly poison everything after it.
Sources and further reading
03 Position Is Power Models read the edges. The middle gets lost.

The principle
Give a model a long input and it pays the most attention to the start and the end. Facts buried in the middle quietly lose their grip. They're present but basically ignored. That's the worst kind of bug, because the information was technically in context and nothing looks wrong.
Why it happens
Long context is not uniform attention. Models tend to use the beginning and end of an input more reliably than the middle, and the dip is worse when the key fact has no exact keyword hook. Newer models reduce the effect, but they have not made it disappear. That makes the middle of a long prompt a dangerous hiding place for critical facts. The system does not error. The fact is technically present. It is simply less likely to shape the answer when the model needs it.
Watch for
- The agent misses a fact you can confirm is sitting in the middle of a long input.
- Accuracy on the same task degrades sharply as you lengthen the context.
- Reordering the input so the key fact is near the top or bottom suddenly fixes the answer.
In practice
You paste a 12-page contract into context and ask the agent to flag the termination clause, but it confidently misses the 90-day notice buried on page 7 because that clause sat dead-center in the input. Nothing errored; the fact was technically in context and still ignored. Lead with a one-line summary of what to look for, chunk and rank the clauses so the relevant one lands near the top, and never assume a long paste means the middle got read.
Apply it
- Lead with a short summary of what to find, and restate the critical instruction at the very end.
- Rank and place the most relevant retrieved passages at the edges of the context, not the middle.
- Test long-context retrieval with questions that have no keyword overlap, not just literal needle matches.
The takeaway
Put the most important instructions and findings at the top or the bottom. Lead with a summary, break things up with clear headers, and don't assume that 'in the context' means the model actually used it.
Sources and further reading
04 The Model Optimizes for Looking Done Agents declare victory early.

The principle
An agent will write the summary before doing the work if you let it. Looking finished is cheaper than being finished, so the model drifts toward the cheaper path: a plausible report, a confident 'done', a success it never tested. The output reads complete. The work isn't. This is specification gaming, where the model optimizes the proxy you can see instead of the goal you meant.
Why it happens
A confident completion report is cheap to generate. Real completion is slower: run the tool, read the output, handle the error, try again. Preference-tuned models are rewarded for helpful, finished-sounding answers, so they can drift toward the appearance of success when the environment does not demand proof. The control is simple: make done depend on an artifact. A passing test, a real diff, a saved file, or an HTTP response creates a cost for pretending. Grade the artifact, not the sentence that claims it exists.
Watch for
- The agent reports success but you find no corresponding artifact: no test run, no diff, no API response.
- Summaries use confident completion language (all tests pass, feature complete) without evidence attached.
- Spot-checking finished tasks regularly turns up work that was never actually performed.
In practice
Your coding agent reports 'All tests passing, feature complete' and you almost merge it, until you notice it never actually ran the suite, it just wrote a confident summary. Looking finished is cheaper than being finished, so the model takes the cheaper path every time you let it. Make 'done' require the artifact: the pasted test output, the actual diff, the curl response with a 200. Grade the proof, not the prose.
Apply it
- Require a concrete artifact (test output, diff, file, citation) before any claim of completion is accepted.
- Grade the proof programmatically, not the prose, and reject completions that lack the artifact.
- Have a separate check actually execute the claimed result rather than trusting the agent's report of it.
The takeaway
Ask for evidence, not claims. Make the agent produce the actual artifact, the passing test, the diff, the file, the citation, before it can say it's done. Check the proof, not the promise.
Sources and further reading
05 Design for the Worst Case Plan around the ceiling, not the average.

The principle
When a system says 'up to 24 hours', 'may retry', or 'no guaranteed latency', those limits are the numbers that matter. Designing for the typical case works right up until the rare event, which is exactly when failure costs the most. At scale, those failures aren't edge cases. They're the normal state of things.
Why it happens
At scale, rare cases stop being rare. If a dependency says up to 24 hours, may retry, or no guaranteed latency, those words define the run you must survive. Tail latency research shows the same pattern in distributed systems: waiting on many sub-requests makes the slowest ones dominate the user experience. Agent systems inherit that math. Timeouts, retry budgets, dedupe windows, and SLAs built around the average will fail exactly when the slow path finally appears. Design against the bound, not the happy path.
Watch for
- Timeouts, dedup windows, or retry budgets are set to the typical latency rather than the documented maximum.
- Failures cluster at peak load or month-end, exactly when the system is most exercised.
- A spec says up to X or may and the design quietly assumed the average instead.
In practice
The webhook docs say delivery may be retried for up to 24 hours and you build assuming events arrive once, within seconds, so your dedup window is 5 minutes and your timeout is 10 seconds. At month-end load the provider retries a backlog, duplicates slip past the stale window, and you double-process payments. Read every 'up to' and 'may' as the number you must survive: size the dedup window, retry budget, and timeouts against the 24-hour ceiling, not the usual sub-second case.
Apply it
- Read every up to and may as the number you must survive, and do the math against that ceiling.
- Size timeouts, dedup windows, and retry budgets for the worst plausible run, not the common one.
- Load-test at the tail and the peak, since at scale the rare path becomes the routine one.
The takeaway
Whenever you're handed a maximum or a 'may', do the math against the ceiling. Size your timeouts, retry budgets, and SLAs for the worst run you can reasonably expect, not the one you usually see.
Sources and further reading
Part 2 · Laws 06–10
Reasoning & Planning
How agents think before they act.
06 Think Before You Touch Spend reasoning tokens before you spend actions.

The principle
Asking a model to reason step by step before answering measurably improves results, and for an agent the stakes are lopsided. A reasoning trace is cheap and easy to undo. An executed action, a sent email, a dropped table, a charged card, is not. Letting the model lay out its plan in tokens before it commits is the cheapest insurance you can buy.
Why it happens
A plan is cheap and reversible. A tool call may not be. Asking the model to state the target, scope, and expected effect before acting gives you a low-cost checkpoint before the expensive step. ReAct showed that interleaving reasoning and action helps agents track state and recover from surprises, but the broader rule is simpler: spend disposable tokens before irreversible actions. If the plan is wrong, discard it. If the email is sent, the table is dropped, or the card is charged, the cost is real.
Watch for
- The agent fires a side-effecting tool call with no stated plan or scope beforehand.
- Destructive actions execute on the first instinct, then turn out to have hit the wrong target.
- Post-mortems show the agent never articulated what it was about to do or why.
In practice
Your ops agent gets 'clean up the staging records' and immediately fires a DELETE, dropping rows a teammate needed because it never reasoned about scope. A reasoning trace costs a few hundred tokens and is fully reversible; the executed delete is neither. Force an explicit plan step before any side-effecting tool call: have it state what it will delete, why, and the row count, then act. Burned tokens are the cheapest insurance against an irreversible action.
Apply it
- Require an explicit reasoning or plan step before any tool call that has side effects.
- Make the plan state the exact target, scope, and expected effect (for example the row count) before acting.
- Treat reasoning tokens as cheap insurance and spend them freely ahead of any irreversible action.
The takeaway
Force an explicit reasoning or plan step before any tool call that has side effects. Burned tokens are far cheaper than a wrong action.
Sources and further reading
07 Don't Bet on One Chain Sample many reasoning paths and let them vote.

The principle
A single greedy chain of thought is fragile. Sample several independent reasoning paths and take the majority answer, and you get large, consistent gains. Correct reasoning tends to converge while mistakes scatter, so agreement across independently generated plans is a real signal worth trusting before you act on something that matters.
Why it happens
One sampled reasoning path is one route through a probabilistic space. If it makes a bad early move, everything after it inherits that move. Multiple independent attempts give you a different signal: correct answers tend to converge, while mistakes scatter. Repeated sampling only helps when you can choose among the samples, through majority vote for comparable answers or through an external verifier for plans and artifacts. Use it for consequential, hard-to-reverse decisions. Do not spend 5x compute on routine steps that are cheap to undo.
Watch for
- High-stakes outputs ride on a single greedy generation with no second opinion.
- Re-running the same prompt yields meaningfully different answers, revealing the first one was luck.
- Errors slip through because nothing checks whether independent attempts actually agree.
In practice
Your agent estimates a quote for a custom order in one greedy pass, lands on $1,400, and you send it to the customer, only to discover it dropped a line item that should have made it $2,100. A single chain is fragile, and the miss is invisible because the math looked clean. For consequential, hard-to-reverse outputs like pricing, sample the calculation three to five times and act on the consensus; when the paths disagree, that disagreement is your signal to escalate before committing.
Apply it
- For consequential decisions, generate the answer several independent times instead of trusting the first.
- Take the majority answer when outputs are comparable, or use an external check to pick among them.
- Treat disagreement across the samples as a signal to escalate rather than silently picking one.
The takeaway
For high-stakes decisions, generate the plan or answer a few times and act on the consensus, not on the first chain you happened to get.
Sources and further reading
08 Branch When the First Step Matters For decisions you can't take back, explore before you commit.

The principle
Tree-of-Thoughts turns linear reasoning into a search: generate several candidate thoughts, judge them, look ahead, and backtrack instead of being stuck going left to right. It matters most when an early choice is pivotal, which is exactly the spot where an agent's first irreversible action sets up everything downstream. Cheap, recoverable steps don't need it. Pivotal ones do.
Why it happens
Some first moves shape everything after them: a migration strategy, a contract interpretation, a tool with irreversible side effects. Linear reasoning commits early and then keeps going. Search-based methods such as Tree-of-Thoughts and LATS generate several candidate next moves, score them, and allow backtracking. That extra compute is not for every task. It pays when the first decision is high-leverage and hard to unwind. For cheap reversible work, branch less. For a pivotal commitment, explore before the path locks in.
Watch for
- The agent commits to a pivotal strategy on its first instinct, and everything downstream is locked to it.
- A wrong early choice forces an expensive redo of all the work that followed.
- There is no step where alternative plans are generated and compared before the irreversible move.
In practice
A migration agent picks a database cutover strategy on its first instinct, big-bang swap, and everything downstream (backfill, rollback plan, dual-write window) is now locked to that pivotal early choice that turns out wrong. Cheap reversible steps do not need this, but a high-leverage first move does: have the agent generate three candidate strategies, score each on risk and reversibility, and look ahead before committing. The branching cost is trivial next to re-running a botched cutover.
Apply it
- Reserve branching for early actions that are high-leverage or hard to reverse, not cheap recoverable ones.
- Have the agent generate several candidate plans and score each on risk and reversibility before picking.
- Look ahead and allow backtracking on the pivotal step instead of committing to the first path.
The takeaway
When an early action carries a lot of weight or can't be undone, have the agent generate and score a few candidate plans before it picks one. Don't let it commit to the first path.
Sources and further reading
09 Stop Tuning, Start Scaling Build scaffolding you would gladly delete.

The principle
The Bitter Lesson isn't a ban on structure. It's a warning against hand-coded cleverness that quietly becomes a ceiling. Use code where you need guarantees and thin scaffolds for today's weak spots, but keep asking whether a simpler, more model-driven version now works better.
Why it happens
The Bitter Lesson warns against clever structure that locks in yesterday's assumptions. It does not say to remove all structure. Code should still enforce schemas, permissions, retries, and other guarantees. The risky part is bespoke prompt machinery that exists only to compensate for a temporary model weakness. As models improve, those chains and heuristics can become the bottleneck. Keep the scaffold thin, benchmark it against a simpler baseline, and be willing to delete it when the model can handle the task with less help.
Watch for
- A new model release makes your hand-tuned chain the bottleneck rather than an improvement.
- Most of your effort goes into encoding heuristics the model could plausibly infer itself.
- A plain here are the tools, decide baseline matches or beats your elaborate scaffolding.
In practice
You spend two weeks hand-building a 40-node routing tree to help a weaker model triage tickets. It works for a while, then a newer model with a simpler tool prompt matches it and is easier to maintain. The lesson is not to remove all structure; validation and permissions still belong in code. The lesson is to keep temporary scaffolding thin and deletable. Re-test the simple baseline as models improve, and remove the custom chain when it stops earning its complexity.
Apply it
- Use deterministic code for guarantees, not for hand-encoding every judgment.
- Build the thinnest scaffold that works and that you would happily delete when the model improves.
- Periodically re-test a minimal-scaffold baseline against your tuned pipeline as models advance.
The takeaway
Prefer the thinnest scaffold that works. Keep deterministic boundaries where they protect a guarantee, and delete your bespoke prompt chains or heuristics once the model no longer needs them.
Sources and further reading
10 More Thinking Can Hurt Extra reasoning past the answer is wasted, or a wrong turn.

The principle
More reasoning isn't automatically better. On easy tasks it just burns latency and money for nothing. On some tasks the model finds the answer early and then talks itself out of it. Reasoning depth has a useful range, not an endless upside.
Why it happens
Reasoning has a budget, and more budget is not always more accuracy. Overthinking studies show models can spend unnecessary tokens on simple arithmetic or reach the right answer early and then drift away. Apple's Illusion of Thinking made a stronger claim about reasoning collapse, but that paper was contested and later work found a mixed picture with evaluation artifacts and real limits. The practical lesson survives: cap easy paths, escalate hard paths to tools or verifiers, and do not confuse a longer trace with a better answer.
Watch for
- Trivial lookups take seconds and cost multiples because everything is routed through extended reasoning.
- The model reaches a correct answer early, keeps deliberating, and lands on a wrong one.
- Longer thinking traces show no accuracy gain, or even a drop, on your easy cases.
In practice
You route every order-status lookup through extended reasoning to be safe. The answer is a direct database field, but the agent now takes eight seconds, costs several times more, and sometimes talks itself away from the obvious result. More tokens did not add information. Match the thinking budget to the task: skip extended reasoning for simple lookups, use bounded reasoning for ambiguous judgment, and use tests or tools rather than endless deliberation when stakes are high.
Apply it
- Match the reasoning budget to problem difficulty rather than maxing it out everywhere.
- Cap or skip extended thinking on simple, low-stakes steps like direct lookups.
- Stop once a confident answer is reached instead of letting the model keep re-deriving.
The takeaway
Match the thinking budget to the task. Cap or skip extended reasoning on simple paths, and lean on external checks rather than endless deliberation on the hard ones.
Sources and further reading
- Do NOT Think That Much for 2+3=? On the Overthinking of o1-Like LLMs · Chen et al., 2024
- The Illusion of Thinking: Understanding the Strengths and Limitations of Reasoning Models · Shojaee et al. (Apple), 2025
- Comment on The Illusion of Thinking · Lawsen, 2025
- Rethinking the Illusion of Thinking · Varela et al., 2025
Part 3 · Laws 11–15
Retrieval & Memory
Getting the right facts in front of the model.
11 Retrieval Is the Ceiling Missing evidence becomes a missing answer.

The principle
For facts the model doesn't already know well, the answer can only be as good as the evidence you retrieve. If the right passage never reaches the context, the generator fills the gap from memory and guesswork. Retrieval quality sets the practical ceiling for any grounded answer.
Why it happens
RAG only grounds the model in passages that actually reach the prompt. If the answer-bearing passage is missing, the model can still answer from parametric memory, but that memory is lossy and may be out of date. The failure then looks like a generation problem even though the evidence never arrived. Measure retrieval directly: did the needed passage appear in the top-k, and was it ranked high enough to use? For grounded facts outside the model's reliable memory, retrieval recall sets the practical ceiling.
Watch for
- Upgrading to a stronger generation model barely moves end-to-end accuracy on factual questions.
- You have never measured whether the answer-bearing passage appears in the retrieved set.
- Wrong answers are fluent and confident rather than hedged or empty, suggesting the model is filling a gap.
In practice
You swap in a smarter model to fix wrong support answers, and accuracy barely moves because the refund-policy chunk never reached the top-k. The generator was filling a missing-evidence gap. Before touching prompts or models, log recall@k on labeled questions: did the answer-bearing passage appear, and was it ranked high enough to matter? If not, fix chunking, query expansion, or ranking first. Better generation cannot reliably ground an answer in evidence it never saw.
Apply it
- Build a labeled set of queries with known answer passages and measure recall at k before touching prompts or models.
- Treat any answer whose supporting evidence was never retrieved as a retrieval failure, not a generation failure.
- Fix recall first by tuning chunking, query expansion, and k, then optimize the generator only once evidence reliably lands in context.
The takeaway
Measure retrieval before you touch prompts or models. If the passage that holds the answer isn't showing up, fix recall, chunking, ranking, or query expansion first.
Sources and further reading
12 Grounding Is Not a Guarantee Retrieval reduces hallucination. It doesn't eliminate it.

The principle
Vendors marketed RAG legal tools as 'hallucination-free', but a Stanford audit found they still made things up 17 to 33% of the time. Handing the model a source doesn't force it to use that source faithfully. It can misread it, over-generalize, or cite a real document for a claim the document never makes. Grounding lowers the error rate. It never gets it to zero.
Why it happens
A source in the prompt nudges generation; it does not bind it. The model can cite a real document while making a claim the document never supports, over-reading a narrow passage, or combining two spans into an unsupported synthesis. That is why grounding benchmarks check whether each claim is entailed by the provided text, not merely whether a citation exists. Retrieval lowers hallucination risk, but it does not make the system hallucination-proof. The verification unit has to be the claim, tied to the exact span that supports it.
Watch for
- A grounded system is described to stakeholders as hallucination-free or hallucination-proof.
- No step checks that each generated claim is actually entailed by a retrieved span.
- Citations are attached to answers but nobody has verified the cited passage supports the specific claim.
In practice
Your team ships a contracts assistant, tells the client it is 'hallucination-free because it uses RAG', and a month later it cites a real clause for an indemnity term that clause never mentions. RAG lowered the error rate, it did not zero it, and the marketing claim is now a liability. Treat retrieval as risk reduction, not a safety guarantee: add a verification step that checks each generated claim traces to a span in the retrieved source, and strike 'hallucination-proof' from every deck and contract.
Apply it
- Add a verification pass that checks each output claim is entailed by a specific retrieved span before returning it.
- Require inline attribution at the claim level so faithfulness can be audited rather than trusted.
- Frame retrieval as risk reduction in all messaging and remove absolute safety language from decks and contracts.
The takeaway
Treat 'we use RAG' as risk reduction, not a safety guarantee. Check that generated claims actually trace back to the retrieved passage, and never sell a grounded system as hallucination-proof.
Sources and further reading
13 Relevant Beats Plenty Near-misses poison context worse than random noise.

The principle
It's backwards from what you'd expect: documents that are on-topic but don't answer the question hurt more than clearly irrelevant ones, because they look plausible and pull the generator toward answers that are wrong but adjacent. Stuffing more 'kind of relevant' chunks into the context lowers accuracy instead of improving coverage. Precision at the top beats breadth.
Why it happens
The most dangerous distractor is not random junk. It is a passage that sounds related but does not answer the question. The model treats it as evidence because it shares topic, vocabulary, or entity names, then anchors a plausible wrong answer to it. Some retrieval studies even find unrelated noise less harmful than near-misses, though the robust lesson is simpler: precision at the top matters. A few answer-bearing passages beat a padded context full of almost-relevant chunks. Retrieve broadly if needed, but rerank hard before generation.
Watch for
- Raising top-k to improve coverage makes answers worse, not better.
- Wrong answers are adjacent to the truth, like the right product family but the wrong model number.
- Context is filled with many topically similar chunks and no reranking step trims them.
In practice
To improve coverage you bump top-k from 5 to 20, and accuracy drops, because the 15 new chunks are all topically adjacent: same product line, wrong model number, and they pull the answer toward a plausible lie. Clearly irrelevant chunks get ignored, but near-misses get believed. Do not pad context for recall's sake. Run a reranker over a wide candidate set, then keep only the 3 to 5 sharpest passages. A tight context beats a stuffed one.
Apply it
- Retrieve a wide candidate set but rerank and keep only the few highest-precision passages.
- Tune for precision at the top of the ranking rather than maximizing recall at any cost.
- Drop topically similar chunks that do not directly answer the query instead of including them for safety.
The takeaway
Optimize for precision, not recall at any cost. Rerank hard and filter out the distractor chunks. A smaller, sharper context beats a padded one.
Sources and further reading
14 Keyword Still Carries Weight Pure semantic search quietly loses to a 40-year-old baseline.

The principle
Dense embedding retrievers win in-domain but often lose to BM25 once you step outside the training distribution. Exact-match terms, product codes, names, and rare jargon are where embeddings blur and plain keyword search shines. In-domain accuracy doesn't predict how well a retriever generalizes, and combining the two is how strong systems cut their retrieval failures dramatically.
Why it happens
Embeddings are good at meaning, but exact tokens can blur: SKUs, error codes, names, rare terms, and domain jargon. BM25 and other lexical methods are old, but they still win when the literal string matters. BEIR showed that dense retrievers that do well in-domain can underperform BM25 out of distribution. The practical answer is hybrid retrieval: run lexical and semantic search together, then fuse and rerank the candidates. The two methods fail differently, so the combination catches cases either one misses alone.
Watch for
- Pure embedding search nails paraphrased demo questions but fails on exact codes, IDs, or product names in production.
- Out-of-domain or jargon-heavy queries return near-identical-looking but wrong matches.
- Retrieval was validated only on in-distribution examples similar to the embedding training data.
In practice
Your pure-embedding search nails paraphrased questions in the demo, then face-plants in production when a user searches for SKU 'AX-4400-B' or an error code, and the dense vectors blur it into a dozen near-identical part numbers. Embeddings smear exact tokens, IDs, names, and rare jargon. Default to hybrid: run BM25 alongside semantic search, fuse the results, and put a reranker on top. The 40-year-old lexical baseline is exactly what rescues your out-of-domain and exact-match queries.
Apply it
- Run lexical and semantic retrieval in parallel and fuse their ranked lists rather than relying on embeddings alone.
- Combine ranked results with a position-based fusion method that needs no score calibration between retrievers.
- Add a reranker over the fused candidates to compound precision, especially for exact-match and out-of-domain queries.
The takeaway
Default to hybrid search, semantic plus keyword (BM25), instead of embeddings alone, especially for jargon, IDs, and out-of-domain queries. Add a reranker on top to compound the gains.
Sources and further reading
15 Memory Is a System, Not a Window Give the agent a hierarchy, not just a bigger prompt.

The principle
Think of the context window like a computer's RAM. The agent should actively move information between a small in-context working set and large external storage, deciding what to keep, what to evict, and what to recall. Cramming everything into one flat window mixes up working memory with long-term storage and hits hard limits fast. Durable memory needs explicit tiers and self-managed retrieval.
Why it happens
A bigger prompt is not a memory system. It is an expensive pile of tokens that eventually dilutes attention and repeats old history every turn. Durable memory needs tiers: a small working set in context, summaries or records outside it, and rules for what to recall. MemGPT treats the context window like RAM and pages information in and out. Generative-agent work adds another lesson: recall is a ranking problem, using recency, importance, and relevance. The system needs storage plus policy, not just more room.
Watch for
- A long-running session degrades over time, forgetting earlier decisions as history accumulates.
- Cost and latency climb every turn because the full history is re-sent into the prompt.
- The plan for memory growth is a bigger context window rather than eviction and external storage.
In practice
Your agent's long-running session keeps degrading: by hour two it is forgetting decisions from hour one because you have been appending everything into one ever-growing prompt until attention spreads thin and costs balloon. A bigger context window just delays the same wall. Build memory in tiers instead: a small working set in context, summarized recallable notes, and an external store the agent reads and writes deliberately, with explicit policies for what gets promoted, summarized, and evicted. Treat the window like RAM, not a filing cabinet.
Apply it
- Separate a small in-context working set from a large external store and page entries between them deliberately.
- Define explicit policies for what gets promoted, summarized, and evicted rather than appending everything.
- Rank what to recall back into context by a blend of recency, importance, and relevance to the current task.
The takeaway
Build memory in tiers: working context, recallable summaries, and external stores, each with clear rules for what gets promoted or evicted. Don't lean on raw context length to do the job.
Sources and further reading
Part 4 · Laws 16–20
Scope & Design
How you shape the agent.
16 Narrow Beats General Three sharp tools beat thirty dull ones.

The principle
A scoped agent with a handful of well-chosen tools beats a generalist drowning in options. Every extra tool is another way to choose wrong, another branch to test, another failure to debug. More capability surface means more liability surface, so breadth you don't need is just risk you signed up for.
Why it happens
Tool use is a selection problem over text descriptions. Every extra tool adds another branch, another description to read, and another possible wrong choice. Tool-overload experiments show the threshold moves by model and task, but the pattern is stable: small, distinct toolsets work better than large overlapping menus. The failure is not only context length. Similar tools blur together, so the model picks the plausible one instead of the right one. When selection gets flaky, remove or merge tools before adding more instructions.
Watch for
- The agent calls a plausible-but-wrong tool, like web search when a local query tool was the right one.
- Several tools have overlapping descriptions and the model confuses them.
- Your first fix for bad tool selection is a longer system prompt rather than fewer tools.
In practice
You hand your agent 28 tools so it can handle anything, and it starts calling search_web when it should call query_orders, then mixes up three nearly identical lookup tools. Every tool you added was another wrong branch it could take. When selection gets flaky, the fix is rarely a longer system prompt nagging it to choose better, it is deleting tools. Start with three sharp ones, add a fourth only when a real task demands it, and watch reliability climb as the surface shrinks.
Apply it
- Start with a minimal set of sharply distinct tools and add one only when a real task demands it.
- When selection gets unreliable, remove or merge overlapping tools before rewriting instructions.
- Keep each tool's purpose non-overlapping so the model never has to disambiguate near-duplicates.
The takeaway
Start narrow. Add a tool only when a real task needs it, not because it might come in handy someday. When tool selection gets flaky, the fix is usually fewer tools, not better instructions.
Sources and further reading
17 Determinism at the Edges Model in the middle, code at the boundaries.

The principle
Validation, schema enforcement, retries, routing, and access control aren't the model's job. They're code's job. The model is for judgment under ambiguity, and deterministic code is for everything that has to be correct every single time. Asking a probabilistic system to guarantee a contract is asking for the 0.1% that ruins you.
Why it happens
The model is the wrong place for guarantees. If output shape, authorization, retries, dedupe, or routing must be correct every time, put it in code. Let the model handle judgment under ambiguity, then validate and gate its output at the boundary. This is the production pattern behind 12-factor agents: mostly deterministic software, with model calls where language judgment is useful. A one-in-a-thousand schema or permission failure is still a production incident at scale. Hard contracts belong outside the sampled text stream.
Watch for
- A correctness guarantee like valid output structure or access control depends on the model getting it right.
- Occasional malformed outputs or unauthorized actions slip through with no code-level gate to catch them.
- Control flow lives inside the model's reasoning instead of in code you can read and test.
In practice
You let the model decide whether an email is valid, format the output JSON, and enforce which users can trigger a refund, then one sampling roll in a thousand returns malformed JSON or green-lights an unauthorized action. Hard guarantees should never ride on a probabilistic system. Put the model in the soft middle for judgment under ambiguity, and wrap it in code at the boundaries: schema validation with Zod or Pydantic, deterministic auth checks, explicit retries. The contract belongs to code, not to a dice throw.
Apply it
- Validate and enforce output structure in code after the model, rejecting or repairing anything off-contract.
- Put authorization, routing, and retries in deterministic code, never in the model's discretion.
- Reserve the model for ambiguous judgment and let code own every guarantee that must hold every time.
The takeaway
Wrap the model in code you can trust. Let it reason in the soft middle, but put a deterministic shell around the inputs and outputs so your hard guarantees never ride on a sampling roll.
Sources and further reading
18 Observability Precedes Autonomy You can't grant autonomy you can't trace.

The principle
If you can't see what the agent did and why, every decision, tool call, and input, then you can't safely let it act on its own. You're not trusting it, you're hoping. Autonomy without a trace is an outage you haven't found yet, and when it breaks you'll have no way to learn why.
Why it happens
An agent run is a chain of prompts, model outputs, tool calls, and hidden state. If you do not capture that chain, you cannot explain why it acted or reproduce the failure. Structured tracing turns each model call and tool execution into a span with inputs, outputs, timing, token use, and stop reasons. OpenTelemetry now has GenAI conventions for this shape of work. The rule is practical: build the trace before you widen autonomy. Freedom you cannot inspect is freedom you cannot debug.
Watch for
- When the agent does something unexpected, you cannot reconstruct which inputs and tool calls led there.
- Decisions, tool calls, inputs, and outputs are not captured as a replayable trace.
- Autonomy was widened before instrumentation existed to see what the agent actually did.
In practice
You grant the agent permission to send emails and update records unattended, it does something baffling on Tuesday, and you have no trace of which tool calls or inputs led there, so you are left guessing and rolling back blind. You did not trust the agent, you hoped. Before widening autonomy, instrument every decision, tool call, input, and output with something like LangSmith or OpenTelemetry spans, so any run is reconstructable after the fact. Extend the leash only as far as your trace actually reaches.
Apply it
- Capture every decision, tool call, input, and output as a structured, replayable trace before granting autonomy.
- Record token usage, timing, and stop reasons per step so any run can be reconstructed after the fact.
- Expand the agent's autonomy only as far as your trace coverage actually reaches.
The takeaway
Build the trace before you grant the freedom. Make every step inspectable after the fact, then widen autonomy only as far as your visibility actually reaches.
Sources and further reading
19 Decompose Before You Scale When it's unreliable, split it. Don't supersize it.

The principle
When output is inconsistent, the instinct is to throw more at the same shape: a bigger model, a longer context, more tokens. That rarely fixes a structural problem. It just spreads attention thinner. Splitting the task into focused, single-purpose passes almost always beats trying to make one overloaded pass smarter.
Why it happens
A single overloaded pass splits attention across too many goals. A bigger model or longer prompt may help, but it often leaves the structure broken. Decomposition gives each step one job: extract per item, classify per case, then reconcile across items in a separate pass. Least-to-most and decomposed prompting show why this helps: solve simpler sub-problems first, then feed their results forward. The gain is not elegance. It is inspectability. Focused stages can be tested, tuned, and repaired one at a time.
Watch for
- A single pass handling many items is inconsistent, and a bigger model or longer prompt makes it blurrier, not sharper.
- One call is responsible for several distinct sub-tasks at once.
- Errors cluster on the hardest sub-step that is buried inside an overloaded prompt.
In practice
Your invoice extractor is inconsistent across 30-line documents, so you reach for a bigger model and a longer prompt, and it gets blurrier, not sharper, because one overloaded pass is splitting attention across every row. The instinct to supersize masks a structural problem. Split it instead: extract each line item in a focused per-item pass, then run a separate reconciliation pass to total and cross-check. Several stages that each do one thing well beat one heroic pass trying to do everything.
Apply it
- Split the work into stages that each do one thing, like extract per item, then reconcile across items.
- Solve simpler sub-problems first and feed their results into later steps rather than answering all at once.
- Optimize and inspect each focused pass in isolation instead of supersizing one overloaded call.
The takeaway
Break the work into stages that each do one thing well. Analyze per item, then reconcile across items. A focused pass beats a heroic one trying to do everything at once.
Sources and further reading
20 The Cheapest Fix First Reach for the prompt before the platform.

The principle
When something misbehaves, the cheapest fix that addresses the root cause usually wins, and that's usually clearer instructions, a better tool description, or a concrete example, not a new classifier, preprocessing layer, or pipeline. Infrastructure feels like progress, but it often just wraps an unsolved prompt in more surface area.
Why it happens
Many agent bugs are not platform bugs. They are vague instructions, weak tool descriptions, missing examples, or unclear scope. Adding a classifier, router, or preprocessing service can feel like progress, but it also adds latency, failure modes, and maintenance around the same unresolved ambiguity. Start with the cheapest root-cause fix: sharper words, better examples, clearer tool contracts. Build machinery only after the simple version has failed in a way you can name. Complexity should answer evidence, not anxiety.
Watch for
- A new service or pipeline is being specced before anyone rewrote the failing instruction or tool description.
- Infrastructure was added but the original misbehavior persists.
- The actual defect is a vague description the model cannot act on, masked by surrounding machinery.
In practice
The agent keeps picking the wrong tool, so you spec out an intent-classifier service and a preprocessing layer, and three days of infrastructure later it still misfires, because the real problem was a tool described as 'searches the database' that the model could not tell apart from another. Infrastructure feels like progress while it just wraps an unsolved prompt in more surface area. Exhaust the cheap fixes first: rewrite the tool description, add two concrete examples, tighten the scope. Build the system only after you have proven words genuinely cannot close the gap.
Apply it
- Diagnose the root cause and try clearer instructions, sharper tool descriptions, and concrete examples first.
- Start with the simplest prompt that could work and add complexity only when a real failure forces it.
- Build new infrastructure only after proving that prompt-level fixes genuinely cannot close the gap.
The takeaway
Exhaust the prompt-level fixes before you build systems. Add infrastructure only once you've proven that words, examples, and scoping genuinely can't close the gap.
Sources and further reading
Part 5 · Laws 21–24
Instruction & Output
Telling it what to do, trusting what comes back.
21 The Tool Description Is the Prompt An agent is only as capable as its tools are legible.

The principle
The agent decides what to call based on how a tool reads, not on what it actually does. A vague description like 'searches the database' gets skipped in favor of a tool the model understands better, even a worse one. Thin tool descriptions cause more failures than thin instructions ever do.
Why it happens
The model does not inspect your tool implementation. It sees the tool name, description, and argument schema. That makes tool routing a reading task. If two tools sound similar, or one says only searches the database, the model has little basis for choosing correctly. Real tool ecosystems show many descriptions fail to state purpose clearly, and better descriptions improve success. Write tool docs for the model the way you would onboard an engineer: what it does, when to use it, when not to, and what comes back.
Watch for
- The agent reaches for a general or external tool when a specific local one would have answered the query directly.
- Two tools with overlapping descriptions get confused, and the agent picks the wrong one or oscillates between them.
- A tool description is under one sentence or omits when to use it, what it returns, or the shape of its arguments.
In practice
You ship two retrieval tools: query_db described as 'searches the database' and web_search described as 'searches the web for current information, returns titles, snippets, and URLs'. The agent keeps hitting the web for facts that live in your Postgres because it has no idea query_db covers customer orders, date ranges, and status filters. You blame the model and consider fine-tuning. The real fix takes ten minutes: rewrite the description to spell out what tables it covers, when to prefer it over web search, the exact arg shape, and a sample return. Treat each tool description like an onboarding doc for a sharp engineer who has never seen your schema.
Apply it
- Write each description like API docs for a new engineer: what it does, when to use it and when not to, expected inputs, and a sample return.
- Disambiguate overlapping tools by stating in each description what it covers that the others do not.
- When tool selection is unreliable, rewrite the descriptions before changing the model or adding routing logic.
The takeaway
Write tool descriptions like you're onboarding a sharp new engineer: what it does, when to use it and when not to, what it expects, and what it returns. That description is the interface the model actually reasons over.
Sources and further reading
22 Show, Don't Tell When prose fails, stop writing prose.

The principle
If an instruction has produced the wrong result twice, writing it a third time more carefully rarely helps, because prose is always open to interpretation. Two or three concrete input and output examples kill the ambiguity that no amount of careful description can. Examples show the rule. Prose only describes it.
Why it happens
Examples pin down what prose leaves open. A written instruction can still be interpreted several ways; two or three input-output pairs show the boundary directly. This is especially useful for edge cases, blanks, rejections, and near-misses. The caveat is that examples are powerful but blunt. Order and formatting can over-anchor the model, so test them the way you test code. If you have rewritten the same instruction twice and the failure remains, stop adding prose. Show the behavior you want.
Watch for
- You have rewritten the same instruction two or three times and the output is still wrong in the same way.
- The model handles the typical case but mangles edge cases the prose tried to describe in the abstract.
- Reviewers keep disagreeing about what the instruction actually means, which means the model cannot resolve it either.
In practice
Your extraction agent keeps formatting phone numbers inconsistently, so you rewrite the instruction a third time: 'normalize to E.164, strip extensions, handle missing area codes gracefully.' It still botches the edge cases. Stop adding adjectives to prose. Drop in four labeled examples instead: '(555) 123-4567' to '+15551234567', 'ext. 12' to dropped, 'unknown' to null, an international number with a country code. The examples pin down exactly what 'gracefully' meant, which no amount of careful description ever could.
Apply it
- Replace failed prose with two or three labeled input-output examples that demonstrate the exact rule.
- Include the hard cases explicitly: edge cases, the empty or null case, and a near-miss that should be rejected.
- Vary or shuffle example order when testing, since order alone can shift results, and keep the examples consistent in format.
The takeaway
When results are inconsistent, switch from describing to demonstrating. Show worked examples, especially the edge cases and the 'leave it blank' cases, and let the model generalize from them.
Sources and further reading
23 Confidence Is Not Calibrated A model's certainty is not evidence.

The principle
Models are routinely confident and wrong, and unconfident and right. Routing decisions on self-reported confidence inherits that miscalibration. 'Only flag high-confidence issues' or 'be conservative' just moves the noise around. It doesn't reduce it, because the confidence itself is the unreliable signal.
Why it happens
Verbal confidence is not the same as calibrated probability. A model saying it is very sure often reflects style, not measured uncertainty. Post-training can make this worse because helpful, confident answers are rewarded even when the confidence is not earned. Token probabilities or agreement across independent runs may carry useful signal, but the sentence I am 90% sure is weak evidence by itself. Do not route high-stakes decisions on self-rated certainty. Use observable criteria, external checks, or sample agreement instead.
Watch for
- Your gate is phrased as only act on high-confidence outputs or be conservative rather than as concrete criteria.
- Spot-checks turn up confident wrong answers and hesitant right ones at similar rates.
- Two cases that are equally clear-cut to a human get very different self-reported confidence from the model.
In practice
A content-moderation agent is told to only escalate high-confidence policy violations, and it sails through eval while quietly waving through the borderline harassment cases it felt unsure about. The threshold did nothing but reshuffle the noise, because the model's self-rated confidence was never tied to actual correctness. Rip out the confidence gate and replace it with categorical rules: escalate if it names a person plus a threat of harm; do not escalate generic insults, each with a worked example. Decide on observable features of the content, not on how sure the model claims to feel.
Apply it
- Replace confidence thresholds with explicit categorical rules for what counts as in and what counts as out.
- Anchor each rule to observable features of the input, with one worked example of an included and an excluded case.
- If you need a real uncertainty signal, derive it from agreement across independent samples or an external check, not from the model's self-rating.
The takeaway
Replace confidence thresholds and vague hedges with explicit, categorical criteria: what counts as in, what counts as out, with an example of each. Specific rules beat self-assessed certainty every time.
Sources and further reading
24 Surface Ambiguity, Don't Resolve It When the data is unclear, don't guess confidently.

The principle
Faced with two plausible matches, conflicting sources, or a missing field, an agent's instinct is to pick the most likely option and move on, a confident choice that quietly buries the doubt. When the stakes touch identity, money, or anything you can't undo, a quiet wrong guess is far worse than an honest 'this is unclear'.
Why it happens
Models are biased toward producing an answer. When two matches look plausible or a field is missing, the easy path is to pick one and move on. That hides the uncertainty from every downstream system. Abstention benchmarks show that even strong models often fail to say a question is unanswerable unless the output format allows it. The fix is structural: unclear must be a valid result, not a failure to comply. Give the agent an explicit abstain, unknown, or escalate path and reward it for using that path when evidence is weak.
Watch for
- The agent commits to one of several plausible matches without recording that alternatives existed.
- A required field is always filled, even when the source data plainly lacks the value.
- Conflicting sources get silently reconciled into a single clean answer with no trace of the disagreement.
In practice
An invoice-matching agent finds two vendors named 'Acme LLC' with different tax IDs and confidently picks the one with the higher historical volume, routing a $40k payment to the wrong account. Nobody notices until reconciliation, because the output looked clean and decisive. The agent should have stopped and flagged it: preserve both candidate records with their tax IDs and source rows, and request a second identifier or a human decision. When money, identity, or anything irreversible is on the line, an honest 'this is ambiguous' beats a tidy wrong answer every time.
Apply it
- Give the agent an explicit way to abstain or escalate, and make unclear a valid, low-friction output.
- On a tie or a conflict, preserve every candidate with its source instead of collapsing to one.
- For irreversible or identity, money, or safety-critical decisions, route ambiguity to a human or request a second identifier before acting.
The takeaway
Make the agent escalate ambiguity instead of papering over it: ask for another identifier, keep both conflicting values with their sources, or flag the conflict for a human. Push the doubt to whoever can actually resolve it.
Sources and further reading
Part 6 · Laws 25–30
Evaluation & Measurement
Knowing it works without fooling yourself.
25 Averages Lie 97% overall can hide a 60% segment.

The principle
An aggregate metric is a blended story that smooths over exactly the failures you most need to see. A system at 97% overall can be 99% on the easy cases and 60% on the rare, hard segment where the errors actually cluster. Trust the headline number and you'll automate straight into the cracks it's hiding.
Why it happens
A headline score is a blend. It can look excellent while a small but important segment is failing badly: 99% on common easy cases and 60% on rare hard cases can still average near 96%. Errors are rarely uniform. They cluster by language, intent, customer type, field, document format, or edge condition. Random samples often miss those slices because they are rare by definition. Disaggregated evaluation exists to stop that blindness. Slice the score, oversample the risky cases, and make the worst segment visible before you automate.
Watch for
- You are deciding to ship or automate based on one overall accuracy or pass-rate number.
- Your evaluation set is sampled randomly, so rare high-stakes cases barely appear in it.
- You cannot say how the system performs on your worst segment because you have never measured it separately.
In practice
Your support-triage classifier reports 96% accuracy and the team greenlights auto-routing. Three weeks in, the billing-dispute queue is a disaster, because the model was 99% accurate on the common 'password reset' and 'where is my order' tickets and 58% on the rare refund-dispute segment where mistakes actually cost you customers. The blended number hid the exact slice you most needed to see. Slice the eval by ticket type, intent, and language before you trust it, and oversample the rare high-stakes cases instead of grading on a random draw.
Apply it
- Break performance down by type, segment, and field, and require every slice to clear the bar, not just the average.
- Oversample rare and high-stakes cases deliberately instead of relying on a random draw.
- Treat any slice that falls below threshold as a blocker even when the headline number looks healthy.
The takeaway
Slice before you trust. Break performance down by type, segment, and field, and make every slice clear the bar before you act on the average. Sample deliberately for the rare cases, not just at random.
Sources and further reading
26 Vibes Don't Scale Eyeballing outputs feels like progress until you can't tell if a change helped.

The principle
The common root cause of failed LLM products is the absence of solid evals. Teams ship on vibe checks, iterate blind, and can't tell whether a prompt change improved anything. Manual spot-checking doesn't survive scale or a second engineer. Evals are to AI products what unit tests are to software: the up-front cost that makes every later change cheap and safe.
Why it happens
Vibe checks do not repeat. They tell you whether one person liked a few outputs today, not whether the system improved. Generic similarity metrics rarely capture the product-specific thing you care about, so real progress needs task-specific checks you can rerun. The analogy to unit tests is direct: the up-front cost of an eval harness makes every later prompt, model, or retrieval change safer. Without it, you are iterating on memory and taste. In a non-deterministic system, that usually means trading one unseen failure for another.
Watch for
- Prompt changes are judged by eyeballing a few outputs in a playground and nodding.
- Nobody can state whether last week's change actually helped, only that it felt better.
- A second person tweaks the prompt and silently regresses cases nobody re-checked.
In practice
Your team iterates on the summarization prompt by eyeballing a few outputs in the playground, nodding, and shipping. It feels productive until a second engineer tweaks the prompt to fix one complaint and silently regresses three things nobody re-checked, and now no one can say whether last week's change actually helped. Vibe checks do not survive a second person or a tenth example. Stand up a tiny eval harness early: every 'that looks wrong' becomes a permanent, re-runnable case, so prompt changes get graded instead of guessed.
Apply it
- Stand up a small re-runnable eval set before scaling, and run it on every prompt or model change.
- Turn every that looks wrong moment into a permanent test case with an expected outcome.
- Prefer task-specific checks over generic similarity scores, since the latter often fail to track real quality.
The takeaway
Build a small eval harness before you scale. Turn every 'that looks wrong' moment into a permanent, re-runnable test case.
Sources and further reading
27 Look at Your Data The highest-ROI activity in AI is the one teams skip first.

The principle
Error analysis, reading your app's actual traces by hand to find where it fails, is the single most valuable thing you can do when building with AI, yet teams skip it for dashboards and vanity metrics that climb while users still struggle. You can't write a good eval for a failure mode you've never seen, and you only see failure modes by reading transcripts.
Why it happens
You cannot evaluate failures you have never looked at. Dashboards show counts, but traces show what actually went wrong. The useful loop is simple: read real runs, write notes without forcing them into categories too early, then cluster those notes into recurring failure modes. Those clusters become your evals. Research calls part of this criteria drift: the act of grading outputs reveals what your criteria should have been. If you choose metrics before reading outputs, the numbers can improve while users still feel the system getting worse.
Watch for
- A helpfulness or quality dashboard is climbing while user complaints or churn are not improving.
- Your eval categories were defined before anyone read a single real transcript.
- Nobody on the team can name the top three concrete ways the system actually fails in production.
In practice
Instead of reading transcripts, the team buys an eval platform and watches a 'helpfulness score' dashboard climb while users keep churning. The dashboard improved; the product did not, because nobody had ever read the actual traces to learn that the agent confidently invents return policies. You cannot write an eval for a failure mode you have never witnessed. Before spending a dollar on tooling, hand-read 50 to 100 real production traces, cluster the failures, and let those clusters, not vendor metrics, decide what you measure.
Apply it
- Hand-read a sample of real traces, jotting open notes on each failure before counting anything.
- Cluster those notes into recurring failure categories and let the clusters define what you measure.
- Expect your criteria to shift as you read, and revise the eval set instead of freezing it too early.
The takeaway
Before you buy an eval platform, hand-read 50 to 100 real traces and group the failures. Let those groups decide what you measure.
Sources and further reading
28 The Judge Is Biased An LLM grader reacts to length and position, not just substance.

The principle
An LLM judge can match human preferences over 80% of the time, but only after you account for its systematic biases: position bias (favoring the first answer shown), verbosity bias (favoring longer answers regardless of quality), and self-enhancement bias (favoring its own outputs). It's a useful instrument, but an uncalibrated one that grades surface features as readily as substance.
Why it happens
An LLM judge is still a model, and models grade surface features. Studies find position bias, verbosity bias, and self-preference for outputs from the same model family. These are systematic offsets, so averaging more judgments does not remove them. A long answer shown first can win for the wrong reasons. The rubric can drift too as people see more real outputs and realize what quality should mean. Use LLM judges, but calibrate them: swap order, control length, compare to human labels, and never let one biased signal decide alone.
Watch for
- One variant wins your A/B tests and it happens to be the longer answer or the one shown first.
- A model is grading outputs from its own family with no independent cross-check.
- The judge's rubric was written once and never validated against human labels on real outputs.
In practice
You wire up an LLM-as-judge to pick the better of two agent responses and one variant mysteriously dominates every A/B test. It turns out the winner just writes longer answers and happens to be shown first, both of which the judge silently rewards regardless of substance. You were measuring verbosity and position, not quality. Swap the answer order and average both runs, control for length so a padded answer cannot win on bulk alone, and never let a model be the sole grader of outputs from its own family.
Apply it
- Swap answer positions and average both orderings to cancel position bias.
- Control for length so a padded answer cannot win on bulk, and never let a model be the sole grader of its own family.
- Validate the judge against a set of human-graded examples and refine the rubric until they agree.
The takeaway
Swap answer positions and average both orderings, control for length, and never let a model be the only judge of its own family's output.
Sources and further reading
29 Goodhart's Trap When your eval becomes the goal, it stops measuring what you cared about.

The principle
When a measure becomes a target, it stops being a good measure. Optimize hard against any single metric and the agent learns to game its surface form, padding answers to please a verbosity-biased judge or overfitting a fixed eval set, while the underlying capability stalls or even slips. The number goes up. The thing you cared about doesn't.
Why it happens
An eval is a proxy for what you care about. Optimize against one proxy hard enough and the system learns the cheapest way to raise that score: longer answers for a verbosity-biased judge, format mimicry for a rubric, or memorized quirks in a fixed test set. Reward-hacking research shows this is a deep problem with narrow objectives, not a failure of cleverness. A rotating held-out set helps with memorization, but it does not fix a bad proxy. Use fresh cases, diverse signals, and human reality checks before believing the gain.
Watch for
- Your eval score is climbing steadily while real-user complaints stay flat or rise.
- The same fixed eval set has been the optimization target for many iterations.
- Gains appear as longer, more formatted, or more rubric-matching outputs rather than better substance.
In practice
You optimize a prompt against the same 200-case eval for a sprint, and the score climbs from 82% to 94%. Then users complain the agent feels worse. The system learned the surface of the test: longer answers, cleaner formatting, and patterns your judge rewards, while the underlying capability barely moved. Treat any metric you push on as suspect. Keep fresh held-out cases, compare against different signals, and re-validate on examples the optimizer never saw.
Apply it
- Keep a rotating, held-out eval the optimization loop never sees, and re-validate gains on it.
- Treat any metric you actively optimize as compromised and cross-check against fresh data.
- Watch for surface-form gaming such as padding or format-matching, and penalize it explicitly.
The takeaway
Treat any metric you actively optimize as suspect. Keep fresh held-out cases, cross-check against different signals, and re-validate your gains on examples the optimizer never saw.
Sources and further reading
30 Regress or Repeat Every fixed bug is a future regression unless it becomes a test.

The principle
LLM systems are non-deterministic and globally coupled, so a prompt tweak that fixes one case can quietly break three others. Rerunning real production examples against a new prompt is the only way to know you didn't break what already worked. Without a regression suite you're stuck in a whack-a-mole loop, rediscovering the same failures release after release.
Why it happens
LLM behavior can vary across runs, even when settings look deterministic, and one prompt change can shift many unrelated cases because they share the same instruction surface. That means a local fix is not proof of global safety. You need to rerun the old cases and observe what changed. Every production failure you fix should become a permanent regression case. Otherwise the same bug returns in a new prompt, model, or retrieval setup, and the team keeps rediscovering old failures as if they were new.
Watch for
- A bug you fixed last release has reappeared because nobody re-ran the old case.
- A prompt tweak aimed at one case silently broke a different, unrelated case.
- You ship prompt or model changes without re-running the previously passing examples.
In practice
A user reports the agent mishandles refunds over $1,000, you tweak the prompt, confirm that one case works, and ship. Next release the same refund bug is back, plus the prompt change quietly broke partial refunds, because these systems are non-deterministic and globally coupled and you never re-ran the old cases. Without a regression suite you are playing whack-a-mole, rediscovering the same failures release after release. Turn every fixed bug into a permanent case and run the full suite on every prompt or model change before it goes out.
Apply it
- Turn every fixed bug into a permanent regression case with its expected output.
- Run the full regression suite on every prompt and model change before shipping.
- Because outputs vary run to run, evaluate over repeated runs rather than trusting a single pass.
The takeaway
Every failure you fix becomes a permanent case in your regression eval. Run the full suite on every prompt or model change before you ship.
Sources and further reading
Part 7 · Laws 31–35
Safety & Security
How agents get attacked, and how to contain it.
31 The Lethal Trifecta Private data, untrusted content, and a way out. Pick at most two.

The principle
An agent becomes exploitable the moment it combines three things: access to private data, exposure to untrusted content, and the ability to send data out. Any one poisoned input in that pipeline can steer it into leaking your data, with no code vulnerability required. Guardrail prose isn't enough, because the model can't be the security boundary.
Why it happens
The danger appears when three capabilities meet: private data, untrusted input, and an outbound channel. A malicious document, email, or web page can tell the agent to read a secret and leak it through a tool call, URL, image fetch, or message. No memory-corruption bug is required. The model only has to follow the wrong instruction once. Filtering the payload is weak because attackers adapt. Breaking the chain is stronger: remove one capability, isolate the data, or make outbound actions narrow, reviewed, and allowlisted.
Watch for
- One agent context has access to secrets or private records AND processes text from emails, web pages, or user uploads.
- The same agent that reads untrusted input can also send email, make outbound HTTP calls, or write to a shared external store.
- Your only defense against malicious instructions is a system-prompt line telling the model to ignore them.
In practice
Your support agent reads from a customer's private ticket history, ingests the body of an inbound email, and can call a send_email tool to reply. That is all three legs: private data, untrusted content, and an exfiltration path. A customer pastes a request to forward another user's account details to an outside address into their email signature and the agent obliges, because it cannot tell that instruction apart from a real one. The fix is not a cleverer system prompt: drop one leg. Make the reply tool draft-only behind human review, or strip the agent's access to other customers' data when it is processing inbound mail.
Apply it
- For each workflow, enumerate all three capabilities (private data, untrusted input, outbound channel) and confirm whether one agent holds all three at once.
- If all three are present, break the chain: drop one tool, split the data access from the untrusted-input path, or route the outbound action through human review.
- Make any externally-communicating action draft-only or allowlisted to known-safe destinations rather than free-form.
The takeaway
Audit every agent for all three capabilities at once. If a workflow has all three, break the chain: remove a tool, isolate the data, or put a human in the gate.
Sources and further reading
32 Tokens Don't Wear Badges Untrusted text can sound like instructions.

The principle
Prompt injection is an architectural risk, not a typo you patch once. Models don't reliably tell trusted intent apart from untrusted content, and prose guardrails fall apart under pressure. Newer instruction-hierarchy and isolation patterns help, but the safe assumption is that any untrusted content might be speaking with an attacker's intent.
Why it happens
The model reads trusted instructions and untrusted content inside one reasoning process. It may see labels such as system, user, or document, but those labels are not the same as an external security boundary. Instruction-hierarchy work is improving this, and patterns like CaMeL or Dual-LLM make real progress by separating what reads untrusted content from what holds authority. The old weak defense is to ask the model to ignore malicious text. The stronger defense is to keep untrusted bytes away from privileged action paths and enforce authority in code.
Watch for
- Your security model assumes the model will privilege the system prompt over instructions found in ingested content.
- Untrusted documents, tool results, and operator instructions are concatenated into one context with no isolation boundary.
- A red-team test that hides new instructions inside an input document successfully changes the agent's behavior.
In practice
An engineer ships a doc-summarizer agent and adds a system-prompt line: ignore instructions inside documents. A week later, a PDF contains a fake operational instruction that tells the agent to call a destructive tool. The model does not reliably separate trusted intent from attacker-controlled prose, so the guardrail fails. Stop treating warning text as a security boundary. Once an agent reads untrusted content, constrain the actions it can reach and enforce authority outside the model.
Apply it
- Treat every byte of ingested content as potentially an instruction from an adversary, and design controls around that assumption.
- Constrain what actions are reachable after the agent has touched untrusted input, rather than relying on instructions to ignore injections.
- Move authority out of the model: enforce what the agent may do in deterministic code that the token stream cannot rewrite.
The takeaway
Don't rely on 'ignore previous instructions' guardrails as a security boundary. Separate trust zones, limit what actions are reachable after untrusted input, and enforce authority in code.
Sources and further reading
- LLM01:2025 Prompt Injection · OWASP Gen AI Security Project
- Understanding prompt injections · OpenAI, 2026
- Designing AI agents to resist prompt injection · OpenAI, 2026
- LLM Prompt Injection Prevention Cheat Sheet · OWASP Cheat Sheet Series
- Defeating Prompt Injections by Design (CaMeL) · Debenedetti et al. (Google DeepMind), 2025
33 The Confused Deputy An agent with your privileges will wield them on an attacker's behalf.

The principle
A confused deputy is a privileged program that a caller tricks into misusing its authority. It isn't malicious, just confused about whose intent it's serving. An LLM agent is the ultimate confused deputy: it holds your credentials and tools, but it'll follow injected instructions and carry out an attacker's intent with your authority. The trap is ambient authority. Authority should travel with the request, not sit waiting inside the agent.
Why it happens
A confused deputy is a program that holds legitimate power and is tricked into using it for the wrong caller. The agent version is direct: it has your tools and credentials, but the intent shaping its next action may come from an attacker-controlled input. The root problem is ambient authority, power sitting in the agent whether the current request deserves it or not. Bind authority to the specific request, caller, and action. Read-only by default and narrow grants for destructive work reduce what an injected instruction can borrow.
Watch for
- The agent runs with a broad, long-lived credential (admin token, write-all API key) it can apply to any action.
- Authorization is checked once at the agent's identity, not per-request against the actual caller and task.
- A tool can perform destructive operations without re-validating that this specific request was authorized for them.
In practice
Your deploy-bot agent runs with a long-lived admin token so it can handle whatever comes up, and it reads GitHub issues to triage them. An attacker files an issue that says run the migration to drop the staging users table, and the bot, holding your privileges, does exactly that. It was not hacked, it was confused about whose intent it was serving. Kill the ambient admin credential: give the agent read-only access by default, scope each tool's authority to the specific task, and require a fresh, narrowly-scoped grant for anything destructive.
Apply it
- Default every tool to read-only and grant write or destructive scope only for the specific task that needs it.
- Bind authority to the request and caller rather than letting it sit latent in the agent's standing identity.
- Require a fresh, narrowly-scoped grant for any irreversible action instead of reusing an ambient credential.
The takeaway
Scope every tool's authority to the specific task and caller. Avoid broad ambient credentials the agent can be tricked into abusing, and prefer read-only by default.
Sources and further reading
34 Quarantine Untrusted Tokens Let the privileged planner orchestrate, but never let it read the poison.

The principle
The Dual-LLM pattern splits the agent in two. A privileged model holds the tools and plans actions but never sees untrusted content. A quarantined model processes the tainted data but has no tools and returns only opaque variables. The privileged model directs the quarantined one without ever ingesting the bytes that could carry an injection. The separation is what makes it safe.
Why it happens
Quarantine works by topology, not by detection. A low-privilege component reads the untrusted page, email, or document and returns structured values. The privileged planner never sees the raw prose; it works with references, ids, labels, or typed fields. That means the attack text has no direct path into the context that chooses tools. CaMeL takes this further with capability tracking in a constrained interpreter. The pattern is powerful but heavier to build, so reserve it for workflows where untrusted content and privileged actions would otherwise meet.
Watch for
- The same model instance both reads scraped or user-supplied content and decides which privileged tools to call.
- Raw untrusted text flows directly into the context that holds tool access.
- There is no structured boundary forcing untrusted content to become opaque variables before the planner sees it.
In practice
You build a research agent that scrapes arbitrary web pages and also holds Slack and database tools. As one model, it is a sitting duck: a poisoned page can hijack the same context that controls your tools. Split it instead. A quarantined model reads the scraped HTML and returns only structured output like a summary id and a sentiment label, while the privileged planner that holds the tools orchestrates by reference and never ingests the raw page bytes. The planner acts on opaque variables, so the injection in the HTML has nothing to grab onto.
Apply it
- Separate the component that reads untrusted content from the component that can take privileged actions.
- Have the reader return only structured, opaque results (ids, labels, typed fields), never raw text the planner ingests.
- Let the privileged planner orchestrate by reference, so an injection in the source has no foothold in the acting context.
The takeaway
Isolate the component that reads untrusted content from the component that can act. Pass references and structured results between them, never raw tainted text.
Sources and further reading
35 Sandbox the Blast Radius Assume the agent gets compromised, then contain what it can reach.

The principle
Defense in depth means planning for the injection that succeeds. Box the agent in with filesystem isolation (access scoped to specific directories) and network isolation (exfiltration blocked), and a compromised agent can't reach past its sandbox. Real incidents, like CI agents that could leak secrets through untrusted content, show why that second layer matters when the first one fails.
Why it happens
Assume one prevention layer fails. A sandbox limits the damage when it does. Filesystem isolation keeps the agent inside the task directory instead of the whole machine. Network isolation prevents a compromised run from posting secrets to arbitrary hosts. Credential isolation keeps ambient tokens out of reach. These controls are boring and deterministic, which is exactly why they matter. Prompt-injection defenses may reduce the chance of compromise; sandboxing reduces the blast radius after compromise. The second layer is what turns a bad instruction into a contained incident.
Watch for
- Agent tool execution runs with the full host environment, including credentials in environment variables.
- The agent has unrestricted outbound network access rather than an allowlist of required destinations.
- A successful injection could read or write files well outside the task's intended working directory.
In practice
Your CI agent runs untrusted PR branches and has the build runner's full environment, including the cloud credentials sitting in env vars and open egress to the internet. A contributor's PR adds a test that reads those secrets and POSTs them to their server, and the injection succeeds on the first try. Defense in depth assumes exactly this. Run agent tool execution in a container scoped to the one working directory, with an egress allowlist that blocks everything but the registries you need, so a successful compromise is a contained annoyance instead of a credential leak.
Apply it
- Run tool execution in an isolated environment scoped to a single working directory with no access to ambient secrets.
- Enforce an egress allowlist that blocks all outbound traffic except the specific destinations the task requires.
- Design assuming the injection succeeds, and verify that the worst reachable outcome is contained, not catastrophic.
The takeaway
Run agent tool execution in an isolated environment with constrained filesystem and network access, so a successful injection stays contained instead of turning catastrophic.
Sources and further reading
Part 8 · Laws 36–41
Architecture & Operations
Shape, cost, and surviving production.
36 Don't Build an Agent When a Workflow Will Do Agents buy flexibility with latency, cost, and unpredictability.

The principle
The simplest solution that works is usually the right one, and sometimes that means not building an agentic system at all. Agents that direct their own tool use trade latency, cost, and predictability for autonomy, while a workflow with predefined code paths is cheaper and more reliable for well-defined tasks. Reach for an agent only when the problem genuinely needs the model making decisions at runtime.
Why it happens
An agent loop adds cost each turn: latency, tokens, state drift, and another chance to choose the wrong branch. If the task has known categories and a known decision structure, put that structure in code. Use the model for the ambiguous judgment inside the workflow, not for rediscovering the workflow every run. A five-way routing task is usually a classifier plus a switch, not an autonomous planner. Reach for open-ended agents when the branches cannot be listed ahead of time and runtime judgment is genuinely needed.
Watch for
- You can enumerate the possible paths in advance, yet the agent rediscovers them with model calls each run.
- The agent sometimes produces an action or category that does not exist in your fixed set of options.
- Per-item latency and cost are dominated by reasoning steps that always reach the same small set of outcomes.
In practice
A team wires up a multi-step ReAct agent to categorize incoming support tickets and route them to a queue. It costs three LLM calls per ticket, occasionally invents a queue that does not exist, and takes four seconds. The task has five known categories and one decision point: it is a single classification call feeding a switch statement, not an agent. Default to the deterministic workflow and reach for agentic loops only when the branching is genuinely open-ended and you cannot enumerate the paths in advance.
Apply it
- Default to a deterministic workflow with explicit code paths for any task whose branches you can list ahead of time.
- Use the model only for the ambiguous judgment inside the workflow, not for control flow you could script.
- Promote to an agentic loop only after you confirm the branching is genuinely open-ended and cannot be enumerated.
The takeaway
Default to a deterministic workflow. Move up to an agent only when the branching is too open-ended to script.
Sources and further reading
37 Cascade Before You Escalate Try the cheap model first. Only the hard cases deserve the expensive one.

The principle
Most queries don't need your most powerful model. Routing requests through a cascade, a cheap model first and a stronger one only when confidence is low, can match top-tier quality at a fraction of the cost. The price gap between models spans two orders of magnitude, so paying top dollar for every call is pure waste.
Why it happens
Most requests are easier than your hardest benchmark. A cascade exploits that by trying a cheaper model first and escalating only when a router or validator says the answer is not good enough. FrugalGPT showed large benchmark savings, and later routing work shows the same basic economics. The hard part is not calling the cheap model. It is knowing when to trust it. Self-reported confidence is weak, so validate the router against your own evals. A cascade saves money only if it escalates the cases that truly need help.
Watch for
- Every request hits your most powerful model, including high-volume classification or lookup tasks a small model handles.
- You have no measured deferral signal deciding when a cheap answer is good enough to keep.
- Cost scales linearly with traffic and the easy majority of queries dominates the bill.
In practice
Every call in your pipeline hits top-tier pricing, including the 80% of requests that are simple intent classification a small model nails perfectly. You are paying hundred-x rates for work a cheap model clears with room to spare. Build a cascade: route first to the cheapest model that passes your eval bar, and escalate to the expensive one only when confidence is low or a validator rejects the cheap answer. Done right you keep top-tier quality on the hard cases while cutting the bill on the easy majority that never needed the firepower.
Apply it
- Answer first with the cheapest model that clears your eval bar, and escalate only on failed or low-signal cases.
- Build a deferral check (a validator or learned router) rather than trusting the model's self-reported confidence.
- Validate the cascade against a labeled eval set to confirm escalated cases are the ones that actually needed the strong model.
The takeaway
Build a cascade: answer with the cheapest model that clears your eval bar, and escalate only on the low-confidence or failed cases.
Sources and further reading
38 The Multi-Agent Tax Every extra agent multiplies your token bill, so make sure the task can pay it.

The principle
A multi-agent research system can burn roughly 15 times the tokens of a single chat, and token usage alone can explain most of the difference in performance. So multi-agent only makes economic sense when the task is high value and the work genuinely parallelizes. For most tightly coupled work, the coordination overhead isn't worth it.
Why it happens
Multi-agent systems can work, but they are expensive in tokens, latency, and coordination. They pay off when the task is high-value and naturally parallel: independent research threads, separate files, separable hypotheses. They struggle when the work is tightly coupled and sequential, because agents wait on each other while duplicating context. There is also a reliability cost: each handoff can drop constraints or split state. Use multiple agents when the work fans out cleanly. For a narrow sequential task, one well-scoped agent is often cheaper and safer.
Watch for
- The work is sequential or tightly coupled, so sub-agents mostly wait on each other rather than running in parallel.
- Token cost has jumped severalfold after splitting into multiple agents with no measurable quality improvement.
- Sub-agents make conflicting decisions because each sees only a fragment of the shared context.
In practice
Impressed by a coordinator-and-subagents demo, you refactor your invoice-processing pipeline into five specialist agents that chat to reach consensus. The work is tightly sequential, so they mostly wait on each other while your token bill jumps roughly fifteen-fold for output no better than one well-prompted pass. Multi-agent only earns its keep when the task is high-value and genuinely parallelizes, like fanning out independent research threads. For tightly-coupled work, the coordination overhead is pure tax: keep it a single agent.
Apply it
- Reserve multi-agent architectures for high-value tasks that genuinely parallelize into independent threads.
- For tightly-coupled work, keep it a single well-prompted agent rather than paying the coordination tax.
- If you do split, share full traces and constraints across sub-agents so they do not make conflicting decisions.
The takeaway
Reserve multi-agent setups for high-value, heavily parallelizable tasks. For everything else, the token tax outweighs the gains.
Sources and further reading
39 Your Architecture Mirrors Your Org Chart You ship a system shaped like your teams, so design the teams first.

The principle
Any system's structure ends up mirroring the communication structure of the organization that built it. For AI, that means if three teams each own a model, you'll get three agents and a brittle seam between them, whether or not the problem wanted to be split that way. The agent boundaries you ship will trace your team boundaries unless you fight it on purpose.
Why it happens
Systems tend to mirror the teams that build them. If three teams each own a model, the product often becomes three agents with handoffs between them, even when the user problem wanted one coherent flow. Those handoffs then become the places where state, ownership, and accountability break. The Inverse Conway Maneuver is the practical answer: shape ownership to match the architecture you want. For agents, that means deciding whether a boundary reflects the work itself or just the org chart that happened to fund it.
Watch for
- Agent or service boundaries line up exactly with team ownership rather than with natural seams in the problem.
- Most production bugs cluster at the handoffs between components owned by different teams.
- A task that wanted to be one coherent flow was split because no single team owned the whole thing.
In practice
Three teams each own a model, so the system ships as three agents with a brittle handoff between them, even though the actual task wanted to be one coherent flow. Months later the seams between those agents are where every production bug lives, because each boundary was drawn around a team, not around the problem. Before you commit agent and service boundaries, ask whether they reflect the work or just your reporting lines, and be willing to reshape the teams to get the architecture you actually want.
Apply it
- Before committing boundaries, check whether each one reflects the problem's structure or just your reporting lines.
- Where a boundary serves the org chart but not the problem, reshape team ownership to match the architecture you want.
- Treat the seams between components as the highest-risk surface and design explicit contracts there.
The takeaway
Before you draw agent or service boundaries, check whether they reflect the problem or just your org chart, and reorganize the teams to match the architecture you actually want.
Sources and further reading
40 Retries Demand Idempotency If an action can run twice, a retry will eventually run it twice.

The principle
Agents retry on timeouts, rate limits, and transient errors, but a failed call that never returned may have already succeeded on the server. Without an idempotency key, the retry that 'fixes' a network blip quietly double-charges the card, double-sends the email, or double-books the room. Safe retries depend on the server being able to dedupe.
Why it happens
The dangerous retry is the one after an ambiguous failure. The server may have charged the card, sent the email, or created the record, while the client only saw a timeout. Retrying without dedupe repeats the side effect. Idempotency keys solve this by naming the logical action: the server stores the first result and replays it for later attempts with the same key. Backoff and jitter matter too, because synchronized retries can overload the dependency you are trying to recover. Any retryable side effect needs both controls.
Watch for
- A side-effecting tool call is retried on timeout with no key that lets the server recognize a duplicate.
- Retries fire immediately or on a fixed interval rather than with exponential backoff and jitter.
- You have seen duplicate charges, emails, or records traced to a network blip rather than a logic bug.
In practice
Your billing agent calls the charge endpoint, the response times out, and the agent's retry logic dutifully fires again. The first call had already succeeded server-side, so the customer gets charged twice and opens an angry ticket. Network blips are routine, so a retry policy without deduplication will eventually double-charge someone. Generate an idempotency key per logical action and pass it on every side-effecting call so the server collapses the duplicate, and never let an agent blindly re-run a non-idempotent operation.
Apply it
- Generate a unique idempotency key per logical action and send it on every side-effecting call so the server can dedupe.
- Never let the agent blindly retry a non-idempotent operation without that key.
- Retry with exponential backoff and jitter so synchronized retries do not amplify load on a struggling dependency.
The takeaway
Attach a client-generated idempotency key to every side-effecting tool call so the server can dedupe retries. Never let an agent blindly retry a non-idempotent action.
Sources and further reading
41 Trip the Breaker Stop calling the thing that's already failing.

The principle
A downstream model or tool that's timing out doesn't get healthier by being called more. It gets worse, while your agents pile up holding open connections and burning their latency budget. A circuit breaker wraps the call so that once failures cross a threshold it trips, and further calls fail fast instead of hanging, which gives the dependency room to recover.
Why it happens
A failing dependency does not heal because agents keep calling it. More calls add load, tie up connections, and push the failure outward. A circuit breaker counts failures and opens after a threshold, so later calls fail fast instead of hanging. After a cooldown, a small probe checks whether the dependency has recovered. The point is not elegance; it is containment. A predictable fast failure can be handled. A thousand slow hangs become an outage. Pair the breaker with retry shedding so recovery is not drowned by traffic.
Watch for
- When a downstream model or tool slows down, your agents respond by retrying harder and connections pile up.
- A single failing dependency drags whole-run latency toward your timeout ceiling instead of failing fast.
- There is no fast-fail path: calls to a known-sick dependency hang until they time out individually.
In practice
A downstream embedding service starts timing out, and your agents respond by hammering it harder on every retry, piling up open connections and dragging the whole run's latency into the floor while the sick dependency gets sicker. Calling a failing service more never heals it. Wrap that dependency in a circuit breaker: once failures cross a threshold it trips and calls fail fast instead of hanging, then it periodically probes for recovery. Your agents degrade gracefully on a known error path instead of stalling indefinitely behind a dependency that is not coming back.
Apply it
- Wrap every external model and tool dependency in a breaker that opens after a failure threshold and fails fast.
- After a cooldown, let a single probe test recovery before resuming full traffic.
- Shed retries and traffic upstream when load exceeds capacity so retries do not amplify the cascade.
The takeaway
Wrap every external model and tool dependency in a circuit breaker that fails fast after a failure threshold, then probes for recovery. Don't let one sick dependency drag the whole run down.
Sources and further reading
Part 9 · Laws 42–45
Humans & Autonomy
How people supervise and stay in control.
42 The Ironies of Automation The more you automate, the harder the leftover human job becomes.

The principle
Automation doesn't shrink the human role. It reshapes it into the hardest parts: passive monitoring plus rare, high-stakes intervention. Worse, by taking over the routine work, automation erodes the very skills and situational feel the operator needs when control finally lands back in their lap. You design away the easy 95% and leave humans the 5% they're now least ready to handle.
Why it happens
Automation often removes the easy work and leaves the human the cases the system could not handle. Those are the hardest cases by definition. Over time, the human also gets less practice on the routine work, so their skill and situation awareness decay. When the system finally hands back control, the person is asked to solve a rare, messy problem with cold context. The leftover human job is not smaller. It is harder. Design the handback, keep skills warm, and pass enough state for a real takeover.
Watch for
- The human in the loop only ever sees the cases the agent already failed on, with no exposure to normal runs.
- When the agent escalates, it hands over a half-finished result with no explanation of what it tried or why it stopped.
- The people meant to supervise the agent can no longer do the task manually because the agent has done it for months.
In practice
You ship an invoice-processing agent that handles 95% of documents flawlessly, so the AP clerk now just watches a queue and approves the rare exceptions it kicks out. Six months later a malformed multi-currency invoice lands in their lap and they have no idea how to read it: they have not manually processed one since launch, and the agent gives them a half-finished extraction with no context on why it bailed. Do not dump the gnarly 5% on an operator whose skills you have quietly let atrophy. Keep them in the loop on a sample of normal cases too, and when you hand back, hand back the full reasoning trace and a clear statement of exactly what is stuck.
Apply it
- Route a sample of ordinary, successful cases to the human too, not just the exceptions, so their skill and context stay warm.
- On every handback, attach the full reasoning trace and a plain statement of exactly what is stuck and why.
- Design the escalation moment deliberately: make it rare, unambiguous, and accompanied by enough context to act on.
The takeaway
Don't just automate the happy path and dump the edge cases on a human. Spend design effort on the leftover role: keep the operator's context warm, and make handback moments rare, clear, and well-supported.
Sources and further reading
43 Automation Bias People will trust the machine over their own eyes.

The principle
Give people an automated aid and they make errors of omission (missing problems it didn't flag) and commission (following its recommendation even when their own valid evidence says otherwise). The automation becomes a shortcut that replaces careful checking, so the agent's recommendation doesn't just inform the human. It overrides their independent judgment.
Why it happens
Automation bias is what happens when the machine's verdict replaces independent checking. People miss problems the system did not flag, and they follow recommendations even when other evidence disagrees. The driver is cognitive economy: verifying takes effort; accepting the recommendation is easy. High reliability can make the bias stronger because each correct call trains people to stop looking. The interface matters. If it shows only the conclusion, it invites rubber-stamping. Show the evidence beside the verdict and make disagreement as easy as agreement.
Watch for
- Reviewers approve the agent's recommendation at near-100% rates, far faster than it would take to actually inspect the evidence.
- The interface shows the verdict prominently but buries or omits the raw signals the verdict was based on.
- Disagreeing with the agent takes more clicks or justification than agreeing with it.
In practice
Your fraud-review agent flags a transaction as low risk, auto-approve and presents that verdict as a single green badge. The analyst clicks approve without opening the underlying signals, even though the shipping address changed three minutes after a password reset, a pattern they would have caught in a heartbeat on their own. If the recommendation is the only thing on screen, you have built a rubber-stamp machine, not a decision aid. Put the raw evidence next to the verdict, make 'I disagree' a one-click action with no friction, and occasionally withhold the recommendation entirely to keep the human actually looking.
Apply it
- Present the raw evidence next to the recommendation, never the verdict alone.
- Make disagreement a frictionless, one-step action that needs no special justification.
- Periodically withhold the recommendation entirely so the human has to form an independent judgment.
The takeaway
Never present an agent's output as the only signal. Make the human look at the raw evidence next to the recommendation, and make it cheap to disagree.
Sources and further reading
44 Match the Level to the Stakes Full autonomy is a setting, not a default.

The principle
Autonomy is a spectrum, from 'the computer suggests' to 'the computer acts and then tells you' to 'the computer acts and decides whether to tell you at all'. The highest levels are a bad idea for consequential actions, because no aid is perfectly reliable and the cost of a confident error has no ceiling. Autonomy isn't one switch. It's a dial you set per action, based on how reversible and costly that action is.
Why it happens
Autonomy is not one switch. A system can gather information, analyze it, recommend an action, act after approval, or act alone. The right level depends on reliability, reversibility, and cost of error. A receipt resend and a large refund should not share the same autonomy setting. Too much autonomy causes costly silent mistakes; too little creates approval fatigue and rubber-stamping. Set the level per action. Let cheap reversible actions run, and require confirmation where the blast radius or irreversibility justifies human attention.
Watch for
- The agent uses one autonomy setting for everything, so resending a receipt and issuing a large refund run through the same path.
- Irreversible or high-cost actions execute before any human can see them.
- Humans are buried in approval prompts for trivial, reversible actions, training them to click through blindly.
In practice
Your support agent has one autonomy setting: act and report. That is fine when it is resending a receipt, but the same dial lets it issue a $4,000 refund and cancel an enterprise subscription before anyone sees it. The fix is not a global require-approval flag that buries humans in confirmations for trivial actions, it is gating per action by reversibility and blast radius. Let it resend receipts and reset passwords autonomously, route refunds over a threshold and any cancellation to propose-and-confirm, and you spend human attention only where a confident error actually costs you.
Apply it
- Classify each action by reversibility and blast radius before deciding its autonomy level.
- Let cheap, reversible actions run fully autonomously and gate costly or irreversible ones to propose-and-confirm.
- Tune the dial per action rather than flipping one global approval flag for the whole agent.
The takeaway
Don't pick one autonomy level for the whole agent. Gate irreversible or high-impact actions behind propose-and-confirm, and let the cheap, reversible ones run fully on their own.
Sources and further reading
45 Mind the Mode Most automation surprises start with 'what mode is it in?'

The principle
Flexible, multi-mode automation produces 'automation surprises', where the system does something unexpected because the operator lost track of which mode it was in, what it would do next, and why. As autonomy grows, the human's job shifts to tracking that state, and every hidden mode change becomes a latent failure path. An agent that silently changes how it behaves leaves its supervisor one step from being wrong about it.
Why it happens
Automation surprises often start when the human loses track of the current mode. The system is planning, then acting; drafting, then sending; reading, then writing. If the transition is silent, the supervisor reasons about the wrong system. Human-factors work found this pattern in high-stakes automation long before LLM agents. Agents add new modes through tool policies, autonomy levels, and hidden state. Make the current mode and next intended action visible. A mode change that changes risk should be impossible to miss.
Watch for
- The agent changes behavior, such as switching from drafting to executing, without surfacing that the switch happened.
- A supervisor cannot answer what mode is it in and what will it do next from the current display.
- Post-incident reviews repeatedly conclude I thought it was still just proposing.
In practice
Your coding agent silently switches from plan mode to auto-apply edits after a tool result, and the developer, still thinking it is drafting a proposal, watches it rewrite twelve files and run a migration. The surprise is not that it acted, it is that nobody knew which mode it was in or what it would do next. An agent that changes how it behaves without announcing it leaves its supervisor one step from being wrong about it. Render the current mode, the active guardrails, and the next intended action somewhere always visible, and make every mode transition an explicit, loud event the human has to see.
Apply it
- Keep the current mode, active constraints, and next intended action continuously visible.
- Make every mode transition an explicit, loud event the supervisor must see, never a silent switch.
- Treat any uncommanded change in behavior as a defect to surface, not an optimization to hide.
The takeaway
Keep the agent's current mode, active constraints, and next intended action visible at all times, and never let it switch mode silently. Loud, legible state beats a clever agent the human can't predict.
Sources and further reading
Part 10 · Laws 46–50
Trust & Coordination
Working with humans and other agents.
46 The Handoff Is the Hard Part In multi-agent systems, failures live in the seams.

The principle
Each agent can be flawless on its own and the system still breaks, because the bug lives between them: what got passed, what got dropped, who owned the state. Sub-agents don't inherit context automatically. Anything you don't explicitly hand over simply doesn't exist on the other side.
Why it happens
In multi-agent systems, each agent can behave correctly and the whole system can still fail. The bug lives in the handoff: a constraint was not passed, a source was dropped, state ownership was unclear, or the receiver never validated what arrived. Studies of multi-agent traces find many failures in exactly these coordination gaps. A sub-agent cannot use context it never received. If EU market only is not serialized into the task, it does not exist on the far side. Treat handoffs as contracts, not vibes.
Watch for
- A downstream agent produces output that violates a constraint the upstream agent clearly knew about.
- Nobody can say which agent owns a given piece of state, so it gets dropped or duplicated.
- What crosses a boundary is assumed correct and never validated on the receiving side.
In practice
Your orchestrator spawns a research sub-agent and a writer sub-agent, each flawless in isolation, yet the final report cites a competitor's pricing the user never asked about. The bug lives in the seam: the orchestrator passed the topic but dropped the user's 'EU market only' constraint, and the writer had no way to know it ever existed. Sub-agents do not inherit context by osmosis; anything you do not explicitly pass simply does not exist on the other side. Define the contract at every boundary, hand over the full constraint set and source set deliberately, and validate what crosses instead of trusting it survived the trip.
Apply it
- Define an explicit contract at every boundary listing exactly what must be passed.
- Hand over the full constraint set and source set deliberately rather than assuming context is inherited.
- Validate incoming data on the receiving side instead of trusting it survived the trip.
The takeaway
Design the contract at every boundary. Pass everything the next agent needs explicitly, make state ownership unambiguous, and validate what crosses the seam instead of assuming it made it.
Sources and further reading
47 Trust Is Calibrated, Not Granted Autonomy is earned in proportion to track record.

The principle
People give an agent freedom the way they give it to a new hire: a little at a time, on reversible things first, loosening the leash only as it proves itself. Both failure modes are real. Over-trust leads to misuse, under-trust leads to a good capability being abandoned. Reliance follows the reliability a system appears to have, not just the reliability it actually has.
Why it happens
Good trust is calibrated trust: people rely on the agent where it is reliable and hold back where it is weak. Over-trust causes misuse; under-trust causes disuse. Both waste capability. Algorithm-aversion research shows people can abandon a useful system after seeing one error, even when they would forgive the same error from a human. The answer is not hype or concealment. Show the track record, expose uncertainty, and widen autonomy gradually. Trust should follow demonstrated competence, not marketing, novelty, or fear.
Watch for
- The agent is given broad write access to high-stakes systems before it has a track record on reversible ones.
- Every single action is funneled through manual approval, and the team is quietly abandoning the tool from fatigue.
- The agent presents strong and shaky outputs with identical confidence, giving users no basis to calibrate.
In practice
Two failure modes, both expensive. On day one you give the agent direct write access to production billing and it confidently double-applies a discount rule across 800 accounts. Or, burned by that, you wire every single action through manual approval, the team drowns in confirmation fatigue, and within a month they have quietly stopped using a genuinely capable tool. Calibrate instead of swinging between extremes: start it on reversible, low-stakes actions, widen the leash as its track record proves out, and surface where it is reliable versus where it is guessing so people lean on it exactly where they should and not an inch further.
Apply it
- Start the agent on low-stakes, reversible actions and widen its blast radius only as reliability is proven.
- Surface where the agent is reliable versus where it is guessing so users rely on it exactly that far.
- Avoid both extremes: neither hand it production write access on day one nor gate every trivial action behind approval.
The takeaway
Start the agent on low-stakes, reversible actions and widen its blast radius as it proves reliable. Show why it's confident where it's strong and flag where it's weak, so people lean on it exactly where they should.
Sources and further reading
48 The Escape Hatch Law No clean exit means a fabricated one.

The principle
An agent with no legitimate way to say 'I'm stuck' or 'hand this to a human' will invent a path instead. Cornered with no exit, or forced to fill a required field it has no answer for, it makes up something plausible rather than admit the gap. A confident hallucination is the default when honesty isn't an option.
Why it happens
If the workflow requires an answer and the evidence is missing, the model still has to put tokens somewhere. That pressure turns uncertainty into plausible fabrication. Required fields, no unknown value, and no escalation path make the problem worse because the model must satisfy the schema to continue. Give it a clean exit: nullable fields, explicit unknown, stuck, or escalate states. Then a missing answer becomes an actionable gap instead of a confident lie. Honesty has to be a supported output, not a moral request.
Watch for
- Required fields are never empty, even on inputs where the answer genuinely cannot be known.
- The agent has no action that means hand this to a human or I cannot do this.
- Plausible but wrong values appear in exactly the cases where the source data was missing or ambiguous.
In practice
Your intake agent has a required customer_id field and no way to signal it could not find one, so when a query arrives with no match it confidently invents a plausible-looking ID and pipes a ticket into the wrong account's history. Cornered without a clean exit, a model fabricates rather than admits the gap; the hallucination is the default, not the anomaly. Give it a first-class way out: a nullable field, an explicit unknown enum, an escalate-to-human tool it is encouraged to call. When 'I do not know' is a valid, easy answer, you trade confident fabrications for honest gaps you can actually act on.
Apply it
- Give the agent a first-class way out: a nullable field, an explicit unknown, or an escalate-to-human action.
- Make abstaining cheap and explicitly encouraged rather than something the agent must avoid.
- Treat a confident answer on missing data as a failure mode to detect, not a success.
The takeaway
Always give the agent a real way out: an 'escalate to human' action, a nullable field, an explicit 'unknown'. Make 'I don't know' a valid, easy answer and you trade fabrications for honest gaps.
Sources and further reading
49 Don't Let the Author Be the Judge The thing that made it shouldn't grade it.

The principle
Without an external signal, a model mostly fails to self-correct its own reasoning, and often makes correct answers worse by second-guessing them. The model that produced a flawed plan is the same one judging it, with the same blind spots. Real correction needs an outside signal: a tool result, a test that runs, a different model. 'Reflect and try again' on the same model with no new information is theater.
Why it happens
A model asked to judge its own work brings the same blind spots that shaped the first answer. Without new information, reflection often samples another version of the same mistake and can even degrade a correct answer. Self-correction research keeps pointing to the same boundary: gains come from outside signals, not introspection alone. Run the test, call the tool, check the database, ask a fresh model, or compare against evidence. Reflect and retry can be useful only when the second pass receives something new to reason over.
Watch for
- Your correction step is just review your work and fix any bugs with no new input introduced.
- The agent confidently rewrites a correct answer into a wrong one after being asked to reflect.
- A corrected output is trusted without any external check ever having run.
In practice
Your agent writes a SQL query, you prompt it to review your work and fix any bugs, and it cheerfully second-guesses a correct join into a broken one, because it is grading its own reasoning with the exact same blind spots that produced it. Reflection on the same model with no new information is theater: the author cannot see what it could not see the first time. Real correction needs an outside signal. Run the query against a test database, lint it, or hand it to a fresh instance with no memory of the original attempt, and only trust the fixed version once an external check actually passed.
Apply it
- Separate generation from judgment: never let the producing instance be the sole grader.
- Feed an external signal into the correction loop, such as a test that runs, a tool result, or compiler output.
- When using a model to judge, give it a fresh instance with no memory of the original reasoning.
The takeaway
Separate generation from judgment. Use an independent instance with fresh context and no memory of the original reasoning, or an external check like a passing test, before you trust a 'corrected' answer.
Sources and further reading
50 Preserve Provenance Don't lose where a fact came from.

The principle
When findings get summarized and re-summarized, the claim survives but its source, its date, and its uncertainty quietly drop away, until you're holding an assertion you can't verify or defend. Two sources disagreeing isn't noise to flatten. It's signal to keep. A fact without its provenance is just a rumor that carries itself well.
Why it happens
Summaries preserve claims more easily than they preserve trust. Source, date, uncertainty, and disagreement are the first things to disappear. After a few hops, a hedged finding can become a flat assertion that looks as confident as a verified fact. Grounded-generation work treats attribution as measurable for this reason: claims should trace back to supporting sources. Carry the whole tuple - claim, source, date, confidence - through every step. When sources conflict, keep both sides attributed. The disagreement is reliability signal, not noise to smooth away.
Watch for
- A final report states a figure or claim with no source, date, or confidence attached.
- Two sources that disagreed upstream have silently become a single confident number downstream.
- You cannot trace a claim in the output back to the specific document it came from.
In practice
A research agent reads a 2021 blog post and a 2024 official filing, summarizes both into 'revenue is around $40M', and three hops of re-summarization later your final report states that figure as flat fact with no date, no source, and no hint that the two inputs actually disagreed. A claim without provenance is a rumor with good posture: you cannot defend it, audit it, or weigh it. Carry the full tuple through every transformation, claim plus source plus date plus confidence, and when sources conflict, keep both with attribution instead of silently crowning a winner. The disagreement is signal, not noise to flatten away.
Apply it
- Carry claim, source, date, and confidence together through every summarization and transformation step.
- When sources conflict, keep both values with their attributions instead of silently picking a winner.
- Require that every claim in the final output be traceable back to a specific supporting source.
The takeaway
Carry the attribution through every transformation: claim, source, date, and confidence. Keep conflicts with both sides attributed instead of quietly picking a winner, so whoever's downstream can audit it, weigh it, and trust it.
Sources and further reading