Introduction to Claude & the Anthropic Model Family
Every lab in this course targets Claude. Before you write more code against it, get the mental model straight: who the models are, how they differ, and how to pick the right one for a task — so your choices are deliberate, not cargo-culted.
Learning objectives
- Explain what an LLM is and how Claude is trained to be helpful/harmless/honest.
- Compare the model tiers (Opus/Sonnet/Haiku) and pick one deliberately.
- Reason about context windows, tokens, and cost.
- Choose the right model per task like a lead sizing a fleet.
code/cl1-intro/ in the course, with a README on how to run it. Read here, run there — no need to copy-paste.The same model shows up in five very different places. They form a ladder: at the bottom you use Claude yourself, in the middle you integrate it into your code and tools, and at the top you build your own agents on it. Each rung adds control and responsibility. This chapter is the foundation for all five; the links take you to where each one is taught in depth.
- Chat (claude.ai, desktop and mobile apps) — you talk to Claude directly. The fastest way to learn what it's good at. Start below.
- API — your code sends messages and gets replies (
client.messages.create), with system prompts, tools, and streaming. → C2 · The Claude API - Claude Code — Claude works as an agent inside your codebase and terminal: reads files, runs commands, makes changes. → C3 · Claude Code · Claude Code in action
- MCP (Model Context Protocol) — a standard way to connect Claude to external tools and data sources. → C4 · MCP · the MCP ecosystem
- Agent SDK — the agent loop behind Claude Code, as a library, so you can build and run your own agents. → The Agent SDK · agent SDKs compared
1 · What Claude is essential
Here's a mistake almost everyone makes on day one. They open the docs, copy the first messages.create snippet, swap in their prompt, and treat the model as a magic box that "understands English." Then it does something baffling — invents a fact, refuses a perfectly reasonable request, or trails off mid-sentence — and they have no mental model to explain why. The fix isn't more prompt-tweaking; it's knowing, at a gut level, what the thing actually is. Ten minutes here saves you a week of confused debugging later.
So here's the honest one-sentence version: Claude is a very, very good autocomplete. Think of the predictive text on your phone that suggests the next word — now imagine that same trick scaled up on a supercomputer, trained on a huge slice of the written world, until "predict the next word" starts producing working code, coherent essays, and step-by-step reasoning. That's not a metaphor that breaks down later; it's literally the machinery. Everything Claude does is choosing the next token (roughly, the next chunk of text) given everything it has seen so far, one token at a time, left to right.
But raw autocomplete would be useless — and often dangerous. A model that only predicts "what text usually comes next" will happily continue a racist joke, or make up a citation because made-up citations look like real ones. So Anthropic does a second stage of training called alignment that reshapes which continuations the model prefers, steering it toward answers that are helpful, harmless, and honest (Anthropic's stated goal for Claude). The everyday analogy: the base model is a brilliant new hire who has read everything but has no judgment; alignment is the onboarding that teaches them what's actually appropriate to say at work.
The common mistake to name and avoid: believing Claude "knows" things the way a database knows things. It doesn't look up facts — it predicts plausible text, and plausible is not the same as true. That single insight explains hallucinations (confident wrong answers), why grounding it in retrieved documents (RAG, Ch 3) matters so much, and why you verify anything load-bearing. Keep the autocomplete picture in your head and Claude stops being mysterious.
Now the precise version, which will land because you have the intuition. Claude is a family of large language models from Anthropic: trained on vast text to predict the next token, then aligned to be helpful, harmless, and honest. You interact with it as a conversation — a list of user/assistant messages — and it responds. Everything in this course is built on that simple loop.
Read the three boxes left to right — they are the pipeline that produces the Claude you call.
- The blue "vast text" box is the training data — a huge slice of the written world the model learns from.
- The middle "base model" box is the raw autocomplete: pre-training teaches it only to predict the next token, one at a time, left to right. Brilliant, but with no sense of what is appropriate to say.
- The green "aligned Claude" box is the payoff: a second stage (RLHF and Constitutional AI) reshapes which continuations it prefers, steering it toward helpful, harmless, and honest answers.
- The arrows show the one-way flow — each stage feeds the next; the bottom line is the warning that survives all of it: it predicts plausible text, so plausible is not the same as true (hallucinations).
In short: base model = predict the next token; alignment = prefer the good continuations; and it never looks facts up, which is why grounding it in real documents matters.
2 · The model family essential
Picture the tool wall in a decent workshop. There's a cordless screwdriver you grab a hundred times a day, a heavy drill for the jobs the screwdriver can't manage, and a tiny precision driver for fiddly, repetitive work. A good tradesperson doesn't reach for the biggest drill every single time "to be safe" — that's slow, clumsy, and wears the battery down for no reason. They match the tool to the task. Anthropic ships Claude the same way: not one model, but a family of tiers, and your job is to grab the right one.
The three names to know are Opus, Sonnet, and Haiku — and there's a lovely mnemonic buried in them. A haiku is the shortest poem, a sonnet is medium-length, and an opus is a grand full-length work; the model names track exactly that size and depth ordering. Haiku is the fastest and cheapest (the precision driver), Opus is the most capable and most expensive (the heavy drill), and Sonnet sits in the middle as the balanced workhorse (the everyday screwdriver you'll reach for most). Within each family there's also a version — this course uses claude-opus-4-8, claude-sonnet-4-5, and claude-haiku-4-5 — so the full ID pins down both which tier and which generation you're calling.
Why does having tiers matter, rather than one model that does everything? Because the three axes you care about — capability, speed, and cost — genuinely trade against each other. A bigger model reasons over more steps and makes fewer mistakes on hard problems, but every token it produces costs more and arrives a little slower. There is no single model that is simultaneously the smartest, the fastest, and the cheapest, any more than there's one vehicle that's the roomiest, the quickest, and the most fuel-efficient. The tiers exist precisely so you can pick your point on that triangle per task.
The common mistake — and it's the expensive one this whole chapter is built to cure — is defaulting to Opus for everything because it's "the best." At the volume of a real production system that habit can multiply your bill by 10–20x for tasks a smaller model handles identically. The professional instinct is the opposite: pick by the task, not by habit, start from the middle, and justify every move up or down. The table below is your starting map; the rest of the chapter turns it into a repeatable decision.
Claude comes in tiers trading capability for speed/cost. Pick by the task, not by habit.
Read the boxes left to right along the single grey scale at the bottom: left is cheaper and faster, right is more capable and pricier.
- The three boxes are the tiers — green Haiku, blue Sonnet, purple Opus — each tick-marked to its position on the scale.
- Their rising height and rightward position encode the trade-off: taller/further-right means more capability, but also more cost and a little more latency. There is no box that is simultaneously left-most and tallest.
- The middle box, Sonnet, is the payoff: it is the balanced default you reach for first, moving off it only with a reason (up to Opus for hard work, down to Haiku for cheap volume).
In short: you pick a point on this line per task — you never get capability, speed, and cost all maxed at once.
| Tier | Strength | Use for |
|---|---|---|
| Opus | most capable, deepest reasoning | hard reasoning, agents, complex code |
| Sonnet | balanced — smart + fast | most production work, RAG, tools |
| Haiku | fastest, cheapest | high-volume, simple classification, routing |
3 · Tokens & the context window essential
A story that has surprised more than one engineer at the end of the month. You build a slick feature that pastes a whole PDF into the prompt "for context," ship it, and it works beautifully in the demo. Then the invoice lands and it's ten times what you budgeted — because you were paying for that entire PDF, in full, on every single request. Nothing was broken. You just never learned the two ideas in this section, and they are the ideas that quietly control both what the model can see and what it costs you.
Start with the token. The model doesn't read letters or whole words — it reads tokens, which are chunks of text roughly ¾ of a word long (common words are one token; longer or rarer words split into several). The mental picture: text is chopped into LEGO bricks before the model ever sees it, and it thinks, bills, and remembers in bricks, not in words. A handy rule of thumb is that 1,000 tokens is about 750 English words — a couple of paragraphs.
Now the context window: the maximum number of tokens the model can hold in its head at once — and, crucially, that budget covers both your prompt and its reply. The analogy that makes it click is a whiteboard of fixed size. Everything for this turn has to fit on the board: the system instructions, the conversation history, the documents you pasted, and the space left over for the answer. When the board is full, something has to be erased — which is why long agent conversations eventually need trimming or summarizing (you'll use a deque(maxlen=N) for exactly this in Ch 4). The window is not memory that persists between calls; it's a fresh whiteboard you re-fill on every request.
Here's why the two ideas fuse into one that matters: you are billed per token, so tokens are literally money, and input and output are usually priced differently (output tokens tend to cost several times more than input). That reframes prompt design as budgeting. The common mistake is treating context as free and stuffing it with "just in case" material — every extra token in that PDF is a tax you pay on every call, forever. The professional habit is the opposite: estimate before you build. The tiny lab below does exactly that, turning a fuzzy "is this affordable?" into arithmetic you can put in a design doc.
Read the four inner boxes left to right — together they must fit inside the one outer frame, which is the whole context window.
- The outer frame is the fixed budget: the model's context window. Everything for a single request lives inside it and nothing spills over.
- The inner blocks are what fills it — the blue system and history blocks, the amber pasted docs (deliberately amber: this is the part that quietly balloons your bill), and the green reply room that must be left over for the answer.
- The payoff is the green block: when the other three grow, the room left for the reply shrinks — which is why long chats eventually need trimming or summarizing.
In short: prompt and reply share one fixed board, so every "just in case" token is both a cost on every call and space taken from the answer.
tokens.pydef estimate(words, out_words, in_per_mtok, out_per_mtok):
# rough: 1 token ~= 0.75 words -> words / 0.75 tokens
in_tok = words / 0.75
out_tok = out_words / 0.75
cost = in_tok/1e6*in_per_mtok + out_tok/1e6*out_per_mtok
return round(in_tok), round(out_tok), round(cost, 4)
# a 2000-word RAG prompt, 300-word answer (illustrative prices)
print("Sonnet:", estimate(2000, 300, in_per_mtok=3, out_per_mtok=15))
print("Haiku: ", estimate(2000, 300, in_per_mtok=1, out_per_mtok=5))
Sonnet: (2667, 400, 0.014)
Haiku: (2667, 400, 0.0047)
This tiny program answers "about how many tokens will my request use, and what will it cost?" A token is a chunk of text (~¾ of a word), and you pay per token — so counting tokens is really counting money. The function does the arithmetic; the two print lines run it for two different models.
- The function takes four inputs: how many
wordsyou send in, how manyout_wordsyou expect back, and the two per-million-token prices (in_per_mtokfor input,out_per_mtokfor output). - It converts words to tokens by dividing by
0.75(since 1 token ≈ 0.75 words, a word is a bit more than one token). So 2000 words ≈ 2667 tokens. - The
costline multiplies each token count by its price. Prices are quoted per million tokens, so it divides by1e6(one million) first, then adds the input and output costs together. - It
returns three numbers — rounded input tokens, output tokens, and dollar cost — which theprintlines show for a Sonnet-priced and a Haiku-priced call.
What the output means: Each line is (input_tokens, output_tokens, cost). The same request costs $0.014 on Sonnet but only $0.0047 on Haiku — Haiku is roughly 3x cheaper here because its per-token prices are lower.
Try this: Change the answer length from 300 to 1500 words and re-run. Output tokens are billed at the higher rate, so long answers cost more — that's why trimming responses saves real money at scale.
4 · Intermediate — how the models differ in practice intermediate
Imagine two chess players. One is a strong club player; the other is a grandmaster. Set them a simple three-move puzzle and they both solve it instantly — you genuinely cannot tell them apart. Now set them a subtle, twenty-move endgame where one wrong step loses, and the gap becomes enormous: the grandmaster sees the whole line, the club player goes astray somewhere in the middle. That is exactly the relationship between a small Claude and a large one, and internalizing it is what separates people who choose models well from people who guess.
Where does the difference actually come from? A bigger model has more capacity to reason over many steps without losing the thread, to follow complicated multi-part instructions reliably, and to stay grounded instead of hallucinating when a problem is genuinely hard. The intuition: on a hard task there are many places to take a wrong turn, and the larger model's extra "headroom" is what keeps it on the path. The flip side of that headroom is the bill and the clock — more capability means more cost per token and a little more latency.
The point that turns this into a design principle is the shape of the gap. It is not a constant. On easy work — classify this sentiment, extract this field, is this spam — a small, cheap model is often indistinguishable from the giant, just as both chess players ace the trivial puzzle. The capability gap only opens up as the task gets hard. So paying for the big model on easy tasks buys you nothing you can measure while charging you a premium on every call.
The common mistake here is assuming quality scales smoothly with price — that a 10x pricier model is "10x better" everywhere, so you should buy as much as you can afford. It doesn't work like that. On the easy majority the curve is flat; on the hard tail it's steep. The right question is never "which model is best?" but "where does this task sit on the difficulty curve, and is that where the models actually diverge?" That reframing is what the model selector in the next section makes concrete.
Scan left to right: the horizontal axis is task difficulty, the vertical axis is answer quality, and the two curves are a small model and a large model.
- The solid blue curve is the large model, the dashed curve the small one. On the left of the dotted divider (easy tasks) they sit almost on top of each other — same quality, so paying more buys nothing measurable.
- Right of the divider (hard tasks) the small model's curve falls away while the large model holds up — that widening space between them is the labelled "the gap".
- The payoff is that arrow-marked gap: it is the only region where the expensive model earns its price, which is exactly where you should spend it.
In short: capability doesn't scale smoothly with price — it's flat on easy work and steep on the hard tail, so match the model to where the task sits.
5 · Advanced — pick the right model per task advanced
Think about how a good triage nurse works. A patient walks in and the nurse doesn't agonize or ask the whole team — they run a fast, consistent checklist (how urgent, how complex, how busy are we) and route the person to the right level of care in seconds. The magic isn't genius per case; it's that the rule is written down, so every patient gets a defensible, repeatable decision. Choosing a Claude model deserves the same treatment — and if you leave it to individual taste, you get the opposite: everyone quietly picks Opus "to be safe" and the bill balloons.
So instead of deciding by vibes, we encode the decision as a function. The three inputs are the ones that actually move the answer: task hardness (how much reasoning does this genuinely need?), volume (how many times a day will this run?), and latency sensitivity (does a human sit waiting for the reply?). Feed those in, get a model out. The value isn't that the function is clever — it's that it's consistent: the same task always gets the same, explainable answer, and you can review the rule instead of arguing case by case.
There's one subtlety worth flagging before you read the code, because it's the thing interviewers probe and the thing that bites in practice: the rules are checked top to bottom, and it returns at the first match. That short-circuit means rule order is a design decision, not a formatting detail. A medium-hardness task can be caught by an earlier rule before the latency check is ever reached — so "why didn't my latency flag change the answer?" is almost always an ordering question. Read the checks in the exact sequence written, and stop at the first that fires; whatever sits below simply never runs for that input.
The common mistake a selector like this guards against is optimizing one axis in isolation — picking purely for capability and ignoring that the task runs a million times a day, or picking purely for cost on the one workload where a wrong answer is catastrophic. A deliberate choice weighs capability need vs volume vs latency budget together. Model the decision.
Read the left column top to bottom — that's the exact order the function tests its rules, and it stops the instant one is true.
- Each left box is a condition; a solid "yes" arrow crosses to the model it returns (purple Opus, white Sonnet, green Haiku) and the function exits there.
- A dashed "no → fall through" arrow drops down to the next rule — the only way control reaches a lower rule is if every rule above it was false.
- The payoff (the trap): a hardness-3 task matches rule 2 (
hardness ≥ 2) and returns Sonnet before the latency half of thatorever matters — so reordering the rules would change the answer.
In short: the chain returns at the first true condition, which is why the order you write the rules in is itself the logic.
pick_model.pydef pick_model(task_hardness, volume_per_day, latency_sensitive):
"""hardness 1-5; returns the cheapest model that meets the need."""
if task_hardness >= 4:
return "opus" # hard reasoning worth the cost
if task_hardness >= 2 or latency_sensitive is False:
return "sonnet" # the workhorse default
return "haiku" # simple + high-volume + latency-sensitive
print("complex agent: ", pick_model(5, 1000, False))
print("prod RAG: ", pick_model(3, 50000, False))
print("high-volume routing:", pick_model(1, 1_000_000, True))
complex agent: opus
prod RAG: sonnet
high-volume routing: haiku
This function makes the model choice for you: given how hard a task is, how much volume you run, and whether speed matters, it returns the cheapest model that still meets the need. It reads top-to-bottom and returns at the first matching rule, so order matters.
task_hardnessis a 1–5 difficulty score. The first check — hardness>= 4— catches the hardest tasks and returns"opus", the most capable (and priciest) tier. Once it returns, the rest is skipped.- The second rule returns
"sonnet", the balanced "workhorse" default, for medium tasks (hardness>= 2) or anything not latency-sensitive. - If neither rule fired, the task is easy and speed-sensitive, so it falls through to
"haiku"— the fastest, cheapest tier. - The three
printcalls try it on a complex agent, a production RAG endpoint, and high-volume routing, so you can see each rule pick a different model.
What the output means: A complex agent → opus, prod RAG → sonnet, high-volume routing → haiku. The rules turn a fuzzy "which model?" into a repeatable decision.
Try this: Call pick_model(3, 50000, True) — hardness 3 still returns sonnet because the >= 2 rule fires before latency is even considered. Reordering the checks would change the answer, which is why rule order is a real design choice.
6 · Professional — cost at scale professional
Here's the number that reframes everything. A choice that costs a fraction of a cent per request feels free when you're testing with fifty calls — the difference between models is rounding-error money. Now multiply by a million requests a day. Suddenly that "free" per-call difference is a line item a finance team will ask you about by name. This is the moment model choice stops being a technical preference and becomes a budget decision, and the engineers who understand that are the ones trusted to run systems at scale.
The everyday analogy is a delivery fleet. You wouldn't send a fully-loaded semi-truck to drop off a single envelope — you'd use a bike courier, and save the truck for the pallet that actually needs it. Sending every request to Opus is exactly that mistake: a semi-truck for the envelopes. A task that's fine on Haiku but run on Opus can cost 10–20x more for no quality gain — you're paying premium capability the task never uses.
The fix is tiered routing: look at each request, send the easy majority to the cheap fast model, and escalate only the genuinely hard minority to the expensive one. Because real workloads are usually mostly-easy — think 90% routine, 10% hard — the cheap model absorbs the bulk of the traffic and the pricey model only touches the slice that needs it. The savings can be dramatic, and the lab below shows precisely how dramatic, and under what conditions.
The common mistake to watch for is assuming the saving is fixed — that "routing saves ~86%" is a law of nature. It isn't; it's entirely a function of how much of your traffic is actually hard. The saving is really the price gap multiplied by the easy share, so as the hard fraction climbs, the routed bill climbs toward the all-Opus bill and the win erodes. Routing pays off most when the easy majority is large — which is exactly why measuring your traffic mix comes before choosing a routing policy, not after.
Follow the arrows left to right: all requests enter on the left, hit the router in the middle, and get split into two streams on the right.
- The blue box is the full traffic; the router inspects each request's difficulty and sends it down one of two branches.
- The green branch (easy majority) goes to cheap Haiku and carries the bulk of the volume; the purple branch (hard minority) goes to pricey Opus and touches only the slice that needs it.
- The payoff is the bottom row: the green routed bill (≈ $2,900) sits beside the red all-Opus bill (≈ $20,000) — the same work for ≈ 86% less, precisely because most requests skipped the expensive model.
In short: the saving is the price gap times the easy share — big when the easy branch is fat, shrinking as more traffic is forced down the Opus branch.
routing_cost.pydef routed_cost(total, pct_hard, haiku_cost, opus_cost):
hard = total * pct_hard
easy = total - hard
routed = easy*haiku_cost + hard*opus_cost # route easy->haiku, hard->opus
all_opus = total*opus_cost
return round(routed,2), round(all_opus,2), round(100*(all_opus-routed)/all_opus)
routed, naive, saved = routed_cost(1_000_000, 0.1, 0.001, 0.02)
print(f"tiered routing: ${routed} | all-opus: ${naive} | saved {saved}%")
tiered routing: $2900.0 | all-opus: $20000.0 | saved 86%
This shows why routing saves money at scale. Instead of sending every request to the expensive model, you send the easy majority to a cheap model (Haiku) and only the hard minority to the pricey one (Opus). The function compares that bill against sending everything to Opus.
- Inputs:
totalrequests,pct_hard(the fraction that truly need the big model), and the per-request costshaiku_costandopus_cost. - It splits the traffic:
hardis the hard slice,easyis everything else. Here 10% (0.1) of a million requests is hard, so 900k are easy. routedis the smart bill — easy requests billed at the cheap Haiku price, hard ones at the Opus price.all_opusis the naive bill: every request at Opus price.- The last returned number is the percentage saved: how much smaller the routed bill is versus all-Opus, as a whole-number percent.
What the output means: Routing costs $2900 versus $20000 to send everything to Opus — a 86% saving, for the same work, because most requests didn't need the big model.
Try this: Bump pct_hard from 0.1 to 0.5 and re-run. As more traffic genuinely needs Opus, the saving shrinks — routing pays off most when the easy majority is large.
7 · Tech-lead — a model policy for the team tech-lead
Watch what happens when there's no policy. Ten engineers each make a locally reasonable model choice. One defaults to Opus because a demo needed it; another copies that config into a high-volume endpoint without thinking; a third picks Haiku for a task that quietly needs more. Every individual decision looked fine. In aggregate you get a spend chart nobody can explain and a quality baseline nobody agreed to. The lesson every lead learns eventually: a decision made ten different ways is not a decision — it's ten accidents.
The remedy isn't heroics, it's a written model policy: one page that makes the team's defaults explicit. Think of it like a coding style guide. Its value isn't that any single rule is brilliant — it's that everyone follows the same rule, so choices become reviewable, teachable, and consistent instead of a per-engineer whim. A good policy states four things: the default tier, the rules for when to escalate up or downgrade down, the cost guardrails (declare expected tokens and volume at design time; alert on deviation), and how model choice gets reviewed — in design, like any capacity decision.
The load-bearing phrase in the whole policy is "with evidence." The point of a default (Sonnet, for this course) isn't that Sonnet is always right — it's that moving off the default requires a reason you can point at: an eval showing Sonnet failing the hard cases (escalate to Opus), or an eval showing a cheaper model is good enough for the volume (downgrade to Haiku). This is the discipline from Ch 5 applied to procurement: measurement sizes the fleet, not opinion.
The common mistake a policy exists to kill is the "to be safe" default — everyone reaching for the biggest model because no one will get blamed for over-provisioning. It feels prudent and it's quietly the most expensive habit a team can have. A lead reframes it: model choice is an architecture decision — which model, where, and how you route between them shapes the cost, latency, and quality of the whole system — so it's measured, budgeted, and revisited, not defaulted. The exercises below have you write exactly this policy for a concrete app.
Compare the two halves across the dividing line: the left is a team with no policy, the right is the same team with one.
- The left cluster of red boxes is the problem — scattered, independent model picks, each locally reasonable but adding up to a spend chart nobody can explain.
- The right side starts from one blue "default: Sonnet" box that everyone shares, with two labelled exits: up to Opus (purple) for hard work, down to Haiku (green) for cheap volume.
- The payoff is the arrows off the default: you only leave Sonnet "with evidence" (an eval), so every choice is consistent, reviewable, and budgeted rather than a per-engineer whim.
In short: replace ten private guesses with one shared default plus evidence-based escalation, and model choice becomes an architecture decision you can review.
Exercise C1.1 — Size the models for an app
Context: The chapter's habits — pick by task, estimate before you build, route at scale — only stick once you apply all three to one concrete app end to end.
Your task: For an app with three workloads (complex planning agent, medium RAG endpoint, high-volume classifier), pick a model for each with pick_model, estimate monthly cost with the token helper, and compute the savings of tiered routing versus all-Opus — then write a one-line model policy.
Requirements:
- Pick a model per workload using the selector
- Estimate each workload's monthly cost from its per-request cost and volume
- Compute tiered-routing savings against an all-Opus baseline
- Distill it into a single one-line model policy for the app
- Keep prices illustrative but the method live
💡 Hint: The one-line policy should read like the default-plus-escalation rule from the ladder, specialised to this app's three workloads.
🪜 Practice ladder beginner → industry
Six graded exercises, easy to real-world. Try each before opening its solution.
Context: Picking a Claude model is a leadership decision, not a habit: Opus, Sonnet and Haiku trade capability for speed and cost. Knowing which tier fits which job is the first thing a lead sizes.
Your task: Using the lesson's model-family table, match each tier — Opus, Sonnet, Haiku — to its strength and a typical use, and name the concrete current model ID for each family.
Requirements:
- Opus (
claude-opus-4-8): deepest reasoning — hard reasoning, agents, complex code - Sonnet (
claude-sonnet-4-5): balanced — most production work, RAG, tools; the sensible default - Haiku (
claude-haiku-4-5): fastest and cheapest — high-volume classification and routing - State the general rule: pick by task, not by habit
- Give the concrete model ID for each family
💡 Hint: Start from Sonnet as the default and justify any move up to Opus or down to Haiku — the burden of proof is on leaving the middle.
Show solution
| Tier | Strength | Use for | Current model ID |
|---|---|---|---|
| Opus | most capable, deepest reasoning | hard reasoning, agents, complex code | claude-opus-4-8 |
| Sonnet | balanced — smart + fast | most production work, RAG, tools | claude-sonnet-4-5 |
| Haiku | fastest, cheapest | high-volume, simple classification, routing | claude-haiku-4-5 |
Claude comes in tiers that trade capability for speed and cost. The lesson's guidance is to pick by the task, not by habit: reach for Opus (claude-opus-4-8) only when a task genuinely needs the deepest reasoning, use Sonnet (claude-sonnet-4-5) as the balanced default for most work, and drop to Haiku (claude-haiku-4-5) for high-volume, simple, latency-sensitive jobs.
Context: A request's cost is knowable before you send it. Estimating tokens and dollars for the same prompt on two tiers turns "which model?" into an arithmetic you can put in a budget.
Your task: Using the lesson's estimate helper, compute the input/output tokens and cost of a 2000-word prompt with a 300-word answer on both Sonnet (in $3 / out $15 per Mtok) and Haiku (in $1 / out $5 per Mtok).
Requirements:
- Convert words to tokens (roughly 1 token per 0.75 words)
- Cost = (tokens / 1e6) × per-million price, summed over input and output
- Report both tiers; Haiku lands roughly 3× cheaper for the same work
- Note that output tokens bill at the higher rate
- Prices are illustrative — swap in live published rates before real budgeting
💡 Hint: Because output bills several times higher than input, trimming the answer length moves the bill more than trimming the prompt.
Show solution
def estimate(words, out_words, in_per_mtok, out_per_mtok):
# rough: 1 token ~= 0.75 words -> words / 0.75 tokens
in_tok = words / 0.75
out_tok = out_words / 0.75
cost = in_tok/1e6*in_per_mtok + out_tok/1e6*out_per_mtok
return round(in_tok), round(out_tok), round(cost, 4)
print("Sonnet:", estimate(2000, 300, in_per_mtok=3, out_per_mtok=15))
print("Haiku: ", estimate(2000, 300, in_per_mtok=1, out_per_mtok=5))
Sonnet: (2667, 400, 0.014)
Haiku: (2667, 400, 0.0047)
Words become tokens by dividing by 0.75 (1 token ≈ 0.75 words), so 2000 words ≈ 2667 tokens. Cost multiplies each token count by its per-million price and sums input and output. The same request costs $0.014 on Sonnet but only $0.0047 on Haiku — roughly 3x cheaper here — because Haiku's per-token prices are lower. These are the lesson's illustrative prices, not a live price sheet.
Context: A model selector reads its rules top to bottom and returns at the first match, so rule order silently decides behaviour. Tracing one call by hand reveals what the ordering actually prioritises.
Your task: Using the lesson's pick_model, predict the return of pick_model(3, 50000, True), explain why latency is never considered, then state what a reordering would change.
Requirements:
- Predict the concrete return value for the given inputs
- Explain that the function returns at the first matching rule (short-circuit)
- Show that a middle-hardness case matches an earlier rule before the latency rule is ever reached
- Conclude that rule order is a deliberate design choice
- State which cases a reordering would change (e.g. latency-sensitive medium tasks)
💡 Hint: Follow the rules in the exact order written and stop at the first that fires — whatever sits below it simply never runs for that input.
Show solution
def pick_model(task_hardness, volume_per_day, latency_sensitive):
"""hardness 1-5; returns the cheapest model that meets the need."""
if task_hardness >= 4:
return "opus" # hard reasoning worth the cost
if task_hardness >= 2 or latency_sensitive is False:
return "sonnet" # the workhorse default
return "haiku" # simple + high-volume + latency-sensitive
print(pick_model(3, 50000, True)) # -> sonnet
pick_model(3, 50000, True) returns "sonnet". The function reads top-to-bottom and returns at the first matching rule. Hardness 3 fails the >= 4 Opus check, but satisfies task_hardness >= 2 in the second rule — which short-circuits before the latency_sensitive half of the or is ever evaluated. So latency is irrelevant here purely because of rule order.
If you reordered the checks — e.g. testing latency_sensitive is True before the hardness-2 rule — a latency-sensitive medium task could fall through to "haiku" instead. That's why rule order is a real design decision, not an incidental detail.
Context: Routing easy traffic to Haiku and hard traffic to Opus can cut a bill dramatically — but the saving depends entirely on how much of the traffic is actually hard.
Your task: Using the lesson's routed_cost helper, compute the routed cost, the all-Opus cost, and the percent saved for 1,000,000 requests where 10% are hard, then explain what happens as the hard fraction rises to 0.5.
Requirements:
- Split traffic: the easy majority priced at the Haiku rate, the hard minority at the Opus rate
- Compute the naive all-Opus bill for the same volume
- Report the percent saved (a large majority-easy split saves the most)
- Explain that as the hard fraction rises, routed cost climbs toward the all-Opus bill
- Conclude routing pays off most when the easy majority is large
💡 Hint: The saving is really just the price gap times the easy share — shrink the easy share and the gap has less to work on.
Show solution
def routed_cost(total, pct_hard, haiku_cost, opus_cost):
hard = total * pct_hard
easy = total - hard
routed = easy*haiku_cost + hard*opus_cost # route easy->haiku, hard->opus
all_opus = total*opus_cost
return round(routed,2), round(all_opus,2), round(100*(all_opus-routed)/all_opus)
print(routed_cost(1_000_000, 0.1, 0.001, 0.02)) # (2900.0, 20000.0, 86)
tiered routing: $2900.0 | all-opus: $20000.0 | saved 86%
With 10% hard, 900k easy requests bill at the cheap Haiku price and only 100k hard ones at the Opus price, so the routed bill is $2900 versus $20000 to send everything to Opus — an 86% saving for the same work, because most requests didn't need the big model.
Raising pct_hard to 0.5 sends half the traffic to Opus, so the routed bill climbs toward the all-Opus bill and the saving shrinks. As the knowledge check states: routing pays off most when the easy majority is large; the more traffic genuinely needs the big model, the less routing helps.
Context: A real app rarely has one workload. Sizing three at once — a planning agent, a RAG endpoint, a classifier — is the exercise that turns the selector and the cost estimator into a budget line.
Your task: For a complex planning agent, a medium RAG endpoint, and a high-volume classifier, pick a model for each with pick_model and compute per-request cost with estimate, then report the choices.
Requirements:
- Planning agent (high hardness) resolves to Opus
- RAG endpoint (medium hardness) resolves to Sonnet
- High-volume, latency-sensitive classifier resolves to Haiku
- Each pick follows the selector's rules exactly — don't override by taste
- Multiply per-request cost by daily volume for each workload's budget line
- Prices are illustrative; swap in live rates before committing
💡 Hint: Let the selector make the call for each workload, then let volume × per-request cost tell you which line item actually dominates the bill.
Show solution
def pick_model(task_hardness, volume_per_day, latency_sensitive):
if task_hardness >= 4:
return "opus"
if task_hardness >= 2 or latency_sensitive is False:
return "sonnet"
return "haiku"
def estimate(words, out_words, in_per_mtok, out_per_mtok):
in_tok = words / 0.75
out_tok = out_words / 0.75
cost = in_tok/1e6*in_per_mtok + out_tok/1e6*out_per_mtok
return round(in_tok), round(out_tok), round(cost, 6)
PRICES = {"opus": (15, 75), "sonnet": (3, 15), "haiku": (1, 5)} # illustrative per-Mtok
workloads = [
("planning agent", 5, 1_000, False, 3000, 800),
("RAG endpoint", 3, 50_000, False, 2000, 300),
("classifier", 1, 1_000_000, True, 200, 10),
]
for name, hard, vol, lat, win, wout in workloads:
m = pick_model(hard, vol, lat)
tok_in, tok_out, cost = estimate(win, wout, *PRICES[m])
print(f"{name:16} -> {m:6} ~${cost}/req x {vol}/day")
The choices follow the lesson's selector exactly: the planning agent (hardness 5) → opus, the RAG endpoint (hardness 3) → sonnet, the high-volume classifier (hardness 1, latency-sensitive) → haiku. Multiplying per-request cost by daily volume turns each choice into a budget line, which is the point of sizing deliberately. Sonnet/Haiku prices ($3/$15 and $1/$5 per Mtok) are the lesson's illustrative figures; the Opus figure here is illustrative too — swap in current published prices before real budgeting.
Context: Model choice at a company is architecture, not per-engineer whim. A one-page policy makes the default, the escalation rules and the cost guardrails explicit and reviewable.
Your task: As a tech lead, write a one-page model policy for the team: default tier, escalation and downgrade rules, cost guardrails, and how model choice is reviewed — grounded in the lesson's guidance.
Requirements:
- Default to
claude-sonnet-4-5for production, RAG and tool use - Escalate to Opus only on evidence (evals show Sonnet failing hard cases)
- Downgrade to Haiku only on evidence (evals show it good enough for volume)
- Route by difficulty at scale — the tier gap is 10–20× for no quality gain on easy work
- Declare tokens/volume/estimated cost at design time and alert on deviation
- Treat model choice as a reviewed, budgeted architecture decision
💡 Hint: "With evidence" is the whole policy — every move off the default should point at an eval result, not an opinion.
Show solution
Team Model Policy
- Default tier:
claude-sonnet-4-5(Sonnet) for all new work — the balanced workhorse for production, RAG, and tool use. - Escalate to Opus (
claude-opus-4-8) only with evidence: move to Opus when evals show Sonnet failing the hard cases — hard reasoning, complex agents, complex code. Not "to be safe." - Downgrade to Haiku (
claude-haiku-4-5) with evidence: drop to Haiku when evals show it's good enough for the volume — high-volume classification, routing, latency-sensitive simple tasks. - Route by difficulty at scale: send the easy majority to a cheap model and escalate only hard cases. A task fine on Haiku but run on Opus can cost 10–20x more for no quality gain; tiered routing can save ~86% when the easy majority is large.
- Cost guardrails: every workload declares expected tokens/volume and an estimated monthly cost (via the
estimatehelper) at design time; alert when actual spend deviates. Trim response length — output tokens bill at the higher rate. - Review: model choice is an architecture decision, reviewed in design like any capacity decision — measured, budgeted, and revisited — never a per-engineer whim. Let measurement, not vibes, size the fleet.
This operationalizes the lesson's core message: default to Sonnet, escalate or downgrade only on eval evidence, route by difficulty, and treat which-model-where as a deliberate, budgeted design choice.
✓ Checkpoint — you can move on when you can…
- Explain what Claude is and how it's aligned.
- Compare tiers and reason about tokens/context/cost.
- Pick a model per task deliberately.
- Set a team model policy and route by difficulty.
Knowledge check check yourself
The tiered-routing cost model sends ~90% easy traffic to Haiku and only the hard ~10% to Opus, saving ~86% versus all-Opus. Under what condition does that saving shrink, and why?
Show answer
The lesson advises defaulting to Sonnet and moving to Opus or Haiku only with evidence. Why should model choice be driven by evals rather than defaulting everyone to the biggest model 'to be safe'?