A Claude Code run split a production incident into three parallel investigations:
- one subagent searched logs;
- one ran the hosted regression suite;
- one queried traces from an observability vendor.
Each child received a four-dollar limit. The parent run had a ten-dollar ceiling. Every child checked its own budget, saw enough room, and started.
The final bill was twelve dollars.
Nothing ignored a limit. The design had four limits and no shared source of truth.
This is easy to miss in a demo because parallel work looks efficient. In production, each branch can consume paid APIs, hosted evals, data scans, model tokens, and storage at the same time. A child-local check cannot protect a parent budget that other children are spending concurrently.
A child allowance is not money
The parent can tell each subagent, “Do not spend more than four dollars.” That instruction is useful, but it does not allocate four exclusive dollars unless the runtime reserves them.
Consider this timing:
parent ceiling: $10
current actual spend: $0
10:02:01 child-a reads available=$10
10:02:01 child-b reads available=$10
10:02:01 child-c reads available=$10
10:02:02 each starts a call with maximum_cost=$4
10:04:18 actual total=$12
All three decisions were individually valid against an old snapshot. Together they were wrong.
This is the same concurrency problem we already know from inventory and account balances. Reading the balance and writing the result as separate operations creates a race. Agent orchestration does not make the race less real.
A token counter inside each child also misses costs outside the model. The expensive call might be a warehouse query or an eval job. The component that can dispatch the paid operation must ask the shared budget owner first.
Let the parent own reservations
Use one ledger for the whole task tree. Every child call asks that ledger to reserve its maximum expected cost before dispatch. The ledger admits or rejects the reservation atomically.
budget_account:
account_id: budget-incident-284
root_run_id: cc-run-9017
ceiling_usd: 10.00
actual_usd: 0.00
reserved_usd: 8.00
available_usd: 2.00
version: 19
reservations:
- reservation_id: rsv-log-17
child_run_id: child-a
operation: log.search
maximum_usd: 4.00
status: active
expires_at: 2026-09-04T10:07:01Z
- reservation_id: rsv-eval-22
child_run_id: child-b
operation: eval.run
maximum_usd: 4.00
status: active
expires_at: 2026-09-04T10:07:01Z
rejected_request:
child_run_id: child-c
operation: trace.query
maximum_usd: 4.00
reason: shared_ceiling_would_be_exceeded
The invariant is small enough to put in a unit test:
actual_usd + active_reservations_usd <= ceiling_usd
Do not calculate that invariant in the prompt. Enforce it in the gateway, scheduler, or budget service that controls dispatch. Claude Code can propose a cheaper operation after rejection, but it cannot mark its own call as affordable.
The update needs an atomic compare-and-swap, transaction, or equivalent lock. If two reservation requests arrive with ledger version 19, only one may commit the next version. The loser rereads the ledger and tries admission again against the new balance.
Reconcile estimates without lending twice
A reservation is a hold, not final spend. When the operation returns, replace the hold with provider-reported actual usage.
reservation_reconciliation:
reservation_id: rsv-log-17
reserved_usd: 4.00
actual_usd: 2.70
provider_usage_ref: logs-job-77192
released_usd: 1.30
ledger_version_before: 20
ledger_version_after: 21
status: settled
Only the parent ledger may release the difference. A child should not tell a sibling that $1.30 is available based on its own response. The ledger may still be processing another settlement, cancellation, or price correction.
Use conservative reservations when exact preflight pricing is impossible. If a query may scan between 20 GB and 400 GB, reserve for the approved maximum query scope. An average estimate protects the dashboard, not the ceiling.
This builds on pricing the tool path before a Claude Code run starts. The cost envelope defines the intended route. The parent ledger makes that envelope survive concurrency.
Give abandoned reservations an expiry
Parallel branches crash. Users cancel runs. Networks split after admission but before dispatch. Without an expiry, abandoned holds can freeze a budget forever.
Each reservation needs a short lease and a dispatch state:
reservation_state:
reservation_id: rsv-trace-31
lease_expires_at: 2026-09-04T10:07:01Z
dispatch_started: false
provider_operation_id: null
If dispatch never started, the parent can release the expired hold. If dispatch may have started, expiry does not prove that the provider did nothing. Mark the outcome unknown, reconcile through the provider operation ID, and block a replacement call until the result is known. The same rule applies to timed-out MCP writes: uncertainty is not permission to repeat the action.
Cancellation should stop new admissions immediately. It should not erase active reservations or pretend in-flight work is free. Keep them until each operation settles or an operator resolves the unknown outcome.
Test the race on purpose
A sequential test will pass even if the implementation is unsafe. Start several children against the same ledger version and force their admission requests to overlap.
fixtures:
- case: three_children_request_four_dollars_from_ten
expect:
admitted: 2
rejected: 1
maximum_committed_usd: 8.00
- case: settlement_releases_unused_hold
expect:
released_only_after_parent_commit: true
- case: child_crashes_before_dispatch
expect:
expired_hold_released: true
- case: child_times_out_after_possible_dispatch
expect:
outcome: unknown
replacement_blocked: true
- case: parent_run_cancelled
expect:
new_reservations_allowed: false
active_reservations_preserved: true
Run the first fixture repeatedly with randomized ordering. Assert against the final ledger, not the messages each child happened to print.
The review packet should include the parent ceiling, peak reserved amount, actual spend, rejected calls, unresolved operations, and ledger versions. That gives an engineer enough evidence to explain why a call ran, why another one stopped, and whether the invoice can still change.
Child budgets help Claude Code plan. They do not protect shared money. Put the ceiling in a parent-owned ledger, reserve before dispatch, and settle against actual provider usage.
Get Claude Code: Building Production Agents That Actually Scale on Amazon Kindle for the wider production system around agent budgets, retries, permissions, MCP, evals, observability, rollback, and review evidence.