Foundation for making budget limits user-settable (parent epic tracks the full set).
Today
The account circuit breaker is two bare constants in workers/api/src/lib/delegation-budget-store.ts:
DAILY_CEILING_MICROS = 50_000_000 // $50 charged / 24h (line 95)
DAILY_TOKEN_CEILING = 250_000_000 // 250M tokens / 24h (line 112)
No env var, no per-account column, no admin setting reads them. The per-tree defaults in delegation-budget.ts (DEFAULT_LIMITS: $5/tree, 50 delegations, depth 4) are likewise static (with a p95-derived per-user cost ceiling in openBudget, but nothing settable). The only existing platform-AI setting is PUT /v1/admin/settings/platform-ai, a boolean kill switch — not a number.
Scope
- Introduce an effective-ceiling resolver: per-account override (persisted) → platform default (persisted/admin-set) → env var → the current constant as the hard fallback. Constants become the last-resort default, not the source of truth.
- Read the resolved value in
reserve() (both the money and token checks) and in openBudget — never the raw constant.
- Storage: a
account_budget_limits D1 table (user_id, token_ceiling, charged_micros_ceiling, per_tree_cost_micros, delegations, max_depth, updated_at) + a platform-default row. Migration.
- Correct the refusal message in
reserve() — it currently says usage-ages-out but implies no lever; once configurable it should point at the setting. (Also the agent-facing claim "contact support to raise it" is fiction today — remove that pathway from any prompt/guidance.)
- Guardrails: clamp to a sane max so a user cannot set an unbounded ceiling; keep it a circuit breaker.
Why
Unblocks the UI (#UI) and MCP (#MCP) surfaces. Without a resolver they would each reach for the constant.
Foundation for making budget limits user-settable (parent epic tracks the full set).
Today
The account circuit breaker is two bare constants in
workers/api/src/lib/delegation-budget-store.ts:No env var, no per-account column, no admin setting reads them. The per-tree defaults in
delegation-budget.ts(DEFAULT_LIMITS: $5/tree, 50 delegations, depth 4) are likewise static (with a p95-derived per-user cost ceiling inopenBudget, but nothing settable). The only existing platform-AI setting isPUT /v1/admin/settings/platform-ai, a boolean kill switch — not a number.Scope
reserve()(both the money and token checks) and inopenBudget— never the raw constant.account_budget_limitsD1 table (user_id, token_ceiling, charged_micros_ceiling, per_tree_cost_micros, delegations, max_depth, updated_at) + a platform-default row. Migration.reserve()— it currently says usage-ages-out but implies no lever; once configurable it should point at the setting. (Also the agent-facing claim "contact support to raise it" is fiction today — remove that pathway from any prompt/guidance.)Why
Unblocks the UI (#UI) and MCP (#MCP) surfaces. Without a resolver they would each reach for the constant.