DEV Community

Cover image for The Price Spread Is Now 80x. Is Your Agent's Model Choice Still a Default?
Samiha Elmansouri
Samiha Elmansouri

Posted on Edited on

The Price Spread Is Now 80x. Is Your Agent's Model Choice Still a Default?

Last week the floor of the model market moved. The ceiling did not.

On 9 November, Anthropic shipped Claude Fable 5.2 at $8.00 per million input tokens. The same day, Meta shipped Muse Ember at $0.10. That is an 80× spread between two models that will both read your file, call your tool, and return JSON.

Bottom line: an 80× price spread is not a discount you take. It is a gradient you route on — and the only thing stopping most teams is a single line of config nobody has revisited.

The spread, in one table

USD per 1M input tokens — an 80× spread between Claude Fable 5.2 at $8.00 and Muse Ember at $0.10

List prices, verified 11 November 2026.

Model Input /MTok Output /MTok Cache read Long-context behaviour
Claude Fable 5.2 $8.00 $40.00 $0.20 (2.5%) 1M, flat pricing
Claude Opus 5.5 $4.00 $20.00 $0.20 (5%) 1M, flat pricing
Claude Sonnet 5.5 $2.00 $10.00 $0.10 (5%) 1M, flat pricing
Claude Haiku 5.5 $0.10 $0.50 $0.01 (10%) 5× above a 100k prompt
Meta Muse Ember $0.10 $0.50 $0.004 (4%) 3× above a 200k prompt
OpenAI GPT-6 Luna $0.10 $0.50 $0.01 (10%) 2× above a 272k prompt

Sources: Anthropic's pricing page, Meta's Model API pricing, and an independent pricing table for Luna. Prices change weekly. Re-check before you paste them into a budget.

"But the 80× is not a fair comparison"

Correct. It isn't. Fable 5.2 is built for long-horizon work; Ember is built for the busywork inside an agent: reading files, running tests, making small fixes, parsing documents. Comparing them per token is like comparing a taxi to a bus per seat.

That is exactly the point. A router exists to exploit an unfair comparison. The question is not "which model is better" — it is "which task deserves which tier", and almost nobody is answering it per task. They are answering it once, at project setup, with a const.

So what does the spread cost?

Cost of one 200-step agent session: $16.00 on Fable 5.2, $0.20 on Muse Ember

Take one agent session: 200 tool calls, ~8,000 input tokens each (1.6M in), 400 output tokens each (80k out).

Tier Cost per session Cost per 1,000 sessions
Fable 5.2 $16.00 $16,000
Opus 5.5 $8.00 $8,000
Sonnet 5.5 $4.00 $4,000
Haiku 5.5 / Ember / Luna $0.20 $200

Same work. Two orders of magnitude between the top row and the bottom row.

Now the honest part: those two rows are not doing the same job. The top row is buying a higher ceiling on what you can hand over without checking. The bottom row is buying volume. If you buy the top row for the 80% of steps that only need volume, you are paying 80× for confidence you already have.

The 80× is the least interesting number here

Three details matter more, and they are the ones that actually break budgets.

1. Caching does not close the gap

Everyone's first instinct: cache the prompt, the discount will fix it. It won't. At a 90% cache-hit rate, the effective input price is:

Model Effective input /MTok at 90% hits Discount vs list
Fable 5.2 $0.98 8.2×
Opus 5.5 $0.58 6.9×
Sonnet 5.5 $0.29 6.9×
Haiku 5.5 $0.019 5.3×
Muse Ember $0.014 7.4×

Caching is a 5–8× cut for everyone, roughly equally. It changes your invoice. It does not change your ranking.

One genuinely under-reported detail though: Anthropic made Fable 5.2 cache reads 2.5% of list price, while Opus 5.5 sits at 5%. So on a cache-heavy loop the 2× gap between them narrows to about 1.7×. The frontier model is deliberately better at being repeated than the mid tier is. Read that as a signal about who they built it for.

2. The one-token cliff

This is the trap that costs real money.

Haiku 5.5 is $0.10 per million input tokens — up to a 100,000-token prompt. Above that, the whole request reprices at $0.50 in and $2.50 out. Muse Ember is $0.10 up to 200,000 tokens, then the entire request bills at $0.30 in and $1.50 out.

Watch the arithmetic. A request with 200,000 input and 10,000 output tokens on Ember costs 2.5 cents. Add one input token and the whole request bills at the long-context rate: 7.5 cents. A 3× jump for one token.

Which means your router cannot classify on task type alone. It has to classify on task_type × prompt_size. A model that is 80× cheaper at 40k tokens is only 27× cheaper at 210k, and if you are not measuring prompt size per call, you will find out from the invoice.

3. The model is only half of the price

The same model costs different amounts depending on how you call it:

  • Batch API: −50% on input and output.
  • Fast mode: +100% (Fable 5.2 goes $8 → $16, Opus 5.5 goes $4 → $8).
  • US-only inference: +10% on everything for Claude 4.6 and later.

So "which model" is at best a 4× decision. "Which model, at which speed, in which mode, on which prompt size" is the 80× one.

Three decisions, not one

Classifier → Tier 1 → Validator → ship, with a dashed escalation path back to the next tier

A router is smaller than it sounds. Three decisions:

  1. Classify — cheap, deterministic rules. If the task is a rename, an extraction, a format, a summarisation or a lookup, it goes to Tier 1. No model needed for the classifier itself.
  2. Validate — a deterministic check: tests, a JSON schema, a type check, a lint rule, a diff-size limit.
  3. Escalate — exactly one tier on failure, and log the event.
// costs.ts — the file most agent repos are missing

type Tier = "cheap" | "standard" | "frontier";

// USD per 1M tokens, verified 11 Nov 2026. Re-check monthly.
const PRICES: Record<Tier, { in: number; out: number; maxPrompt: number; cliff: number }> = {
  cheap:    { in: 0.10, out: 0.50, maxPrompt: 200_000,   cliff: 3 }, // muse-ember-1.0
  standard: { in: 4.00, out: 20.0, maxPrompt: 1_000_000, cliff: 1 }, // claude-opus-5-5
  frontier: { in: 8.00, out: 40.0, maxPrompt: 1_000_000, cliff: 1 }, // claude-fable-5-2
};

export function costOf(tier: Tier, inTok: number, outTok: number): number {
  const p = PRICES[tier];
  // the cliff reprices the whole request, not just the excess
  const k = inTok > p.maxPrompt ? p.cliff : 1;
  return ((inTok / 1e6) * p.in + (outTok / 1e6) * p.out) * k;
}

export function classify(task: {
  kind: string;
  files: number;
  needsJudgement: boolean;
}): Tier {
  if (task.needsJudgement || task.files > 20) return "standard";
  const mechanical = ["rename", "format", "extract", "summarise", "lookup"];
  return mechanical.includes(task.kind) ? "cheap" : "standard";
}

const NEXT: Record<Tier, Tier> = {
  cheap: "standard",
  standard: "frontier",
  frontier: "frontier",
};

export async function run<T>(
  task: { kind: string; files: number; needsJudgement: boolean; tokens: number },
  attempt: (tier: Tier) => Promise<T>,
  validate: (out: T) => boolean,
  log: (e: { tier: Tier; ok: boolean; usd: number; escalated: boolean }) => void,
) {
  let tier = classify(task);
  let escalated = false;

  for (let i = 0; i < 3; i++) {
    const out = await attempt(tier);
    const ok = validate(out);
    log({
      tier,
      ok,
      usd: costOf(tier, task.tokens, Math.round(task.tokens * 0.05)),
      escalated,
    });
    if (ok) return { out, tier };
    if (tier === "frontier") break;
    tier = NEXT[tier];
    escalated = true;
  }

  throw new Error("failed at every tier: this is a task problem, not a model problem");
}
Enter fullscreen mode Exit fullscreen mode

Look at what is not in there: no LLM judge. validate has to be deterministic — tests, a schema, a type check, a lint rule. An LLM judging an LLM is how teams convince themselves an 80× saving is real when it is actually an 80× increase in unreviewed output.

The counter-argument, which is fair

Routing costs you something real:

  • two sets of prompts and two eval suites instead of one;
  • the latency of an escalation round-trip on the tasks that fail;
  • a new failure mode where the cheap tier returns something plausible and your validator is too weak to catch it.

Those are legitimate. And they point at the actual thesis:

The 80× is only real where your validator is deterministic.

Where the check is "tests pass", "the schema validates", "the types compile", a cheap tier plus escalation is genuinely 80× cheaper per unit of work. Where the check is a human reading a diff and thinking "is this right?" — that is the most expensive token in your system, and moving the generation to a cheaper model just moves the cost to the person who has to trust it.

So route on task class, not on ambition. The mechanical 80% is where the money is.

The 30-minute audit

Do this before you refactor anything:

  1. Count your model IDs.
   grep -rn "claude-\|gpt-6\|gemini-" --include=*.ts --include=*.py src/ | wc -l
Enter fullscreen mode Exit fullscreen mode

Every hit is a decision someone made once and nobody revisited.

  1. Log cost per task. One line: tier, input tokens, output tokens, USD, duration. If you cannot print cost per task, you cannot route.
  2. Measure the escalation rate. Take 100 real tasks, run them on Tier 1, validate deterministically, count the failures. That number is your architecture.
  3. Move only what passes. Escalation rate under ~20%: route it. Above that: either your classifier is wrong or your validator is weak. Neither is solved by a cheaper model.

What this post is not

I did not run a single API call for this piece. Every number here is a published list price, and the arithmetic is reproducible on the back of an envelope:

cost = (tokens_in / 1e6) × price_in + (tokens_out / 1e6) × price_out
Enter fullscreen mode Exit fullscreen mode

Vendor benchmarks — including Anthropic's own claim that Fable 5.2 at High effort lands near Opus 5.5 at Max for about half the cost per task — are vendor claims. Your repo is the only benchmark that matters.

Your turn

Here is the question I actually want answered, and it is not "which model do you use":

What is your escalation rate? Not the model pinned in your config — the share of tasks that failed the cheap tier and had to move up.

If you don't know the number, that is not a gap in this post. That is the post.

Top comments (2)

Collapse
 
aiapikey profile image
于侃 •

The 80x only matters when you measure it per successful task, not per token. A cheaper model that needs three attempts where the expensive one needs one is really 27x, not 80x - still a lot, but it is the honest denominator.

The number to track is attempts per success, per model, on your real tasks: (list price x tokens) x (attempts / successes). That folds in retries, recoveries, and the validation that catches a bad answer.

And the routing upside is asymmetric: with an 80x spread you can afford the cheap model to fail on one task in twenty, escalate those to the expensive one, and still land near the cheap price. The break-even is when escalation cost eats the spread - a number you can compute before shipping anything.

Collapse
 
jes_p_d4f61f7aa2ec405a418 profile image
Dev_PJS •

For your escalation-rate question, I pre-decide three things before any run: what 'done' means, what counts as evidence, and what happens if it fails. Writing those down first removed most of my mid-run second-guessing — the run either matches the sheet or it doesn't.

Collapse
 
sara_builds profile image
Sara •

The escalation rate framing is useful. One thing that helped me was logging the reason for each escalation (schema fail, test fail, timeout), because the cheap tier often fails for one fixable reason like a bad prompt, not because it is too weak. Do you track cost per successful task or just per call?