Claude Code is asked to investigate a checkout failure. The run reads the repository, searches production logs, queries an issue tracker, and launches an eval suite. The first eval finds a flaky fixture, so the agent retries twice with broader traces.

The model bill might still look small. The tool path does not.

log search:       3 queries x 40 GB scanned
eval runner:      3 runs x 250 cases
issue search:     6 requests
artifact storage: 750 traces

A token limit cannot contain those costs. It knows nothing about bytes scanned, paid API calls, hosted test minutes, or the human time needed to inspect 750 traces.

Before a production run starts, I want Claude Code to submit a cost envelope for the path it intends to use. The runtime should reserve that budget before each call and stop when the remaining envelope cannot cover the next operation.

Claude Code tool path cost envelope

price units, not tool names

“May query logs” is a permission. It is not a budget.

The same log tool might scan 50 MB for a narrow request or 500 GB for a wildcard. Price the unit that drives the bill:

cost_catalog:
  log.search:
    unit: gb_scanned
    price_usd: 0.005
  eval.run:
    unit: test_case
    price_usd: 0.012
  issue.search:
    unit: request
    price_usd: 0.003
  model.reason:
    unit: million_tokens
    price_usd: 18.00

The opening scenario, prices and ledger values below are illustrative, not provider quotes or measurements from an actual run.

Keep the catalog outside the prompt. The tool gateway or orchestration layer should own it, version it, and attach the applicable price to each decision. An agent should not be able to lower a price estimate by rewriting its own instructions.

Some costs do not have a clean dollar rate. Track them anyway. Wall-clock minutes, trace count, changed files, and expected review minutes can each have a ceiling. A run that stays below its provider bill but creates a two-hour review is not cheap.

This extends the permission budget pattern. Permission decides whether a capability is available. The cost envelope decides how much of that capability this run may consume.

require a preflight path

The agent does not need to predict every branch. It does need to expose the expensive route it currently expects:

cost_envelope:
  task_id: checkout-timeout-284
  run_id: cc-run-a18f
  catalog_version: 2026-08-11.2
  proposed_path:
    - tool: log.search
      calls: 2
      maximum_units_per_call: 10
      maximum_cost_usd: 0.10
    - tool: eval.run
      calls: 1
      maximum_units_per_call: 250
      maximum_cost_usd: 3.00
    - tool: issue.search
      calls: 3
      maximum_cost_usd: 0.01
  ceilings:
    external_tools_usd: 3.25
    model_usd: 1.50
    elapsed_minutes: 25
    eval_cases: 250
    retries: 1
    review_minutes_estimate: 20
  stop_if:
    - query scope requires production wildcard
    - eval fixture changes
    - retry lacks new evidence

A useful preflight states the maximum, not the average. The gateway can approve a smaller reservation at runtime, but the run should never rely on a best-case estimate to fit under the ceiling.

The stop conditions matter as much as the arithmetic. Changing an eval fixture can make a failure disappear while weakening the test. A production wildcard changes data exposure as well as cost. Neither belongs inside an automatic budget adjustment.

reserve cost before dispatch

Checking spend after a call returns is too late. The charge may already exist.

Before dispatch, reserve the call’s maximum expected cost:

available external budget: $3.25
reserved by eval.run:       $3.00
remaining:                  $0.25
next log.search maximum:    $0.40
 decision: stop before dispatch

Reservations also protect parallel runs. Without them, four subagents can each see the same remaining dollar and all spend it at once. The budget service should update reservations atomically, then replace the estimate with actual usage when the tool returns.

If a provider cannot expose usage before or after a call, use a conservative fixed price or keep the tool behind human approval. Unknown cost should not mean unlimited cost.

The same boundary should reject calls that exceed permission scope. Cost control is not a substitute for method-level MCP permissions. A cheap production write can still be the wrong write.

a tool-cost budget does not limit records changed

Suppose a support agent can update ten customer records per call. Each call costs a fraction of a cent. Four workers each submit a batch of ten, all under the dollar ceiling. The task was approved to change only twenty records.

Every individual request fits. The combined action does not. This is a hypothetical design example, not a reported Claude Code incident.

Count business effects separately from money. In this example the shared allowance is twenty record mutations for the whole task, including retries and delegated workers. The trusted orchestrator assigns the task identity; a worker cannot reset its allowance by inventing another run ID. Decide whether repeated writes to one record count as additional mutations. Counting unique records alone can hide repeated notifications or other side effects.

Before dispatch, reserve both the maximum charge and the maximum mutation count. Treat them as one admission decision: either both reservations succeed or neither call proceeds. For distributed budget services, use a coordinator that holds dispatch until all reservations are confirmed and reconciles abandoned holds. A prompt cannot provide that guarantee.

The first two ten-record batches consume the task’s twenty available mutation slots. The other two must wait or be denied even if plenty of money remains. A read-only request can still proceed if its own permissions and budget allow it. This expected outcome belongs in the integration test, not just in the design document.

review the boundary with a concrete worksheet

Use the task cost and mutation budget worksheet to record the task identity, counting unit, reservation owner and evidence for each decision. It is a blank production-review artifact, not an executable gateway or proof that your controls work.

Test these cases with synthetic records in an isolated environment:

  • Start four ten-record requests against a twenty-mutation task allowance. Verify that at most two dispatch before any settlement or release. Observe dispatches and resulting changes independently of the agent’s report.
  • Restart a worker under a new run ID. Verify that it still uses the original task allowance.
  • Give the caller enough money but insufficient mutations, then reverse the shortage. Neither request should dispatch. Check for abandoned reservations too.
  • Allow one authorised read. An unavailable connector must not count as a successful denial policy.
  • Time out after a write may have reached the provider. Keep the unresolved mutation reservation held until authoritative evidence reconciles the result. A missing response is not evidence that nothing changed.

Record observed results beside the expected ones. An unknown outcome stays unknown. Do not release mutation capacity merely because a reservation timer expired; otherwise a delayed write and a retry can both consume the same allowance. Fence or cancel pending work where supported, then reconcile effects before deciding what capacity is safe to reuse.

Bind consequential actions to a single approval as well. A budget says how much the task may consume; approval says which action it may perform. Neither replaces the other.

make every retry buy evidence

Retries multiply tool spend quietly. A three-dollar eval becomes nine dollars because the agent changed one line and tried again twice.

Record why the next attempt deserves budget:

retry_request:
  previous_attempt: 1
  failed_check: checkout-timeout-eval
  new_evidence: ev-trace-91
  changed_assumption: timeout begins after gateway handoff
  proposed_change: move deadline propagation into checkout client
  repeated_calls:
    - eval.run
  added_cost_usd: 3.00
  remaining_retry_budget: 0

“Try again” is not evidence. A different failure, a narrowed hypothesis, or a new observation may justify another attempt. If the run learned nothing, the cost loop should stop.

Do not let the agent fund a retry by shrinking another estimate after the fact. Budget changes need a fresh envelope and, above a team threshold, human approval.

keep an actual-cost ledger

The review packet should show proposed, reserved, and actual consumption by cost class:

cost_ledger:
  run_id: cc-run-a18f
  catalog_version: 2026-08-11.2
  external_tools:
    ceiling_usd: 3.25
    reserved_peak_usd: 3.10
    actual_usd: 3.06
  model:
    ceiling_usd: 1.50
    actual_usd: 0.74
  eval_cases:
    ceiling: 250
    actual: 250
  retries:
    ceiling: 1
    actual: 0
  stopped_calls:
    - tool: log.search
      reason: reservation_would_exceed_external_ceiling
  pricing_unknown: []
  decision: within_envelope

Save the catalog version and raw provider usage references with the ledger. Prices change. Reviewers need to know which rate produced the total, and operators need enough evidence to reconcile the invoice later.

This ledger also gives the team something useful to optimize. If log scans dominate, narrow the query tool. If eval retries dominate, improve failure classification. If review time dominates, improve the evidence linked to each action. Cost data should change the workflow, not merely decorate a dashboard.

My rule is straightforward: price the proposed path, reserve the next call, and record actual spend. When the next operation does not fit, Claude Code stops and asks for a new decision.

For the wider workflow around tool permissions, cost controls and review evidence, see Claude Code: Building Production Agents That Actually Scale, available on Kindle.