Problem
There's no way to set a token budget on a running city. If agents go haywire (context accumulation, spawn storms, stuck loops), they burn tokens silently until you notice or run out.
Currently the only workaround is an external monitoring loop (shell script parsing Claude JSONL transcripts on a cron), which requires a separate Claude session running — itself burning tokens to watch for token burn.
Proposed solution
Add a [budget] section to city.toml:
[budget]
max_input_tokens = 500000 # per window
window = "30m" # rolling window
action = "stop" # "stop" | "warn" | "suspend"
The controller already runs a reconcile tick every patrol_interval (default 30s). On each tick:
- Read token usage from Claude JSONL transcripts (the plumbing exists in
internal/sessionlog/tail.go)
- Sum input tokens across all active sessions within the rolling window
- If over threshold: execute the configured action (stop city, warn via event, or suspend all rigs)
Why the controller, not the deacon
This must be in Go, not in an LLM agent. The deacon is itself an LLM session that burns tokens — having it monitor token burn is circular. The controller is a Go process with zero token cost.
Existing infrastructure
internal/sessionlog/tail.go — extracts input_tokens, cache_read_input_tokens, cache_creation_input_tokens from session JSONL
~/.claude/projects/ — Claude Code writes transcripts here, path derivable from agent work_dir
- Controller reconcile loop — runs every
patrol_interval, natural place to add the check
Why
Token costs are the #1 operational concern for multi-agent orchestration. A circuit breaker that runs at zero marginal cost (Go code in the controller) is better than any LLM-based monitoring.
Problem
There's no way to set a token budget on a running city. If agents go haywire (context accumulation, spawn storms, stuck loops), they burn tokens silently until you notice or run out.
Currently the only workaround is an external monitoring loop (shell script parsing Claude JSONL transcripts on a cron), which requires a separate Claude session running — itself burning tokens to watch for token burn.
Proposed solution
Add a
[budget]section tocity.toml:The controller already runs a reconcile tick every
patrol_interval(default 30s). On each tick:internal/sessionlog/tail.go)Why the controller, not the deacon
This must be in Go, not in an LLM agent. The deacon is itself an LLM session that burns tokens — having it monitor token burn is circular. The controller is a Go process with zero token cost.
Existing infrastructure
internal/sessionlog/tail.go— extractsinput_tokens,cache_read_input_tokens,cache_creation_input_tokensfrom session JSONL~/.claude/projects/— Claude Code writes transcripts here, path derivable from agent work_dirpatrol_interval, natural place to add the checkWhy
Token costs are the #1 operational concern for multi-agent orchestration. A circuit breaker that runs at zero marginal cost (Go code in the controller) is better than any LLM-based monitoring.