Chapter 06
Prompt Engineering
Examples instead of adjectives, criteria instead of judgement, and retries that carry the actual error.
6.1
Show, don't describe
Two to four input/output pairs. An example pins down format and decision logic that no adjective can.
x.active acceptable · x.active == true flagged. Draws the line where prose cannottype, same schema~100g, precision approximate. Too varied for rules — this is where few-shot is strongest6.1b
Normalisation rules close the gap a schema leaves
A strict schema accepts "five bucks" in a string field. The prompt is where the format gets decided.
Always ISO 8601 YYYY-MM-DD. "yesterday" → compute the absolute date.
Numeric amount + currency code. "five bucks" → {amount: 5, currency: "USD"}.
Decimal fraction. "half" → 0.5, never "50%".
6.2
Explicit criteria beat adjectives
"Be conservative" has as many meanings as readers. A numbered list has one.
Check code comments for accuracy. Be conservative — report only high-confidence findings.
What counts as high confidence? Whose conservative?
Flag a comment ONLY if: 1. it describes behaviour that CONTRADICTS the code 2. it references a function or variable that does not exist 3. a TODO/FIXME refers to a bug already fixed in code Do NOT flag: - stylistically outdated comments - minor wording inaccuracies - missing comments (separate category)
An inclusion list and an exclusion list. The exclusions do most of the work.
| severity | means | example |
|---|---|---|
| critical | runtime failure for users | NullPointerException while processing a payment |
| high | security vulnerability | SQL injection, XSS, missing authorisation check |
| medium | logic bug, no immediate impact | wrong sort order, off-by-one |
| low | code quality | duplication, suboptimal algorithm on small data |
6.3
Prompt chaining
One focused prompt per unit of work, then one pass for what only shows up between them.
Chaining suits predictable, repeatable work — code review, file migrations. Open-ended investigation where the subtasks only become visible as you go wants dynamic decomposition instead.
6.4
The interview pattern
Have Claude ask its questions before it writes anything. The answers are context only you have.
Before implementing caching: which invalidation strategy — TTL or event-based? Is stale data acceptable when the cache is down? Per-user or global? What volume?
Unfamiliar domain (fintech, healthcare, legal), non-obvious implications (cache strategies, failure modes), or several viable approaches where the right one depends on context the model cannot see.
6.5
Retry with feedback
A bare retry re-rolls the dice. A retry carrying the specific error is a correction.
| situation | retry? | why |
|---|---|---|
| format error | yes | date in the wrong format — the model can reformat |
| structural error | yes | a field placed in the wrong location — it can move it |
| arithmetic | yes | it can re-add the line items |
| absent from source | no | the document does not contain the field. Retrying invites invention |
| context is elsewhere | no | the data lives in a document you did not provide |
Pydantic covers both halves in Python: types, requiredness and enums structurally, custom validators for business logic (items sum to total,start_date < end_date), and it generates the JSON Schema fortool_use — one source of truth instead of two that drift.
6.6
Make it check itself
Ask for the stated value and the computed value. The disagreement is the finding.
{
"stated_total": "$150.00",
"calculated_total": "$145.00",
"conflict_detected": true,
"line_items": [
{"name": "Widget A", "price": 75.00},
{"name": "Widget B", "price": 70.00}
]
}conflict_detected routes the document to review instead of quietly shipping $150.00 as fact.
Recall in 60 seconds
- Few-shot = 2–4 examples; strongest for ambiguity, output format, flag-or-not, and informal units.
- Examples teach a pattern, not a lookup table — the model generalises to unseen cases.
- Normalisation rules in the prompt (ISO dates, amount + code, decimal fractions) prevent valid-JSON-wrong-value.
- Replace adjectives with numbered criteria plus an explicit do-NOT list.
- Define severity levels with one concrete example each.
- Chain per file, then run an integration pass — cross-file issues appear nowhere else.
- Retry must carry the original input, the wrong output and the exact error; retry cannot conjure absent data.
- Ask for stated and calculated values plus
conflict_detectedto catch semantic errors.