Control Techniques
Agents default to confident action under ambiguity. Control techniques are prompt (and mode) patterns that interrupt that default: force questions, force a plan, constrain the blast radius, and demand evidence. Use them on every non-trivial Claude Code task; skip them only for mechanical, fully-specified edits.
The control stack (modes + prompts)
| Lever | What it constrains | When to tighten |
|---|---|---|
| Plan mode | Edits until you approve a plan | Anything with >1 file or an undecided design choice |
| Permission mode | Tool auto-approval | Unfamiliar repos, prod-adjacent paths, migrations |
| Prompt controls | Behavior inside an allowed run | Always — modes don't encode your acceptance criteria |
Repo steering (CLAUDE.md) | Every session | Recurring mistakes, never-dos, command recipes |
Modes are the seatbelt; the techniques below are the driving instructions. See Prompt Anatomy for the full prompt skeleton these techniques plug into.
1. Questions-first
Weak:
Add webhook retries for failed Stripe events.Strong:
Add webhook retries for failed Stripe events.
Before writing any code:
1. List open questions and undecided decisions (at least: retry policy,
idempotency, storage, which events, dead-letter behavior).
2. For each, propose a default AND the risk if that default is wrong.
3. Stop. Do not implement until I answer.
Do not invent product behavior to fill gaps.Why the delta matters: The weak prompt silently decides six product/ops choices. The strong prompt surfaces them as a reviewable list — usually cheaper than reversing a wrong retry store two days later.
Checklist — questions-first
- [ ] Prompt explicitly says "list questions before code"
- [ ] Prompt forbids inventing product/ops behavior
- [ ] You actually answer (or write answers into a spec) before allowing implementation
2. Plan-before-code
Claude Code plan mode is the primary lever. Reinforce it in the prompt so the plan is shaped the way you review:
Weak:
Refactor the invoice PDF generation to be async.Strong:
Refactor invoice PDF generation to be async.
Plan mode. Produce a plan that includes:
- Current call sites (file:line) and the proposed new flow
- Queue/worker choice and failure/retry behavior
- Migration path for in-flight requests
- Files you will touch (allowlist) and files you will not
- Verification steps (commands + manual checks)
Do not edit until I approve the plan. If the plan exceeds ~8 steps,
split into sequenced PRs and stop after proposing the split.Why the delta matters: "Async" without a plan often means "fire-and-forget in the request handler" or a new queue library you didn't ask for. The plan forces call-site inventory and an allowlist before the blast radius expands.
Checklist — plan-before-code
- [ ] Plan mode on (or equivalent "plan only, no edits")
- [ ] Plan names files, risks, and verification — not just vibes
- [ ] You approve, amend, or reject before any edit
3. Incremental implementation
Weak:
Implement the full billing proration spec.Strong:
Implement specs/012-billing-proration.md in increments.
Increment 1 only: pure proration function + unit tests for the examples
in the spec. No HTTP, no DB, no Stripe.
When increment 1 passes `make check`, stop and show:
- Diff summary
- Test output
- Open questions discovered
Do not start increment 2 until I say so.Why the delta matters: A full-spec run in one shot buries a wrong formula under layers of wiring. Incremental stops give you a human gate at the cheapest failure point. For work bigger than context, see Large Tasks.
Checklist — incremental
- [ ] First increment is the riskiest pure logic or the thinnest vertical slice — pick one deliberately
- [ ] Explicit stop between increments
- [ ] Each increment has its own verification command
4. Stop-and-ask
Weak:
Follow existing patterns. Use your best judgment on edge cases.Strong:
Constraints:
- If a decision is not in specs/012-billing-proration.md or CLAUDE.md,
STOP and ask. Do not invent.
- You MAY decide: local variable names, test fixture shape, log message text.
- You may NOT decide: HTTP status codes, error taxonomy, money rounding,
idempotency keys, or new dependencies.
If you hit a blocker, output: BLOCKER: <question> and wait.Why the delta matters: "Best judgment" is permission to invent requirements. An allowlist/denylist of decision classes is enforceable in review: any new dependency or status-code change without a question is a process failure.
Checklist — stop-and-ask
- [ ] Decision allowlist and denylist are explicit
- [ ] "STOP and ask" appears as a hard rule, not a suggestion
- [ ] Reviewer greps the diff for denylist items (deps, status codes, schema)
5. Constrained file scope
Weak:
Fix the N+1 query on the invoice list endpoint. Clean up anything nearby.Strong:
Fix the N+1 on GET /invoices.
Touch only:
- src/api/invoices/list.ts
- src/api/invoices/list.test.ts
- src/db/queries/invoices.ts (if query lives there)
Do NOT:
- Rename modules
- "Improve" unrelated handlers
- Add a repository abstraction
- Change response JSON shape
If the fix requires files outside this allowlist, stop and propose an
amended allowlist before editing.Why the delta matters: "Clean up anything nearby" is how architecture erosion lands in a one-line bugfix. Scope is a first-class acceptance criterion.
Checklist — file scope
- [ ] Allowlist present for any bugfix / small feature
- [ ] Explicit do-not list for common agent temptations (renames, new layers)
- [ ] Diff reviewed against allowlist before merge
6. Evidence requirements
Weak:
Make sure tests pass and nothing else broke.Strong:
When done, provide evidence — not claims:
1. Paste the exact command(s) run and their full exit output
(`make check`, plus any targeted test file).
2. Cite call sites checked for breakage (file:line) or `rg` output
showing no remaining old symbol.
3. If you did not run a check, say NOT RUN and why.
"Should be fine" / "tests pass" without output is incomplete.Why the delta matters: Agents hallucinate green builds. Pasted output is cheap; trusting a sentence is expensive. See Hallucination and False Confidence.
Checklist — evidence
- [ ] Prompt demands pasted command output
- [ ] Claims about "no callers" require search evidence
- [ ] You spot-check at least one command yourself on non-trivial PRs
Composing techniques (default recipe)
For a typical feature or non-trivial fix, stack them:
Read CLAUDE.md and <spec path>.
1. QUESTIONS FIRST: list open questions; stop if any block implementation.
2. PLAN MODE: plan with file allowlist, risks, verification; wait for approval.
3. IMPLEMENT incrementally per approved plan; STOP-AND-ASK on denylist decisions.
4. EVIDENCE: paste `make check` (and targeted tests) output; cite paths touched.
Out of scope: <list>
Do not touch: <paths>| Task type | Minimum controls |
|---|---|
| Rename / mechanical edit | File scope + evidence |
| Bug fix | File scope + evidence + stop-and-ask |
| Feature from spec | All six (plan mode mandatory) |
| Legacy change | Characterization tests first + all six — see Legacy Refactor |
| Recovery from bad output | Context reset + tighter scope — see Recovery |
Failure modes these techniques prevent
| Symptom | Missing control | Fix |
|---|---|---|
| PR invents product behavior | Questions-first / stop-and-ask | Amend spec; reject silent decisions |
| 20-file "cleanup" in a bugfix | File scope | Revert drive-bys; re-run with allowlist |
| "Tests pass" but CI red | Evidence | Require pasted local output; run yourself |
| Wrong design fully implemented | Plan-before-code | Plan mode; reject and re-plan |
| Session digresses into adjacent refactors | Incremental + scope | Reset context; one increment only |
Related
- Prompt Anatomy — the skeleton these techniques fill.
- Implementation Prompts — task-shaped prompts that already embed controls.
- Context and Instruction Hierarchy — why durable rules belong in
CLAUDE.md, not only in chat. - Why Agents Fail — the silent-assumption failure these patterns interrupt.
- Reviewing AI PRs — how to verify controls held in the diff.