Debug the Prompt Like Code

A four-move playbook for debugging prompts like code: build an eval suite first, fix structural hygiene, clear out patch debt at migration, and add tools for capability gaps.

4:42 video5 min readWatch on YouTube

A prompt in production breaks on a model migration, with multiple contributors and no clear owner. A brand new agentic system gets built from zero, with no baseline at all. Different starting points, same underlying discipline: a prompt that works is debugged like code, with reproducible test cases and one failure mode addressed at a time. Anthropic engineer Margot Vanlar ran that discipline on a real production prompt, and it breaks down into four moves, applied in order.

Move one: write evals before you change anything

The first move is building an eval suite before touching the prompt at all, because without one, every change is an experiment with no control group. A complete suite needs three categories of test cases. Control cases are unambiguous queries the model should always pass, confirming nothing broke after a change. Edge cases are queries where the model has failed before, explicitly caught by the updated prompt. Boundary cases are queries the model should refuse or escalate, testing whether it knows the edge of its own role. Missing any one of these three categories leaves a blind spot in the eval suite, and these evals get run before and after every prompt change, for both the production-migration scenario and the from-zero scenario.

Move two: fix structural hygiene

Once a baseline exists, the second move is general cleanup before targeting specific failures. The rule here is straightforward: if you can't tell guidelines from policy from data inside the prompt, the model can't either. Fixing that means adding explicit XML tags for role, guidelines, policy, tone, customer context, and user message. That single structural change alone was enough to improve a failing test case, before any targeted instruction was even written. Adding a closing XML tag as a stop sequence also matters here, since it prevents runaway output, especially with structured or nested schemas.

Move three: clear out patch debt

The third move addresses what happens when defensive instructions outlive the problem they were written for. An instruction written to stop a hallucination on one model version can cause a different failure on the next. The example given: an instruction like "never give wrong plan details, point to the URL" was written to stop a hallucination on an earlier model version. On a newer model, followed literally, it caused the model to withhold correct information it already had in context. The fix is to apply this check at every model migration: audit every defensive instruction, check why it was originally written, and if the original failure no longer occurs on the new model, delete the patch.

Move four: instructions don't add capability, tools do

The fourth move is recognizing when a prompt is asking the model to do something it structurally can't do. An instruction like "always calculate proration correctly" does nothing, because the model cannot do reliable mental arithmetic no matter how the instruction is phrased. The fix is registering a tool: adding a proration calculator to the API call lets the model call it when needed, read the output, and explain the result. The general rule is that if a task requires exact arithmetic, deterministic lookup, or external state, it needs a tool. Instructions only change behavior within capabilities the model already has.

Both sides of every trade-off

A related trap shows up around telling a model to avoid something without stating the cost of avoiding it. An instruction like "avoid escalating" cost eight dollars per case and produced a model that never escalated, even on genuine billing errors, because the model optimized for exactly the goal it was given. The fix was stating both sides explicitly: weigh not escalating against the cost of refunds plus customer trust. More capable models optimize trade-offs more aggressively, so an incomplete cost function in the prompt produces stronger wrong behavior, not weaker.

Model, prompt, and harness together

For a staff-scheduling task with hard constraints, testing across five trials each showed that no single lever solved the problem alone. A simpler model with a simple prompt failed every trial. A more capable model with the same prompt reduced violations but still failed. The same capable model with extended thinking became compliant, at triple the token cost and triple the latency. The simpler model with a better-structured prompt passed two of five trials before hitting an output limit. The conclusion: test all three levers, model, prompt, and harness, before concluding the model itself is the bottleneck. For tasks with discrete, separable steps and clear pass-or-fail criteria, splitting one large prompt into three single-responsibility prompts, a generator that drafts, an evaluator that checks every hard rule and reports violations with evidence, and a repair step that makes targeted fixes to only the flagged violations, outperformed a single large prompt, with lower token count and lower latency, and the added benefit that soft constraints can be added to the evaluator at runtime with no code changes.

Key takeaways

  • Build an eval suite with control, edge, and boundary cases before changing a prompt; without it, every change is untestable.
  • Structure prompts with explicit XML tags separating role, guidelines, policy, and data, and use a closing tag as a stop sequence.
  • At every model migration, audit defensive instructions and delete ones written for failure modes the new model no longer has.
  • Instructions cannot add capability like arithmetic; tasks needing exact calculation, lookup, or external state need a registered tool instead.
  • State both sides of a trade-off explicitly in the prompt; an incomplete cost function produces stronger wrong behavior in more capable models.
  • For separable multi-step tasks, splitting a single large prompt into generator, evaluator, and repair roles can outperform one large prompt on cost and latency.

Try it yourself

Take a prompt you own and write five test cases: one control, two edge cases, and two boundary cases. Run them before changing anything, find the first failure mode, and apply one change at a time, structure first, then a targeted instruction, then a tool if instructions alone fall short. This explainer is narrated by Liam, in for Bear, and is part of the Claude prompting series from Humanitarians AI.

Chapters

  1. 0:00The playbook in four moves (verdict)
  2. 0:34Two scenarios, one discipline
  3. 0:54Two scenarios unpacked — production vs. zero
  4. 1:17Eval suite: control, edge, boundary
  5. 1:44Hygiene: XML structure + output contract
  6. 2:17Patch debt — old defensive instructions backfire
  7. 2:52Instructions don't add capability — tools do
  8. 3:25Both sides of the trade-off (billing escalation)
  9. 3:57New agent: model × prompt × harness
  10. 4:26Generate-evaluate-repair loop
Full transcript(auto-generated, with timestamps)

The playbook in four moves (verdict)

[0:00]Four rules for prompt engineering that hold up in production. One, write a vals before you change anything, control edge and boundary cases. Two, structure the prompt with XML tags. If you cannot parse it, neither can the model. Three, delete old defensive instructions when you upgrade models. Patches written for earlier models break on newer ones. Four, if a task needs arithmetic or a handoff, give the model a tool or an escalation path. Instructions alone cannot add that capability. Apply these four in order. Skip step one and you cannot tell whether anything else worked. Anthropic engineer Margaret Vanler just ran the prompting playbook

Two scenarios, one discipline

[0:34]On a real production prompt. This is Liam. Two scenarios, a prompt that broke on migration and a new agent built from zero. Same four steps apply to both. Here is what they are and when to use each one. Two scenarios engineers face constantly. First, a prompt in production with multiple contributors, no clear owner, and model migration breaking test cases. Second, a new agent

Two scenarios unpacked — production vs. zero

[0:55]From scratch with no baseline. The discipline is the same for both. You need a reproducible test suite before touching anything. Without one, every change is an experiment with no control group. Three categories of a val cases, all required. Control, an unambiguous query the model should always pass, confirms nothing broke. Edge cases, queries where the model has failed before, the prompt now catches them explicitly. Boundary queries the model

Eval suite: control, edge, boundary

[1:18]Should refuse or escalate, tests whether it knows the edge of its role. Missing any category means your a val suite has a blind spot. Run these before and after every prompt change. General cleanup before targeting specific failures. Rule, if you cannot tell guidelines from policy from data in the prompt, the model cannot either. Fix XML tags, role, guidelines, policy, tone, customer context, user message. That single structural change improved a failing test case before any targeted instruction was written. Also, add a

Hygiene: XML structure + output contract

[1:46]Stop sequence. A closing XML tag as the stop signal prevents runaway output. This matters most with structured or nested schemas. Patch debt, an instruction written to stop a hallucination on one model causes a different failure on the next. Example, never give wrong plan details, point to the URL, written to stop hallucination on V1. On V2, followed literally, model withholds correct information already in context. When to apply this rule at every model migration, audit every defensive instruction. Check why it was written. If the [clears throat] original failure no longer occurs, delete the

Patch debt — old defensive instructions backfire

[2:18]Patch. Instructions do not add capability. Critical, always calculate proration correctly does nothing. The model cannot do reliable mental arithmetic. The solution, register a tool. Add the proration calculator to the API call. The model calls it when needed, reads the output, explains the result. When to use a tool versus an instruction? If the task requires exact arithmetic, deterministic lookup, or external state, use a tool. Instructions only change behavior within capabilities the model already has. Give both sides of every trade-off in the prompt. Avoid escalating. It costs $8 per case produced a model that never

Instructions don't add capability — tools do

[2:53]Escalated, even on genuine billing errors. The model optimized for the goal it was given. The fix, state would not escalating costs to refund plus customer trust. Apply this everywhere you are telling the model to avoid something. More capable models optimize trade-offs more aggressively. An incomplete cost function produces stronger wrong behavior. Three levers model prompt harness. Staff scheduler hard constraints five trials each. Sonnet 46 simple prompt all fail. Opus 47 same prompt violations drop still failing. Opus with extended thinking compliant but triple tokens and

Both sides of the trade-off (billing escalation)

[3:26]Triple latency. Sonnet 46 with a better prompt two of five pass hits output limit. No single lever solved it. Test all three before concluding the model is the bottleneck. Three single responsibility prompts outperform one large prompt for constrained optimization. Generator drafts the schedule. Evaluator checks every hard rule and reports violations with evidence. Repair makes targeted fixes to violations only. Result, lower token count, lower latency than in large single prompt. Bonus, soft constraints go into the evaluator at runtime, no code changes required. Use this pattern

New agent: model × prompt × harness

[3:59]When the task has discrete separable steps with clear pass or fail criteria. Your turn, take a prompt you own, write five test cases, one control, two edge cases, two boundary cases. Run it before changing anything. Find the first failure mode, apply one change, structure first then a targeted instruction, then a tool if instructions fall short. Measure whether the failure count went down. Paste this into Claude to generate the eval suite. The prompting playbook, Humanitarian's AI.

Generate-evaluate-repair loop

[4:28]>> Humanitarian's AI. >> [bell]

More from Claude

Humanitarians AI Lyrical Literacy Project