Professional Agentic Product Engineering

Tier 2

Tier 2 — Plan: Shape and slice the work before you build, and give the agent the context it needs

You stop You do instead Climb when
Explaining the project; steering each step Decide the plan and the slice You can't trust the output without reading every line

Reach for this tier when big asks go sideways — the agent edits the wrong things or tries to do everything in one pass — or you re-explain the same conventions every session and it can't see your DB, browser, or docs. Plan first, then cut the work into small slices, each one small enough to check and cheap to undo. Engineer the project's context once — durable project memory plus the right tools — and it stops re-asking and guessing.

This is the triad externalized onto the page: intent becomes a written spec, context comes from investigating before you edit, and each slice is a constraint small enough to check and undo.

2.1 Investigate before you edit — a wrong mental model wrecks the diff.

Instead of: "Add OAuth." (straight to code)

Prefer: "Explore @src/auth, explain how it works, change nothing." → then "now implement OAuth."

2.2 Plan the uncertain; skip the plan for the trivial.

Instead of: a 6-step plan to rename a variable.

Prefer: plan multi-file or unfamiliar work; do one-sentence diffs directly.

2.3 Force an approval checkpoint and see what it will touch — nothing irreversible runs unseen.

Instead of: letting it touch 30 files unsupervised.

Prefer: "Numbered plan, risk per step, exact files to be created/modified/deleted. STOP for approval."

2.4 Ask for options, not the first idea.

Instead of: accepting plan #1.

Prefer: "Give me 2–3 approaches with a one-line trade-off each; I'll choose."

2.5 Slice vertically — thin end-to-end increments, not horizontal layers.

Instead of: "Build the whole course-catalog feature."

Prefer: "Slice 1: a user searches courses by department and sees results — UI → API → DB → test. Ship it green before slice 2."

A vertical slice is narrow, end-to-end, independently testable. It keeps each agent task inside the context window, makes dependencies explicit, and gives a working checkpoint after every slice instead of one giant unverifiable diff.

flowchart LR
  S1[Slice 1<br/>UI→API→DB→test ✓] --> S2[Slice 2<br/>UI→API→DB→test ✓] --> S3[Slice 3<br/>...]

2.6 Turn big features into a spec, then a fresh session.

Instead of: a 200-message thread that drifts.

Prefer: "Interview me on the hard parts, write SPEC.md" → new session: "Implement SPEC.md."

How: shape the behavior into the spec itself — a Story, Given/When/Then scenarios (.feature), and Non-goals — so "done" is concrete before any code. Keep scenarios crisp (one behavior each, concrete Then steps):

# Spec — refund eligibility
## Story
As a customer, I want to request a refund within 30 days so I'm not stuck with a bad purchase.
## Scenarios (.feature)
Scenario: Refund allowed inside the window
  Given an order placed 10 days ago
  When the customer requests a refund
  Then the refund is approved and the amount is credited
Scenario: Refund refused outside the window
  Given an order placed 45 days ago
  When the customer requests a refund
  Then the request is rejected with reason "window_expired"
## Non-goals
- Partial refunds (separate spec).

This is the shape; Tier 3 turns these scenarios into the loop's executable check (Tip 3.3).

Your first multi-model setup (the basics)

Two moves, no infrastructure — this is all the multi-model you need until you're orchestrating real work (the rest is the full playbook that opens Tier 5).

2.7 Plan with the smart model, build with the cheap one.

Instead of: running planning and coding on the same single model.

Prefer: /model opusplan — Opus reasons through the plan, Sonnet writes the code. One command, top-tier planning, without paying Opus rates on every edit.

How: type /model opusplan (or set "model": "opusplan" in .claude/settings.json). Switch by hand any time: /model opus for hard thinking, /model sonnet to implement, /model haiku for cheap bulk work, /model best for the current top of the ladder (Fable 5 where available, else latest Opus). Aliases auto-update to the recommended version; pin a full name like claude-opus-4-8 when you need it fixed.

That's the whole basic setup — two Anthropic models, one flag, zero infra.

2.8 Have one agent draft the spec and a different one critique it — before any code.

Instead of: one model writing SPEC.md and you trusting it.

Prefer: let one agent draft the spec, then hand it to a different model to attack: "You're the reviewer. Find gaps, wrong assumptions, missing edge cases, and unstated requirements in this spec. List them; don't rewrite." Feed the findings back to the author to revise. One or two rounds and the spec is far harder than a single model produces.

How: quickest is two chat tabs (Claude drafts, ChatGPT/Gemini critiques, repeat).

Inside Claude Code, make it a loop: a spec-author subagent writes SPEC.md and a spec-critic subagent (different model:) reviews it — the critic's different blind spots are the point.

The spec is the contract the whole build runs against (Tier 3), so this is the highest-leverage place to spend a second model.

That's the basics: one model plans while a cheaper one builds, and agents draft and critique the spec against each other before code. Per-subagent models, an advisor, cross-lab code review, and open-weight/self-hosted routing come later in the full playbook.

Knowledge Encoding — engineering what's always available

This is the triad's context slot, scaled — from pasting context into a prompt to engineering it: @files, tools, MCP, durable memory.

2.9 Keep secrets out of git and out of context — set this up first.

Instead of: real keys in the repo, or pasted into a prompt.

Prefer: .env gitignored and referenced by variable, enforced with a hook.

A coding agent reads your whole tree and everything you paste; both leak.

How:

  • Gitignore secrets before anything else. Real values in .env; add .env (plus .env.local, *.pem, *.key) to .gitignore — so neither git, a PR, nor the agent's own commits ever carry them. Commit a .env.example with blank keys as the shape to follow.
  • Never paste a key into a prompt — it lands in the transcript, the logs, and the context window. Reference it by variable (process.env.STRIPE_KEY); the app reads it at runtime.
  • Enforce it, don't just trust it: a PreToolUse guard hook that blocks any read or write of .env — the layer the model can't talk its way past.
  • Privacy boundary: code routed to a third-party model or gateway leaves Anthropic's trust boundary into that provider's data handling — keep sensitive code on Anthropic or your own infra (Level 2).

2.10 CLAUDE.md = gotchas + conventions, not an encyclopedia.

Instead of: a 500-line style manual.

Prefer: architecture, key commands, forbidden patterns, and the mistakes it keeps repeating — pruned often.

How: keep it short; subdirectory CLAUDE.md files for local rules; point to docs rather than pasting them:

For the payment flow, see docs/payments.md.
NOTE: src/legacy/* is deprecated — use src/v2/* equivalents.

2.11 Put occasional knowledge in Skills — loaded only when the task matches.

Instead of: cramming the migration protocol into CLAUDE.md.

Prefer: a Skill that auto-loads only when the task matches its description.

How: .claude/skills/db-migration/SKILL.md — a folder, so it can carry scripts too:

---
name: db-migration
description: Use when creating or altering database schema or writing migrations.
---
# Migration protocol
- New file in /migrations; never edit an applied one.
- Run `npm run migrate:make <name>`; then fill up/down.

A slash command is the same idea you trigger by hand. In fact commands are now skills under the hood — .claude/commands/review.md and .claude/skills/review/SKILL.md both make /review. Add disable-model-invocation: true to a skill to make it explicit-only.

2.12 Add the right MCP servers; keep the surface small.

Instead of: copy-pasting data in and out by hand, or wiring 30 thin tools.

Prefer: connect a few high-value MCP servers (browser, DB, issue tracker) and let Claude use them directly.

How: add one, scope it to the project so the team shares it:

claude mcp add playwright --scope project npx @playwright/mcp@latest
claude mcp list   # confirm "connected"

Or commit .mcp.json to the repo root:

{ "mcpServers": {
  "playwright": { "command": "npx", "args": ["-y", "@playwright/mcp@latest"] }
} }

>~20k tokens of MCP definitions already eats your working context. Few powerful gateway tools beat many thin REST mirrors.

2.13 Use external memory for multi-session work — compaction won't carry decisions across sessions.

Instead of: trusting compaction to carry decisions across sessions.

Prefer: write STATUS.md at session end; reload it at the next session's start.

Tier 5 scales this into a full hand-off protocol for multi-session builds — Tip 5.5.