InterviewPrepKit

Home / Cheat Sheet / AI Agent System Design

Cheat sheet

Scenario Debugging

Read the full lesson →

Most agent bugs are harness bugs, not model bugs: the model faithfully continues a context your code built wrong, so localize by finding where your intended context and actual context first diverge.

The five-part method

Answer these five in order; the common mistake is skipping to step 4.

1. Signal      what observable metric/log line reveals it?
2. Mechanism   the causal step, not a restatement of the symptom
3. Diagnostic  one command/field that splits causes ~in half
4. Fix         cheapest-in-QUALITY true fix first (not cheapest to build)
5. Verify      decide beforehand what moves, and what must stay true
  • “Cheap” means cheap in quality, not engineering hours.
  • A verify metric must move for the right reason: a loop detector that trips then fails every run renamed the bug, it did not fix it.

Bisect the harness (symptom not in the catalogue)

Get one good run and one bad run on the same input; every rung is a diff. Stop at the first that differs; prompt is last because it is the only rung a diff cannot settle.

#RungRules out
iDiff the two full serialized payloadsTemplating, retrieval, trimming, tool assembly
iistop_reason, usage, is_error, content blocksSilent truncation / tool failure / cache loss
iiiCalls per turn, results per turn, args-hash histogramRepetition, dropped results, lost parallelism
ivFive hashes: prompt, tool set, model id, index version, harness versionEnvironment drift, stale index, mid-session model switch
vRead the prompt, change one thing, re-run evalsNothing — which is why it is last

Numbers that recur

  • Cache multipliers (on input price): read 0.10x, write 1.25x. Ceiling saving 1.0/0.10 = 10x; a token flipped from read to write-and-never-read costs 1.25/0.10 = 12.5x (worse than no cache).
  • Quadratic history: input(n) = P + n·a; total = n·P + a·n(n+1)/2. Double the length, ~4x the bill. Context ceiling ≈ n/2 (~10x at turn 20).
  • Model routing cheaper tier is 3/5 = 0.6x price → only 1/0.6 = 1.67x saving, not “halves the bill.”
  • Multi-agent buys only context isolation; worth it above ~5x compression per worker, clearly worth 20x+, useless under 5x.
  • Birthday bound: 4 hex (16 bit) hash collides at ~7.3% for 100 items, ~49.6% for 300 — full digest in the guard, truncate only for printout.
  • ~20 cases = order-of-magnitude “do it by hand today,” not a power calc.

First diagnostic per symptom

SymptomLook at firstMechanism
Loops to step capArgs-hash histogramTranscript is a few-shot demo of itself
Tools disagree, answer matches neitherWas right value in context?No precedence in the forward pass
Cost grows faster than turnscache_read_input_tokens on call 2Quadratic resent history
Cost flat but 10x highcache_read_input_tokens = 0Broken cache prefix (one changed byte)
A few tasks cost 10-50xCost histogram, not meanModel can’t see its own spend
KeyError on missing toolPrompt capabilities vs TOOLS namesPrompt read as the action space
Irreversible action ranWhat can the credential express?Prompt rules are advisory
Wrong tool chosenConfusion matrixDescription overlap + schema volume
SlowSpan breakdown (prefill/decode/tools)Two latency terms; tools usually dominate
Malformed / wrong args20 calls read by hand vs intentUndeclared constraints are unenforced
Confident but wrongRecall@10 (0.4 retrieval vs 0.9 generation)Embeddings lossy for rare literals
Worse in prodFive-hash diffRendered tokens differ, source doesn’t
Cross-tenant leakIdentity fields in tool schemasModel output is not a trust boundary
Obeyed retrieved docLethal-trifecta checkNo privileged channel in attention
Evals pass, users complainGrade 100 real inputs by handYou chose the eval distribution
Says “done,” isn’tRun the goal predicate yourselfend_turn is a token, not a fact
Output cut mid-sentencestop_reason (= max_tokens, HTTP 200)Decode hit the cap
Lost parallel callsResults per assistant turnMessage-array shape is a demonstration
Valid JSON, wrong contentSchema field orderFields generate in order
Recall dies after rebuildCan a document find itself?Vectors are model-specific
Same prompt, different outputDiff 20 runs (near-tied tokens)Batched float non-associativity

Rules and gotchas

  • Enforce guarantees in code, not the prompt: precedence, budgets, tenant isolation, irreversible-action approval. A prompt only shifts probabilities; the tail is where production lives.
  • Loops come in three shapes: A identical repeat (hash args, trip at 3), B A/B/A cycle (hash state, trip at 2), C zero progress (track a monotone metric). A detector for one is blind to the others. Feed the trip back to the model before halting; halt only on a second trip.
  • Propose-then-apply: the guarantee is that approved is set by a path the model cannot call (approve is not a tool), NOT that the id is unguessable — the model is handed the id. Read-only credentials beat every prompt rule.
  • Tenant leak fix is to delete the identity parameter and inject it at dispatch, not guard it.
  • Reasoning fields first in a schema: score before reasoning rationalizes; the swap is the largest free quality win in structured output.
  • Verify cost per completed task, not per call. Track self-reported vs verified success; the gap is your real error rate.
  • Never return success on the budget-exhausted / truncated / predicate-failed path — return a partial result plus what’s missing.
  • Temperature 0 is not deterministic and there is no knob (sampling params removed). Fix the assertions (semantics, not string equality), don’t hunt the randomness.
Want the full picture? The lesson has the derivations, worked examples, and diagrams this card compresses into bullets. Read the full lesson →
Report a bug