●FABLE 5 — Claude Fable 5 is available again to users worldwide from July 1 after US export controls were lifted●SCIENCE — Claude Science, a workbench for researchers, is in beta; the AI for Science credit program is open through July 15●CODE — Claude Code adds dynamic workflows (research preview) and raises weekly usage limits by 50% through July 13●MODEL — Claude Sonnet 5 is the default across all plans at $2/$10 per million tokens through August 31●GATEWAY — A self-hosted Claude apps gateway arrives for Amazon Bedrock and Google Cloud (SSO, policy, cost control)●SECURITY — A new cybersecurity classifier ships alongside the Fable 5 redeployment●FABLE 5 — Claude Fable 5 is available again to users worldwide from July 1 after US export controls were lifted●SCIENCE — Claude Science, a workbench for researchers, is in beta; the AI for Science credit program is open through July 15●CODE — Claude Code adds dynamic workflows (research preview) and raises weekly usage limits by 50% through July 13●MODEL — Claude Sonnet 5 is the default across all plans at $2/$10 per million tokens through August 31●GATEWAY — A self-hosted Claude apps gateway arrives for Amazon Bedrock and Google Cloud (SSO, policy, cost control)●SECURITY — A new cybersecurity classifier ships alongside the Fable 5 redeployment
Fable 5 Is Back Worldwide and Sonnet 5 Is the Default — Where Each of the Three Models Belongs in a Solo Automation Stack
With Fable 5 redeployed worldwide and Sonnet 5 now the default, solo automation suddenly has three capable top-tier models to reach for. Instead of ranking them, this piece assigns each a role and captures that in a policy object with a fallback ladder and run-level logging.
On the morning of June 30th I opened the logs for a scheduled job that should have been identical to the night before, and paused. The output had shifted, just slightly. The cause was quick to find: Claude Sonnet 5 had become the default across all plans, and any job that hadn't pinned a model had quietly moved to the new default overnight.
A few days earlier, on July 1st, Fable 5 had returned to worldwide availability after export restrictions were lifted. That left me with three top-tier models reachable from my own automation at once: Sonnet 5, Fable 5, and Opus 4.8. More options is a good problem to have, but the moment you start choosing among them by asking "which one is smartest," you usually hit a wall. As an indie developer running unattended article generation and monitoring across several sites, I spent those days rethinking not "which one do I use" but "where do I put each one." Here is that placement, and how I pushed it down into code.
Why not leave it to the default model
What that opening moment really exposes is the fragility of running without a pinned model. The default changes for reasons on the platform's side. The June 30th switch was a benign, announced change — and even so, "the character of the output differs between yesterday and today" is not a small tremor for anyone running things unattended.
Leaving it to the default means tying your automation's behavior to someone else's decision. Cost, latency, output granularity — all of them ride along when the default moves. So the first principle is simple: in production automation, always pin the model explicitly. Then decide, with intent and per task, which model to pin. That is where the real work begins.
See the three models by role, not by rank
Line the three up and try to rank them, and you end up comparing benchmark numbers while losing the connection to your own tasks. Instead, I keep a one-line sense of where each one earns its place.
Model
Where it earns its place
Model string
Sonnet 5
The everyday workhorse for planning, tool use, and autonomous execution. Cheap enough at the introductory price to run constantly
claude-sonnet-5
Fable 5
Single-pass generation of long deliverables and large-context passes, leaning on always-on adaptive thinking and 128k-token output
claude-fable-5
Opus 4.8
Central judgment calls that need multi-step reasoning and consistency across long-running work
claude-opus-4-8
These three rows are a division of labor, not a ranking. Sonnet 5, as the most agentic Sonnet yet, sits as the default for everyday work that calls tools and advances through steps. I reach for Fable 5 only where 128k output and always-on thinking pay off — drafting a full article in one pass, sweeping a large log in a single go. Opus 4.8 I reserve for the central calls where a mistake throws off everything downstream, choosing spots that justify the cost. My hands-on notes from running two of them side by side are in three days with Fable 5 and Opus 4.8 side by side, but the takeaway was the same: it's about role, not who wins.
✦
Thank you for reading this far.
Continue Reading
What follows includes implementation code, benchmarks, and practical content we hope you'll find useful. This site runs without ads — server and development costs are supported entirely by members like you. If it's been helpful, we'd be truly grateful for your support.
WHAT YOU'LL LEARN
✦A way to sort tasks by role rather than rank, mapping Fable 5 / Sonnet 5 / Opus 4.8 to layers by what each does best (128k single-pass output, the everyday agentic workhorse, long-run reasoning consistency)
✦A Python policy object that looks up the model by task class instead of hardcoding model strings, with a per-class fallback ladder for when a model is unavailable
✦A logging step that records the resolved model per run, so you can verify what ran on which model even on a day the platform default changes
Secure payment via Stripe · Cancel anytime
✦
Unlock This Article
Get full access to the rest of this article. Buy once, read anytime. This site is ad-free — your support goes directly toward keeping it running.
Assign by task class — the mapping in my automation stack
Now translate the language of roles into your own tasks. I group my automation work at the grain of a "task class" and decide the model per class. Deciding per individual job always drifts; folding jobs into classes is the point.
Task class
Examples
Assignment
Why
Classify / extract
Diff summaries, tagging, short judgments
Sonnet 5
Short and fast. A top-tier model is overkill here
Long-form single pass
Drafting a whole article, long reports
Fable 5
128k output avoids splice-and-stitch
Agentic work
Cross-tool research, multi-step execution
Sonnet 5
Strong at tool use and autonomy by default
Central decisions
Final publish/no-publish, consistency checks
Opus 4.8
Needs long-run consistency and multi-step reasoning
The important thing is that this table is specific to my stack. In your environment classification might be the lead act, in which case Opus 4.8 barely appears. Don't copy the table itself — fold your own tasks into classes and attach a one-line reason to each. That method is the only part worth taking home.
From hardcoded model strings to a policy object
Once the assignment is decided, the next question is where it lives in the code. The common misstep is hardcoding the model string at the call site.
# Before: model strings scattered across call sitesresp = client.messages.create( model="claude-sonnet-5", # hardcoded here max_tokens=4096, messages=[{"role": "user", "content": prompt}],)# ...and another file hardcodes a different string, until you can no# longer see the whole picture of which task uses which model
This shape forces you to grep every file when you want to revisit a model choice, and worse, the judgment — the mapping from task class to model — is written nowhere in the code. I'd recommend consolidating that judgment into a single policy object.
# After: a policy object that looks up the model by task classfrom dataclasses import dataclass# model strings are defined in exactly one placeMODELS = { "sonnet5": "claude-sonnet-5", "fable5": "claude-fable-5", "opus48": "claude-opus-4-8",}# task class -> model assignment (the table above lands right here)TASK_MODEL = { "classify": "sonnet5", # classify / extract "longform": "fable5", # long-form single pass "agentic": "sonnet5", # agentic work "decide": "opus48", # central decisions}@dataclass(frozen=True)class Plan: task_class: str model_id: strdef plan_for(task_class: str) -> Plan: if task_class not in TASK_MODEL: # unknown class falls back to the workhorse, not silently to the top model key = "sonnet5" else: key = TASK_MODEL[task_class] return Plan(task_class=task_class, model_id=MODELS[key])
The call site now just passes plan_for("longform").model_id, and revisiting a model choice means editing one table. The single line that keeps an unknown task class from silently defaulting to the top model matters more than it looks — it stops cost and behavior from spiking on unexpected input.
A fallback ladder for when a model is unavailable
Deciding the assignment doesn't guarantee the pinned model is always reachable. Rate limits, temporary unavailability, org-level model restrictions — the reasons vary. In unattended runs, dropping to a meaningful alternative is often better than throwing and stopping. But there is an order to how you climb down.
# Fallback ladder: make the allowed descent order explicit per classFALLBACK = { "classify": ["sonnet5"], # don't descend (cheap; wait and retry) "longform": ["fable5", "sonnet5"], # if 128k is out, Sonnet 5 with splitting "agentic": ["sonnet5", "opus48"], # escalate up if the workhorse is jammed "decide": ["opus48"], # don't descend (don't drop quality)}class ModelUnavailable(Exception): passdef resolve(task_class: str, is_available) -> Plan: ladder = FALLBACK.get(task_class, ["sonnet5"]) for key in ladder: if is_available(MODELS[key]): return Plan(task_class=task_class, model_id=MODELS[key]) # if the whole ladder is exhausted, fail explicitly rather than return a surprise raise ModelUnavailable(f"no model available for task_class={task_class}")
What I care about most in the ladder's design is separating the classes that may descend from the ones that must not. Cheap classification has no need to descend — wait and retry. Long-form generation drops to Sonnet 5 on the assumption of splitting when 128k isn't available. Central decisions, on the other hand, are better stopped and left for a human than quietly degraded, so I deliberately give them a single-rung ladder. Applying "just return whatever model works" to every class is the pitfall — it lets the one judgment you most need to protect degrade in silence. To avoid that pitfall, I vary the depth of the ladder per class.
Log the assignment so you can verify it later
To never again miss the "default changed, output changed" of the opening, record on every run what ran on which model. Once everything goes through the policy object, the logging is a few lines.
import json, timedef run_logged(task_class: str, call_model, is_available): plan = resolve(task_class, is_available) started = time.time() result = call_model(plan.model_id) # keep the real call swappable record = { "ts": int(started), "task_class": plan.task_class, "resolved_model": plan.model_id, # record the model actually used "elapsed_ms": int((time.time() - started) * 1000), } print(json.dumps(record, ensure_ascii=False)) return result
Keeping resolved_model lets you confirm after the fact — even on a day the default moved — that "this task ran on the model I intended." Since I started reconciling the daily log against this single line, I catch model-driven behavior changes first thing in the morning. The record also makes visible how often fallback fired, and which classes descend most — that is, where the strain is.
Three dividing lines that are easy to blur
Finally, three lines I often waver on when deciding assignments, and return to each time.
First, Fable 5's always-on thinking is overkill for cheap classification. 128k output and always-on adaptive thinking pay off on long deliverables; routed to short judgments, they add more latency and cost than the quality gain justifies. Classification sits most comfortably on Sonnet 5.
Second, Opus 4.8 earns its keep only where the cost is justified. Pushing everything to the cheap introductory-price Sonnet 5 occasionally softens a central judgment; sending everything to Opus 4.8 keeps paying for reach where it doesn't help. It works when you narrow it to the single point where a mistake throws off everything downstream.
Third, a cheap introductory price is not a reason to change an assignment. Sonnet 5's introductory price is $2 per million input and $10 per million output (standard is $3/$15); even at standard pricing that runs roughly 40% below Opus 4.8's $5/$25 on both input and output. It's genuinely cheap — but the introductory price has an expiry. Move a class's assignment on price, and you'll be rebuilding the design when the price reverts. Decide the role by capability, and handle price as a matter of estimating total volume — keeping those two apart makes life easier later.
Wrapping up, and the next step
With three top-tier models now in hand, what paid off wasn't chasing "which is strongest," but deciding once, properly, where each belongs, and folding that into a policy object. Today's step can be small.
Fold your automation's tasks into four or five classes.
Attach a one-line reason to each class and decide the model to assign.
Put that assignment table in one place in the code — the policy object.
That alone means the next time the default model moves, you won't scramble over the morning logs.
I'm still finding the best assignment myself, but "pin it, log it, and choose it with intent" — those three points have carried me through a jittery stretch. Thank you for reading. I hope it gives you a useful footing to build on.
Share
Thank You for Reading
Claude Lab is ad-free, supported entirely by members like you. We publish practical guides daily with implementation code, benchmarks, and production-ready patterns. If you've found it useful, we'd love to have you on board.