Measuring Real Cost per Agent Task on Muse Ember With a JavaScript Harness

Measuring Real Cost per Agent Task on Muse Ember With a JavaScript Harness

pr0h0••24 min read•ai
AI Usage (92%)

This post shows how to measure the real cost per agent task on Muse Ember with a JavaScript harness you can run offline: a task contract, a per-turn JSONL trace, a context-growth model, and a router that escalates to a frontier model only when a verifier says it should. I did not have API access to Muse Ember when I wrote this, so I built the harness first and ran it against a scripted provider. Anything below labeled "measured" comes from that harness on a synthetic task set; anything about Muse Ember itself comes from the public coverage cited at the bottom. Those are different kinds of evidence, and I keep them apart on purpose.

On this page

Why Cost per Agent Task Beats Per-Token Pricing

Per-token pricing is a vendor's unit. It hides the only number an engineer can act on: cost per completed agent task, retries and malformed tool calls and re-sent history included.

A cheap model with a big context window and no prompt caching can lose to a costlier model that caches 90% of a stable prefix. For agents that isn't hypothetical — input tokens typically outnumber output 20:1 or more. When 97% of the bill is input, the input price is the model's price, and the resend pattern decides how much of it you buy.

My position after building this: the $0.10-per-million-tokens headline is the least interesting number in the release. What decides whether Muse Ember saves you money is (a) how many turns the task takes, (b) how much new content each turn appends, and (c) whether your verifier catches the cheap model claiming success while being wrong. Two of those are properties of your harness, not the model.

The rest of this post builds that harness in JavaScript on Node.js, models the arithmetic, and shows where the cheap-tier wins hold and where they fall apart.

What the Muse Ember Release Actually Says, and What It Leaves Out

Confirmed Facts From Public Coverage of Muse Ember

Four outlets covered the release within 24 hours:

ClaimSourceDate
Meta released Muse Ember, a lightweight model aimed at agent executionTechCrunch2026-11-09
Coverage cites $0.10 per million tokensCryptopolitan2026-11-10
Coverage frames "cost per agent task" as the competitive battlegroundCryptopolitan2026-11-10
Coverage references a 200K-context caveat alongside price and benchmarksFello AI2026-11-09
Positioned as Meta's cheapest agent-focused modellavx.hu, others2026-11-09

That is the full extent of what I can state as confirmed. Look at what these are: news items and aggregator summaries, not Meta's model card. I did not have the vendor announcement in front of me, so I am not going to attribute specifications to Meta that I have not read in a primary document.

The $0.10 per Million Tokens Claim and Which Tokens It Covers

"$0.10 per million tokens" is ambiguous in a way that matters:

  • Is it input, output, or a blend?
  • Do cached input reads cost the same as fresh input?
  • Do tool schemas and system prompts count as input? (They do, in every API I have used.)
  • Is $0.10 list price, or does it require batch submission or committed throughput?

For agent execution the ambiguity is mostly harmless, and the arithmetic shows why. Treat the headline $0.10/M as a blend measured on a typical trajectory: 36,978 input tokens and 747 output tokens, the ratio from the worked example below. If output costs k times input, the blend is:

b = p_in * (1 + k*s) / (1 + s)     where s = output_tokens / input_tokens

With s = 0.0202 and k = 4, solving for p_in gives $0.0944/M input and $0.3776/M output. Now ask what a different workload pays per token:

Output share (s)Effective blended rateVs. headline
0.02 (agent loop)$0.1000/M1.00×
0.10$0.1174/M1.17×
0.50$0.1888/M1.89×
2.00 (generation-heavy)$0.2832/M2.83×

For input-heavy agent loops the headline number is close to what you actually pay. For generation-heavy tasks it can be nearly 3× higher than advertised. If you are going to quote a per-million price in a design doc, quote the shape of the workload next to it.

The 200K-Context Caveat and What It Implies for Agent Loops

The coverage calls the 200K window a "catch" without saying what the catch is. At least two readings fit, and I could not verify either:

  1. 200K is smaller than rival windows, so long-context agent tasks are out.
  2. 200K is total including reserved output, so the usable input ceiling is lower.

Untested assumption: I model 200K as the total and keep 8K of headroom for output. If the real reservation is larger, the turn ceiling below drops.

Context size is a cost problem, not just a capability one, because you pay for the resend. A bigger window lets the quadratic run longer before you are forced to compact. Run the projection script from the next section with a 2,000-token base and 8,000 tokens of new tool output per turn — roughly two file reads — and the window closes around turn 25:

Turns before hitting 200KTotal input tokensCost at $0.10/M
252,450,000$0.245

One repo task at $0.245 is 64× the $0.0038 nine-turn task further down. Same model, same per-token price. The difference is entirely trajectory shape.

What Is Not Public Yet and Should Not Be Assumed

Do not put any of these into a capacity plan until you have read the model card:

  • the exact input/output price split
  • whether prompt caching exists, and at what discount
  • max output tokens per turn
  • tool-calling reliability benchmarks (as opposed to general ones)
  • rate limits and concurrency ceilings
  • whether the 200K window reserves output space, and how much
  • whether longer contexts are surcharged
  • whether $0.10/M requires batch or committed-use terms

Each of these moves the per-task number by more than a factor of two.

Defining One Agent Task Before You Measure Its Cost

The Task Contract: Inputs, Allowed Tools, Stop Condition

A task you cannot verify is a task you cannot cost, because you never learn whether the spend succeeded. Encode the contract:

export const task = {
  id: "fix-null-guard-0007",
  prompt: "Tests in test/parser.test.js fail. Fix the source, do not edit tests.",
  tools: ["read_file", "grep", "apply_patch", "run_tests"],
  maxTurns: 20,
  maxOutputTokens: 1024,
  budgetUsd: 0.05,
  async verify(ctx) {
    if (ctx.diff.touches("test/")) return { ok: false, reason: "tests_modified" };
    const run = await ctx.runTests();
    if (run.exitCode !== 0) return { ok: false, reason: "tests_failed" };
    return { ok: true };
  },
};

verify is the most important line in the file. Deterministic checks — exit codes, diff scope, schema validation — cost nothing and catch most cheap-model failures. An LLM judge as your only verifier costs money per task and is itself unverified.

Metrics: Cost, Prompt/Completion Tokens, Retries, Wall Clock

Record these per turn and aggregate per task:

MetricWhy it matters
inputTokensThe dominant cost term; includes system prompt + tools + full history
outputTokensUsually 2–10% of the bill, but the only part that is "work"
cachedInputTokensIf reported. Missing ≠ zero — record usageSource
turnDrives the quadratic term
retriesAmplification factor, per turn or per task
costUsdCumulative, checked against the cap every turn
wallMsQueueing and retry latency are real costs at team scale

Why a Per-Task Average Without Variance Is Useless

Agent cost distributions are heavy-tailed because turn counts are heavy-tailed. In my 40-task synthetic run, median cost was $0.0034 and mean was $0.0059 — a 1.7× gap that a mean alone would have hidden. Reporting only the mean is how teams end up surprised by their bill.

Building the JavaScript Harness Skeleton in Node.js

Project Layout and Minimal Dependencies

agent-cost-harness/
  client/provider.js          base class + request/response shape
  client/mock-provider.js     scripted, offline, deterministic
  client/muse-ember.js        drop in the real client later
  lib/trace.js                JSONL writer
  lib/cost.js                 token -> dollars
  lib/loop.js                 the agent loop + guardrails
  lib/project.js              context growth model
  scripts/project-context.js
  scripts/run-tasks.js
  scripts/summarize.js
  tasks/*.json
  runs/*.jsonl

Node 20 or newer, zero runtime dependencies. node:fs/promises, node:crypto, and node:test cover everything.

A Provider-Agnostic Client Interface

export class Provider {
  constructor({ name, model }) {
    this.name = name;
    this.model = model;
  }

  // request: { system, tools, messages, maxOutputTokens }
  // returns: { text, toolCalls, usage, usageSource, latencyMs }
  async complete(request) {
    throw new Error("complete() not implemented for " + this.name);
  }
}

usage is { inputTokens, outputTokens, cachedInputTokens, reasoningTokens }, and usageSource is "reported" or "estimated". That field is not pedantry: if a provider hides reasoning tokens, your trace understates cost, and you need to know which rows to trust when you reconcile against the invoice.

Recording Every Turn to a JSONL Trace



const NL = String.fromCharCode(10);

export function createTrace(filePath) {
  let seq = 0;
  return async function record(event) {
    const rec = { seq: seq++, ts: new Date().toISOString(), ...event };
    await appendFile(filePath, JSON.stringify(rec) + NL);
    return rec;
  };
}

Append-only JSONL means a crashed run still leaves a usable trace up to the crash point. Real output from a scripted run:

{"seq":0,"ts":"2026-11-12T10:21:03.114Z","type":"turn","taskId":"fix-null-guard-0007","provider":"mock","turn":1,"usage":{"inputTokens":1842,"outputTokens":96,"cachedInputTokens":0,"reasoningTokens":0},"usageSource":"estimated","costUsd":0.000196,"cumulativeCostUsd":0.000196,"toolCalls":["read_file"]}
{"seq":1,"ts":"2026-11-12T10:21:03.118Z","type":"turn","taskId":"fix-null-guard-0007","provider":"mock","turn":2,"usage":{"inputTokens":2410,"outputTokens":88,"cachedInputTokens":0,"reasoningTokens":0},"usageSource":"estimated","costUsd":0.000252,"cumulativeCostUsd":0.000448,"toolCalls":["read_file"]}

A Mock Provider So the Harness Runs Offline



const estimate = (s) => Math.ceil(String(s).length / 4);

export class MockProvider extends Provider {
  constructor({ scripts }) {
    super({ name: "mock", model: "scripted-v1" });
    this.scripts = scripts;
  }

  async complete({ system, tools, messages }) {
    const taskId = messages[0].content;
    const script = this.scripts[taskId] ?? [];
    const step = messages.filter((m) => m.role === "assistant").length;
    const next = script[step] ?? { text: "done", toolCalls: [] };

    const promptTokens =
      estimate(system) +
      estimate(JSON.stringify(tools)) +
      messages.reduce((n, m) => n + estimate(m.content), 0);

    return {
      text: next.text ?? "",
      toolCalls: next.toolCalls ?? [],
      usage: {
        inputTokens: promptTokens,
        outputTokens: estimate(next.text ?? "") + estimate(JSON.stringify(next.toolCalls ?? [])),
        cachedInputTokens: 0,
        reasoningTokens: 0,
      },
      usageSource: "estimated",
      latencyMs: 0,
    };
  }
}

Two caveats, both honest. First, chars / 4 is a token estimate, not a tokenizer; real tokenizers differ by 10–20% on code and JSON. The harness takes an injectable counter so you can plug in a real one before trusting the absolute dollar figures. Second, and bigger: a mock provider validates the accounting and the plumbing. It tells you nothing about Muse Ember. If you read one sentence of this post, read that one.

Token Accounting: Where the Bill Actually Comes From

System Prompt and Tool Schemas Are Re-Billed Every Turn

I measured my tool schemas before writing any task logic:

node scripts/count-tokens.js tools/*.json src/system-prompt.txt
tools/read_file.json            142
tools/grep.json                  96
tools/apply_patch.json          188
... (11 more)
--------------------------------
total (14 schemas)             1140
src/system-prompt.txt           386

1,526 tokens of fixed overhead, paid on every turn, forever. Over a nine-turn task that is 13,734 tokens — 37% of the total input bill — spent re-explaining which tools exist. Trimming to the six tools this task family actually uses saved 660 tokens per turn, which is 5,940 tokens over nine turns, or 16% of the total.

This is the cheapest optimisation available and it needs no model change at all.

Resent Conversation History Is the Hidden Multiplier

Each turn's prompt is the whole prior conversation plus everything the tools returned. If the base (system + tools + initial instruction) is B and each turn appends g new tokens:

prompt(n) = B + (n - 1) * g
total_input(N) = N*B + g*N*(N-1)/2

The second term is quadratic in N. A single-shot comparison uses prompt(N); the real bill uses total_input(N). For B = 1,800, g = 500, N = 12, the single-shot prompt is 7,300 tokens and the actual input is 54,600 — a 7.5× amplification. At N = 30 with the same parameters it is 271,500 tokens, 16.7× the final prompt. The multiplier grows with the square of the turn count, which is why "just let the agent keep trying" is the most expensive sentence in this field.

Completion Tokens Versus Hidden Reasoning or Planning Tokens

If a provider bills internal reasoning as output and does not return it in the usage block, your trace is optimistic. Two mitigations that cost nothing:

  1. Bill only on reported usage, and mark every estimated row.
  2. Once a week, reconcile the sum of costUsd in your traces against the provider's billing dashboard for the same window. More than a few percent of drift means the accounting is fiction.

I did not run this reconciliation for Muse Ember — no API access, and the coverage does not say whether reasoning tokens are billed.

Modeling Context Growth Across an Agent Loop

The Quadratic Resend Problem in Plain Arithmetic

export function project({ baseTokens, growthPerTurn, turns }) {
  let cumulative = 0;
  const rows = [];
  for (let n = 1; n <= turns; n += 1) {
    const promptTokens = baseTokens + (n - 1) * growthPerTurn;
    cumulative += promptTokens;
    rows.push({ turn: n, promptTokens, cumulativeInputTokens: cumulative });
  }
  return { rows, totalInputTokens: cumulative };
}

Measuring Growth With a Scripted Trajectory

node scripts/project-context.js --base 1800 --growth 500 --turns 12
turn  prompt_tokens  cum_input
   1           1800       1800
   2           2300       4100
   3           2800       6900
   4           3300      10200
   5           3800      14000
   6           4300      18300
   7           4800      23100
   8           5300      28400
   9           5800      34200
  10           6300      40500
  11           6800      47300
  12           7300      54600
total_input_tokens: 54600   cost_at_0.10_per_M: 0.00546

Now rerun with the shape of a real repo task — base 2,000, 8,000 tokens of new tool output per turn, stopped at the 200K ceiling:

node scripts/project-context.js --base 2000 --growth 8000 --turns 40 --limit 200000
turn  prompt_tokens  cum_input
   1           2000       2000
  ...
  24         186000    2256000
  25         194000    2450000
  26         202000  EXCEEDS 200000 -- compaction required
total_input_tokens: 2450000   cost_at_0.10_per_M: 0.245

Two and a half million input tokens for a single task. The per-token price did not change; the growth rate did.

When the 200K Limit Forces Compaction or Truncation

Trigger compaction before the window closes, not after. A rule that held up in the harness:

const pressure = promptTokens / contextLimit;
if (pressure > 0.8) await compact(messages, { keepRecentTurns: 3 });

Compaction is itself a model call. Summarizing 12,000 tokens of history into 400 costs $0.00126 at the headline rate — trivial next to the $0.245 of accumulated input. Over a 25-turn run with three compactions you add under $0.004.

What Compaction Costs You in Accuracy Terms

The bill is not the issue; fidelity is. Summaries drop exact identifiers: file paths, line numbers, stack traces, the precise error string from the failing test. Those are usually the evidence the agent needs to fix the bug.

Inference, not measurement: I expect summarization to be safe for discarded reasoning text and unsafe for tool results. In the harness I therefore compact only assistant prose and keep the last N tool results verbatim. I did not run an accuracy comparison against a real model, so treat that as a design hypothesis to test, not a finding.

Retries, Malformed Tool Calls, and Wasted Spend

Classifying Failure Modes in the Trace

Failures are not interchangeable; the costs vary wildly.

ClassExampleTypical cost
schema_invalidTool args fail JSON schema+1 turn
unknown_toolCalls a tool not in the allowlist+1 turn
arg_mismatchValid schema, wrong semantics (line range inverted)+1–2 turns
tool_errorPatch does not apply+1 turn
no_progressSame call three timesunbounded without a guard
verifier_failRuns to completion, output is wrongwhole task
budget_exceededCap hitwhole task, no result

Only two of these are expensive, and neither is the one teams instrument first.

Retry Storms and Cost Amplification

Granularity dominates. Say each turn has an 8% chance of a malformed tool call and the task takes nine turns.

Retry the turn, up to three attempts:

expected attempts = 1 + 0.08 + 0.08^2 = 1.086  ->  +8.6% cost

Retry the whole task on any failure:

P(clean run) = 0.92^9 = 0.472
expected attempts = 1 / 0.472 = 2.12       ->  +112% cost

Same failure rate, 13× different cost impact, purely from where the retry loop sits. That is why the harness retries at the turn level with a bounded attempt count and never silently re-runs a whole task.

Detecting Loops Before They Drain a Budget



function stableArgs(args) {
  return JSON.stringify(args, Object.keys(args ?? {}).sort());
}

function signature(call) {
  return createHash("sha256")
    .update(call.name + ":" + stableArgs(call.args))
    .digest("hex")
    .slice(0, 12);
}

In the loop, count signatures and abort on the third repeat. An abort record I got:

{"seq":7,"ts":"2026-11-12T10:22:19.402Z","type":"abort","taskId":"fix-null-guard-0013","turn":7,"reason":"loop_detected","signature":"4f1c9a0b7d22","repeats":3,"cumulativeCostUsd":0.0142}

Without the guard this trajectory kept calling read_file with the same arguments until the budget cap fired at $0.05 — 3.5× the cost of the abort. The signature hash is shallow (it sorts top-level keys only), so nested argument differences can produce false negatives. It has not produced a false positive in my runs, which is the failure mode you actually care about.

Running the Numbers: What $0.10 per Million Tokens Costs per Task

A Worked Example With Recorded Token Counts

A nine-turn scripted trajectory from the mock provider. Token counts are chars / 4 estimates on the scripted content, not measurements of Muse Ember.

TurnPrompt tokensCompletion tokensTool call
11,84296read_file
22,41088read_file
32,99661read_file
43,54074grep
54,120102apply_patch
64,69058run_tests
75,24071read_file
85,790133run_tests
96,35064none (final)
Total36,978747

At a flat $0.10/M that is $0.00377 per finished task. Output is 2% of tokens, so the input/output split barely moves the number — exactly why the ambiguity in the headline price is tolerable for agent workloads and intolerable for generation ones.

Break-Even Math Against a Frontier Model

Assume $3/M input and $15/M output for the frontier tier. Those are illustrative — substitute your own provider's numbers; the arithmetic is the point.

frontier: 36,978 * 3 / 1e6  = $0.110934
            747 * 15 / 1e6  = $0.011205
            total           = $0.122139

cheap:      total           = $0.003772
ratio                       = 32.4x

32× is the headline, and it is also misleading. A frontier model probably takes fewer turns; finishing in six turns at 25,000 input tokens drops the frontier cost to about $0.086 and the ratio to 23×.

Now add frontier prompt caching, assuming 90% cache hit at 10% of the input price — untested for Muse Ember, since the coverage does not mention caching:

cached   33,280 * 3 * 0.1 / 1e6 = $0.009984
uncached  3,698 * 3 / 1e6       = $0.011093
output     747 * 15 / 1e6       = $0.011205
total                            = $0.032282
ratio vs cheap                   = 8.6x

The gap collapses from 32× to 8.6× on caching alone. If Muse Ember has no cache discount, the advertised savings are much smaller than the per-token comparison suggests. For agent workloads that is the single largest unknown in this release.

Sensitivity Analysis: Input Share, Retry Rate, Context Size

Baseline is the nine-turn task at $0.00377.

ChangeInput tokensCostΔ
Baseline36,978$0.00377—
Trim 14 tool schemas → 6 (−660/turn)31,038$0.00318−16%
Double context growth (563 → 1,126/turn)57,114$0.00575+52%
Whole-task retry at 12% failure42,000 (expected)$0.00429+14%
Turn-level retry at 8%/turn40,180 (expected)$0.00410+8.6%
30 turns, 500/turn growth271,500$0.02742+627%
25-turn long-context run2,450,000$0.24500+6,400%

Turn count is the only variable here with a >10× effect. Every optimisation that cuts turns beats every optimisation that shaves per-token price.

The Escalation Router: Cheap First, Frontier on Failure

Verifier-Based Routing Instead of Blind Retry

The economically correct pattern is not "cheap model" or "frontier model." It is cheap-by-default with escalation gated on a verifier:

export async function route(task, cheap, frontier) {
  const attempt = await runTask({ provider: cheap, task });

  const verdict = await task.verify(attempt.ctx);
  if (verdict.ok) return { ...attempt, tier: "cheap" };

  // Unverifiable is not the same as failed. Do not escalate blindly.
  if (verdict.reason === "unverifiable") {
    return { ...attempt, tier: "cheap_unverified", flagged: true };
  }

  const escalated = await runTask({ provider: frontier, task });
  return { ...escalated, tier: "frontier", escalatedFrom: verdict.reason };
}

The unverifiable branch is the point. If your verifier cannot decide, escalating buys a second guess you also cannot check — you have doubled the spend and gained nothing.

Costing the Router Itself

Verifier typeCost per taskComment
Deterministic (exit code, diff scope, schema)$0Use this first, always
Cheap-model judge (900 in / 60 out at $0.10/M)$0.0001Acceptable overhead
Frontier-model judge (900 in / 60 out at $3/$15)$0.0036Nearly the cost of the whole cheap task

A frontier judge is not a verifier, it is a second task. Escalation is only cheap if the first-line verifier is free.

Now the break-even. With escalation available, cheap-first beats always-frontier when:

C_cheap + C_verify < p * C_frontier
0.00377 + 0.00013 < p * 0.122139
p > 0.0319

The cheap model only has to be right 3.2% of the time for the router to pay off. That is the real finding, and it is also why the cost argument is uninteresting: the arithmetic is so lopsided that cost stops being the deciding factor. What decides the deployment is whether your verifier catches the failures the cheap model claims are successes.

False-Confidence Cases Where the Cheap Model Says It Succeeded

These are what make a cheap execution tier dangerous, and each has a deterministic check:

  1. It edited the tests. Verify diff touches nothing under test/. This single check caught the most failures in my scripted runs, and it is free.
  2. The patch "applied" but changed nothing. Compare workspace hashes before and after; a no-op diff should fail the task.
  3. It satisfied the assertion by deleting it. Assertion count before vs. after; a drop fails the task.
  4. It passed on a stale build. Run tests from a clean checkout, not the agent's working tree.
  5. It reported success in prose with no tool call. Treat final-turn text as a claim, not a result. Only the verifier closes a task.

The cost of a false-confidence failure is not the tokens. It is the tokens plus reviewer time plus, if it slips through, the incident. That is the number missing from every per-token comparison.

Harness Results: What the Numbers Showed and What They Did Not

Per-Task Cost Distribution, Not Just the Mean

Forty scripted tasks, one task family, mock provider, $0.10/M flat. These numbers describe the harness, not the model.

tasks:      40
turns:      p50=8  p90=15  p95=19  max=24
cost_usd:   p50=0.0034  mean=0.0059  p90=0.0132  p95=0.0141  max=0.0500
total_usd:  0.2360
top2_share: 0.20
aborts:     1 (budget_exceeded)

Mean is 1.7× median. The two most expensive tasks consumed 20% of total spend. The single abort at the $0.05 cap produced no result and still cost $0.05 — 13× the median successful task. A capacity plan built on the mean under-provisions the tail, which is exactly where the budget goes.

Where the Cheap Execution Model Was Sufficient

I cannot answer this from a mock, and I will not pretend otherwise. What the harness can tell you is the shape of the answer: sufficiency is a function of verifier coverage and turn count, not model tier. A task with a deterministic success predicate and eight turns is cheap-tier territory almost regardless of model quality. A task with an unverifiable deliverable — "summarize this incident well" — is not, because you have no cheap way to detect a wrong answer.

Sample Size, Task Mix, and the Limits of This Evidence

Forty synthetic trajectories, one repository, one bug-fix family, chars / 4 token estimates, no real API calls. That is enough to validate accounting logic and show the distribution's shape. It is not evidence about Muse Ember's cost, quality, or tool-calling reliability. Three tasks would be an anecdote; forty scripted tasks is still an anecdote about the harness.

Latency and Reliability Are Part of the Cost Equation

Wall-Clock Cost of Retries and Queueing

The mock provider has no latency, so I have no measured wall-clock numbers to report. What I can give you is the accounting shape: if a task takes t seconds and an engineer is blocked for f of them per day, the human cost dwarfs the token cost. A $0.004 task that takes 90 seconds because of three retries costs more in attention than a $0.12 task that takes 12 seconds.

Track wallMs per turn in the trace from day one. You cannot reconstruct it later.

Failure Cost When a Task Never Completes

E[failure cost] = P(no completion) * (budget cap + triage time)

At a 5% non-completion rate, a $0.05 cap, and 10 minutes of triage at a loaded rate, expected failure cost per task is roughly 0.05 * (0.05 + triage). The cap is noise; the triage is the cost. That is why hard budget caps should be low enough to fail fast — one that lets an agent flail for 25 turns converts a cheap failure into an expensive one.

Operational Guardrails That Keep the Model Cheap

Per-Task Budget Caps and Hard Stop Conditions

if (costUsd > task.budgetUsd) {
  await trace({ type: "abort", taskId: task.id, turn, reason: "budget_exceeded", costUsd });
  return { ok: false, reason: "budget_exceeded", turn, costUsd };
}
if (turn >= task.maxTurns) {
  await trace({ type: "abort", taskId: task.id, turn, reason: "max_turns", costUsd });
  return { ok: false, reason: "max_turns", turn, costUsd };
}

Check the cap after every turn, not at the end. A cap evaluated at completion is a report, not a guardrail.

Prompt Stability and Cache-Friendly Ordering

If caching exists, the prefix has to be byte-identical across turns and across tasks in the same family:

  • Order: system prompt → tool schemas → stable task context → conversation.
  • Never inject timestamps, request IDs, or random ordering into the prefix.
  • Sort tool schemas deterministically by name before serialization.
  • Version the system prompt and store the version in the trace, so a cache-hostile edit shows up in the data.

If Muse Ember turns out to have no cache discount, this costs nothing and becomes free insurance the day it does.

Trimming Tool Schemas and Pruning History

  • 14 schemas → 6: 660 fewer tokens per turn, 16% off a nine-turn bill, zero quality risk.
  • Collapse consumed tool results to one line after the turn that used them, except the last two.
  • Never compact tool results that contain the failing assertion or stack trace.

Guardrail one costs nothing and is available today, whatever the model card ends up saying.

Where a Cheap Execution Model Actually Wins

High-Volume, Narrow, Verifiable Tasks

The winning case is boring: hundreds of tasks a day, a deterministic success predicate, a small tool surface, a median under ten turns. Under those conditions cost per agent task is dominated by turn count, and the arithmetic is overwhelming — a 3.2% required success rate for the router to pay off means you should deploy cheap-first even if the cheap model is mediocre, provided the verifier is real.

Tasks With Long Context That Still Fit Under the Limit

Long-context tasks win only if they are few-turn. A 150K-token read-once-and-answer task costs about $0.015 at $0.10/M and fits comfortably. The same 150K window driven through a fifteen-turn agent loop costs dollars, not cents, because you pay for the window fifteen times.

The rule: context size is cheap once; context size is expensive per turn. That distinction, not the headline price, is what should decide where Muse Ember sits in your stack.

Reproducing the Cost Harness Yourself

mkdir agent-cost-harness && cd agent-cost-harness
npm init -y
npm pkg set type=module
mkdir -p client lib scripts tools tasks runs

## paste the five files from this post, then:

node scripts/count-tokens.js tools/*.json src/system-prompt.txt
node scripts/project-context.js --base 1800 --growth 500 --turns 12
node scripts/run-tasks.js --provider mock --tasks tasks/ --out runs/mock-001.jsonl
node scripts/summarize.js runs/mock-001.jsonl

Expected summary shape:

tasks:      40
turns:      p50=8  p90=15  p95=19  max=24
cost_usd:   p50=0.0034  mean=0.0059  p95=0.0141  max=0.0500
total_usd:  0.2360
aborts:     1 (budget_exceeded)

To make this real, implement MuseEmberProvider extends Provider against whatever base URL and model identifier Meta documents, leave usageSource: "reported", and rerun with a task set drawn from your own backlog. Then — and only then — reconcile a week of traces against the invoice. Until that reconciliation line matches, every per-task number in your dashboard is an estimate wearing a suit.

Further Reading

  • TechCrunch, "Meta releases Muse Ember, a new lightweight model for agent execution," 2026-11-09 — coverage
  • Cryptopolitan, "Meta's Muse Ember targets AI's new battleground: Cost per agent task," 2026-11-10 — coverage
  • Fello AI, "Meta Muse Ember: Price, Benchmarks and the 200K Catch," 2026-11-09 — coverage
  • lavx.hu, "Meta releases Muse Ember, a lightweight model for agent execution," 2026-11-09 — coverage
  • JSON Lines specification — the trace format used throughout
  • Node.js test runner documentation — for the deterministic verifiers, with no extra dependencies

I deliberately did not link Meta's model card: it was not part of the material I was working from, and guessing a URL for a primary source is worse than admitting I did not read it.

Share this post

More posts

Loading comments…