The spend guard watches for work that multiplies cost, says so before and while it happens, and explains it afterwards. It never changes anything on its own: every mitigation is something you pick.
Before fan-out. When a turn is about to start several subagents (Task calls in one batch, or one next to agents already running, e.g. from /batch), when you start a /team, or when you start a /loop, Chanto estimates the cost first:
estimate = the context each agent starts with × the calls it's expected to make × agents × the model's price
Each agent starts with the system prompt and tools plus its task, and grows by about 3k tokens a call. Its first call writes that prompt to the provider's cache and later calls read it back, at the cache-read and cache-write rates where the provider has them (input rates otherwise). Calls per agent default to 15, and once you've run a few subagents Chanto uses the average of your own (kept in ~/.chanto/cache/spend.json). Agents run on the subagent model: the agent definition's model, subagent_model, or the main model. A /loop is priced as six calls on the current context per run, times the runs in a day; a self-paced loop is assumed to run every 10 minutes.
Prices that aren't known are never guessed. Those estimates show tokens, and on a plan that reports usage windows (ChatGPT) the share of the window. Chanto learns that share from how fast the window fills as the session uses tokens: e.g. ~2.1M tokens, ~14% of your 5h window. Local models are free and never asked about.
Above confirm_over_usd (default $2), or confirm_over_plan_percent of a plan window (default 10%), or confirm_over_tokens when neither is known (default 5M), the TUI asks:
Spend check: starting 4 subagents on anthropic/claude-opus-5-5 (~15 calls each): ~$3.10 (2.3M tokens), over your $2.00 confirm threshold.
❯ Continue (~$3.10 (2.3M tokens))
Use anthropic/claude-sonnet-5-5 for the agents (~$1.40 (2.3M tokens))
Run at most 2 at a time (same total, slower to burn, easier to stop)
Cancel- Use a cheaper model is offered when
[spend] cheap_model, or the next tier down of the same family (Opus → Sonnet → Haiku, GPT-6 Astra → Sol → Luna, …), has a known, lower price. Subagents then run on it for the rest of the session. - Run at most N at a time caps how many agents run at once for the rest of the session (
limit_agents, default 2). The total is the same; it burns slower and is easier to stop part-way. - Cancel doesn't start them; the model is told why and does the work directly or with fewer agents.
After you continue, a similar fan-out within 10 minutes isn't asked about again unless it's more than twice as big. -p and background runs follow non_interactive: "warn" (default) prints the estimate as a warning and continues, and "stop" refuses to start the fan-out and says so. Neither is silent. /team shows the estimate in its plan approval, next to the team budget that caps it.
While it runs. The guard tracks $/min (or plan-% an hour) for the session and each agent, over a rolling 5-minute window. It flags each of these once per session, with a one-line note in the transcript and a $ … marker in the footer:
| Pattern | Example notice |
|---|---|
many agents at once (parallel_agents, default 4) | Spend: 5 agents running in parallel; each resends its own context on every call, so cost grows with the count. /cost limit 2 caps how many run at once. |
the same large file (4k+ tokens) read again and again (repeated_reads, default 3) | Spend: src/parser.rs (~12k tokens) has been read 3 times; every copy stays in context and is resent on each call. Read the part you need (offset/limit) or keep one summary. |
a context above resent_context_percent of the window (default 50%) resent on five calls in a row | Spend: the main agent's context is ~150k tokens (75% of the window) and is resent on every call, ~$0.05 a call even with most of it cached. /compact or a fresh session cuts that. |
| the same tool call with the same result four times in an agent's last dozen | Spend: the same Grep call ran 4 times in the Explore: map the parser with the same result: no progress, but each repeat is another model call over the whole context. |
spend above burn_usd_per_min (default $0.50) or burn_plan_percent_per_hour (default 25%) | Spend: ~$0.62/min over the last 3m across 6 agents (above $0.50/min). /cost shows where it goes. |
notices = false turns them off. Detection works on counters the agent loop already keeps, so it adds no model calls.
Afterwards: /cost. Besides the totals, budgets and plan limits, /cost breaks the session down by agent (model, calls, tokens in and cached, out, cost, $/min), by model (including cache writes), by tool (tokens their results added to the context) and by the large files read more than once. It ends with suggestions from what it saw:
Subagents ran on anthropic/claude-opus-5-5 for $4.12 (63% of this session's spend); anthropic/claude-sonnet-5-5 would have cut that by ~50%.Context was resent 340 times at ~180k tokens (90%+ of the window): /compact or start fresh when a task is done.Up to 8 agents ran in parallel: /cost limit 2 caps that.
/cost today adds up every session's model calls today, by model, from the log. /cost cheaper [model] runs subagents on a cheaper model for the rest of the session (/cost cheaper off undoes it), and /cost limit [N] caps agents at once (/cost limit off). /compact shrinks the context.
Budgets. session_usd, day_usd and month_usd cap spend per session, per local calendar day (from the model-call log) and per calendar month (saved sessions last active this month, plus this one). They're the same budgets as max_cost_usd and max_cost_usd_per_day (which win when both are set), and the same checks: /goal's max_cost_usd, background runs' and the runner's budgets all count against them too. A note at 50% and 80% of the tightest budget, and at 100% the turn stops before its next model call: interactively you're asked whether to continue, and -p and background runs stop.
[spend]
confirm_over_usd = 2.0
confirm_over_plan_percent = 10
confirm_over_tokens = 5000000
non_interactive = "warn" # or "stop"
# calls_per_agent = 15 # default: learned
# cheap_model = "anthropic/claude-haiku-5-5"
limit_agents = 2
notices = true
burn_usd_per_min = 0.5
burn_plan_percent_per_hour = 25
parallel_agents = 4
repeated_reads = 3
resent_context_percent = 50
# session_usd = 5.0
# day_usd = 20.0
# month_usd = 200.0