▶ Watch this course as a narrated video playlist (8 lessons, about 28 min)
What the Claude Code team learned about prompt caching, tool design and skills — stated as design rules you can apply, with the places where the advice is version-specific, self-serving or unmeasured called out.
Spine texts (claude.dev): Prompt caching is everything · Seeing like an agent · How we use skills · The unreasonable effectiveness of HTML
These three posts are written by Anthropic engineers about Anthropic’s own product. They are rare in publishing real design decisions — and none of them publishes a measurement. There are no hit-rate numbers, no tool-accuracy numbers, no skill-adoption numbers. So each module separates what the source says, where it is incomplete or version-specific, and arithmetic or doc facts I checked against the official prompt-caching and tool-search docs.
Modules 1, 3, 6 and 7 make you commit to an answer before the reveal. Do them before reading the explanation.
Prompt caching is prefix matching. The API hashes everything from the start of the request up to each cache_control breakpoint; if an earlier request wrote an identical prefix, you pay the read price instead of reprocessing it. The hierarchy is tools → system → messages, and a change at one level invalidates that level and everything after it. Edit a tool definition and you lose the system prompt cache and the message cache too.
| Change | Tools | System | Messages |
|---|---|---|---|
| Tool definitions modified | lost | lost | lost |
| Tool-choice parameter | kept | kept | lost |
| Images added/removed | kept | kept | lost |
| Web-search / citations toggled, fast mode | kept | lost | lost |
| Thinking or effort config (model-specific) | check the docs for your model — on some it breaks the system and message cache | ||
Source: the platform docs invalidation table. This table is more precise than anything in the claude.dev post.
The ordering rule is simply most stable first. The post also notes that order matters for output quality, not just cost — the stable instructions sit where the model has most consistently seen them.
Per the docs, a 5-minute cache write costs 1.25× base input, a 1-hour write 2×, and a cache read 0.1× on standard models (lower still on some tiers; Opus 5.5 reads at $0.20/M against a $4/M base). Refreshing within the TTL is free. A hit is therefore roughly an order of magnitude cheaper than a miss — and a miss is not just uncached, it is a fresh write at a premium.
An agent session on Opus 5.5 runs 40 turns at an average of 100K tokens of context (input $4/M, 5-min cache write $5/M, cache read $0.20/M). A well-meaning engineer puts the current timestamp into the system prompt, so the prefix changes every turn and every turn is a cache miss that rewrites the cache. Estimate the total input cost in dollars for the session (ignore output). Then commit.
“Cache rules everything around me” is true of long-running, tool-heavy agents, the post’s subject. It is not true of a stateless classifier with a 400-token prompt (below the 512–4,096-token minimums depending on model; the docs say no error is returned, both cache counters just read 0). The post also never states the TTL economics that decide when caching pays: a 5-minute default means a user who walks away for lunch pays a full rewrite on return no matter how clean your prefix is.
When something changes (the time, a file the user edited, a setting), don’t rewrite the system prompt. Append the new fact inside the next message wrapped in a <system-reminder> tag. The prefix stays byte-identical; the new information arrives at the tail, which is already uncached anyway.
# breaks the cache every turn
system = f"You are a coding agent. Now: {now}. ..."
# preserves it
system = "You are a coding agent. ..." # static
user_msg = f"<system-reminder>Now: {now}</system-reminder>\n{text}"
The docs state the same principle as a failure mode: putting cache_control on a block that changes every request produces a miss every request. The breakpoint belongs on the last static block.
Adding or removing a tool mid-session invalidates the whole cache. Claude Code’s answer to “plan mode shouldn’t have write tools” is not to remove them; it is to keep every tool present and add EnterPlanMode / ExitPlanMode tools the model itself calls. Mode becomes conversation state, not configuration. A side effect the post notes: the model can enter plan mode on its own when a task is hard.
For large tool sets, the tool-search feature sends lightweight stubs with defer_loading: true; full schemas enter the context only when the model searches for them. Two facts from the docs that the post leaves out:
defer_loading controls what enters the context window, not what you transmit. The API keeps deferred tools out of the cached system prefix and expands a tool_reference inline in the conversation, so the prefix is untouched.defer_loading: true cannot also carry cache_control (HTTP 400). Put your breakpoints on the non-deferred tools; the docs recommend keeping the 3–5 hottest tools non-deferred.A typical five-server MCP setup consumes ~55K tokens of definitions before work starts; tool search cuts that by >85%. Tool selection accuracy degrades past roughly 30–50 tools. At 55K tokens on a 200K window that is more than a quarter of the context gone — plus a larger prefix to re-write on every miss.
“Never change tools mid-session” is a heuristic, not a law. It holds when the cache is warm and the context is large. At a 5K-token context, a tool swap costs 5K × $5/M = $0.025 — below the cost of a model call, and cheaper than the confusion of a model that sees write tools it must not use. The rule’s real content is price the break against context size. The post’s “static tools + state-as-tools” design also has a cost it doesn’t discuss: the model sees tools it isn’t currently allowed to use, so you need server-side enforcement (a plan-mode write attempt must still be refused), not just a prompt that says “don’t.”
Costs in the explanations come from public prices and the docs’ multipliers; the incidents are illustrative composites, not Anthropic data.
Naively, you summarize with a different system prompt and no tools. The request prefix no longer matches the conversation’s, so you pay a cold write for the entire history to produce a few thousand tokens of summary. The post’s fix: send the parent’s exact system prompt, user context and tool definitions, replay the parent’s messages, and append the compaction request as a new final user message. The prefix matches the parent’s last request; only the instruction tokens are fresh. You must reserve a compaction buffer so the summary fits in the window.
The post says rebuilding a cache for a lighter model “can exceed” the cost of just running the heavier one. Using the 5.5 prices: at 100K context, Opus 5.5 reads at $0.20/M = $0.02/turn. Switching to Sonnet 5.5 means writing 100K at $2.50/M = $0.25 once, then reading at $0.02/turn — the input side is a wash after the first turn. The savings are on output: $10/M cheaper. At 2K output tokens per turn that is $0.02/turn, so break-even is ~12 turns; at 500 tokens/turn it is ~50 turns.
Using the numbers above: you are on Opus 5.5 at 100K context and consider switching to Sonnet 5.5 (one-time 100K write at $2.50/M). The switch saves $10/M on output, and your agent emits 1,000 output tokens per turn. After how many turns does the switch break even? Commit a number.
The team alerts on cache hit rate and declares service incidents when it drops. This is the most transferable practice in the post. Compute why: a miss costs 12.5× a hit (write 1.25× vs read 0.1×; ~25× at Opus 5.5’s $0.20/M read), so misses dominate the bill even when they are rare. Per 100 turns at relative cost: 96 hits × 1 + 4 misses × 12.5 ≈ 146, versus 90 × 1 + 10 × 12.5 = 215 — 96% vs 90% hit rate is a ~1.5× difference in input spend (using the 1.25/0.1 multipliers; larger if your misses are 1-hour writes at 2×).
No hit-rate target, no baseline, no incident rate. “Treat it like uptime” is a culture claim; copy it by choosing a measurable SLO (e.g., per-session read share = cache_read / (cache_read + cache_creation + input) from the usage fields) and alerting on change, since the right level depends on session length and TTL. And remember the 5-minute TTL: idle gaps depress hit rate in ways no prompt design can fix — which is where the 1-hour TTL (2× write) can pay for interactive products.
The post’s analogy: given a hard maths problem, would you want paper, a calculator or a computer? The right tool depends on the solver’s skills. Its method is empirical — read the model’s outputs, run experiments, adapt.
questions parameter to an existing tool. The model got confused by conflicting information: the tool’s main job and the question payload competed.Generalization: give a distinct capability its own tool with a typed schema, instead of overloading an existing tool or hoping for a text convention.
Todo lists plus a reminder every five turns kept earlier models on track. A stronger model (the post cites Opus 4.5) found a rigid list limiting — sticking to the list instead of adapting — and couldn’t coordinate subagents through it. The team replaced it with a Task tool with dependencies and cross-agent updates. Moral in the post’s words: tools your model once needed can constrain it later.
Early Claude Code used RAG with a pre-built index. Giving the model Grep and letting it search itself worked better, and Agent Skills extended this: files that reference other files, discovered recursively — progressive disclosure. The model finds context by exploring rather than being fed it.
Users asked Claude Code how Claude Code works. Rather than add a tool or bloat the system prompt, the team added a Guide subagent that searches the docs in its own context and returns an answer, keeping the main context clean.
It is a set of war stories, not an experiment. “Claude couldn’t reliably produce the format” and “found the todo list limiting” come with no failure rates or ablations, and the model they describe (4.5-era) is not the one you are running. The durable principle is method, not conclusion: every scaffold is a hypothesis about the current model’s weakness; re-test it by ablation when the model changes. If a harness reminder, a todo list or a “think step by step” instruction can be deleted without an eval regression, delete it.
“Grep beat RAG” is context-bound. It was demonstrated on code, where exact identifiers make lexical search strong and an index goes stale on every edit. For a fuzzy-semantic corpus (policy documents, support history) an index can still win; and note the post’s own Guide-subagent solution is retrieval, just moved out of the main context.
“~20 tools” is a snapshot. The tool-search docs put the degradation point at 30–50 always-loaded tools; deferred loading changes the arithmetic. Count context-resident tools, not registered tools.
The post’s first correction: skills are not just markdown files, they are folders — instructions, scripts, templates, reference files — that the agent discovers and reads as needed. The folder is the unit of progressive disclosure.
| # | Category | Example |
|---|---|---|
| 1 | Library & API reference | billing-lib gotchas, internal CLI usage |
| 2 | Product verification | Playwright / tmux scripts, video recording, programmatic assertions |
| 3 | Data fetching & analysis | funnel and cohort queries with credential handling |
| 4 | Business process & team automation | standup aggregation, ticket creation |
| 5 | Scaffolding & templates | framework boilerplate |
| 6 | Code quality & review | org style enforcement, adversarial review |
| 7 | CI/CD & deployment | PR babysitting, gradual rollout |
| 8 | Runbooks | symptom → multi-tool investigation |
| 9 | Infrastructure operations | cleanup with guardrails |
rm -rf and force-push only while the production skill is active.Nine categories describe what Anthropic built, not a complete taxonomy — it is a retrospective clustering with no counts. “Organic adoption over centralized curation” is also convenient at Anthropic’s scale and talent density; at a company with 200 mostly non-expert engineers it risks hundreds of untested, overlapping skills — and the “measure with logging hooks” step is the only quality control they mention. The post reports invocation counts as the metric; invocation is not value. A skill that fires often and misleads is worse than one that never fires. Pair logging with outcome checks (did the verification skill’s runs catch real bugs?).
“Skills measurably improved quality” for verification is asserted without numbers. Also note the tension in the post’s advice: “don’t railroad” versus “ship scripts and libraries” — the reconciliation is that scripts fix mechanics (deterministic, testable) while prose should state goals.
In “The unreasonable effectiveness of HTML” (20 May 2026), Thariq Shihipar of the Claude Code team says he has “stopped using Markdown altogether for almost everything.” His reasons: HTML carries more information (tables, CSS, SVG, interaction), is easier to read than a 100-line Markdown file he admits he will not read, is shareable by link, supports two-way controls (sliders and toggles with a “copy as prompt” button that feeds your choices back to Claude), and Claude Code can fill it from the filesystem, git and MCP sources. His deeper reason is the honest one: HTML makes him “feel more in the loop.”
| Claim | Type | My read |
|---|---|---|
| Markdown cannot show a spatial layout, a diff with margin notes or a live slider | Mechanism | True. Where the content is genuinely visual or parametric, ASCII workarounds lose. |
| “Copy as prompt” export closes the loop | Mechanism | The best idea in the post. A UI that turns a human choice into a precise instruction removes transcription error. |
| People read HTML specs more than Markdown ones | Anecdote | Plausible, unmeasured. No readership data, one author’s habits. |
| Token overhead is “unnoticeable” with a 1M context | Category error | Context capacity is not cost or latency. HTML is output the model must generate, and output is the expensive side of the bill. |
| Easier to share | True, with a caveat | A file with scripts is code your reader executes. |
The post optimises for one reader, a human making a decision, and generalises to all outputs. A second reader exists: the agent in the next session. Instructions, memory files, specs the agent will re-read and anything a team reviews as a diff are consumed repeatedly. HTML in those places costs tokens on every read, bloats the stable prefix you worked to protect in module 1, and produces diffs full of markup. Markdown wins there for the same reason a config file is not a web page.
“Feeling in the loop” is not the same as being in the loop. A polished page signals rigour. Reviewers trust well-formatted output more than plain text with the same content, so a handsome AI-generated review can lower scrutiny exactly when you wanted more. The test is whether the format forces a decision (a slider you set, a finding you accept or reject), not whether it is pleasant to scroll.
It is also version-specific and self-interested. The post cites a million-token Opus 4.7 context and the writer works inside Claude Code with unlimited-feeling budgets. A team paying per token should measure the same content in both formats before adopting a house rule, and should treat HTML with scripts from outside the team as code review, not reading.
cache_read / total input) from usage fields to your dashboard; alert on change.The first three claude.dev posts were read in full on 1 Oct 2026; the HTML-vs-Markdown post (module 8) on 3 Oct 2026. Pricing multipliers, minimum lengths, the invalidation table and the tool-search constraints are from the Anthropic platform docs; the arithmetic is mine and reproducible from those numbers and from the Opus/Sonnet 5.5 prices used in the companion “Choosing & Tuning Claude 5.5 Models” course. Simulator incidents are illustrative composites. Re-check docs before relying on any figure.