Budgets and billing
Hard ceilings, the alert line, subscription versus API key, and how to leave dry run.
Every pull request has a ledger. Four numbers are hard ceilings. Crossing one stops the run in budget_exceeded. That state is terminal until the ceiling changes on the default branch or an operator reconciles.
Ceilings
Set these under budget in .autofeat/config.yml.
| Key | Default | Rule |
|---|---|---|
budget.usd | 25.0 | Cumulative USD for this pull request. Must be greater than 0. |
budget.tokens | 2000000 | Cumulative tokens. Integer, at least 1. |
budget.minutes | 240 | Wall-clock minutes. Integer, at least 1. |
budget.turns | 12 | Turns for this pull request. Integer, at least 1. |
budget.alert_usd | 10.0 | Warning only. Must be >= 0 and <= budget.usd. |
alert_usd does not stop the run. When the ledger reaches it, the sticky comment gains a warning banner and ledger.alert_fired stays true. A blocking budget alert (the ceiling itself) fails the check run.
The sticky spend row prints usd=, tokens=, minutes=, and runs=.
Subscription versus API key
agents.billing maps an agent name to subscription or api_key. An agent missing from the map is api_key.
| Mode | USD |
|---|---|
subscription | Settles at 0 USD. Turn, minute, and run ceilings still apply. |
api_key | Priced from the model table below. Unknown pricing refuses the run before it starts. |
Subscription ceilings (deployment, not per pull request):
| Key | Default | Rule |
|---|---|---|
subscription.max_concurrent | 2 | At least 1. |
subscription.max_runs_per_day | 50 | At least 1. An alert fires at 80% of this cap, and at 80% of turns and minutes. |
Hosted subscription logins belong to the operator (claude, codex, kimi, grok-build). You do not put those tokens in the repository.
Priced models
API-key billing accepts these model ids. Prices are USD per million tokens (input / output) and are estimates, not an invoice.
| Model id | Input | Output |
|---|---|---|
deepseek-v4-pro | 0.30 | 1.20 |
deepseek-chat | 0.27 | 1.10 |
deepseek-reasoner | 0.55 | 2.19 |
claude-sonnet-4 | 3.00 | 15.00 |
claude-3-5-sonnet | 3.00 | 15.00 |
gpt-4o | 2.50 | 10.00 |
grok-4 | 3.00 | 15.00 |
Aliases that share a row: openrouter/<id> for each id above, anthropic/claude-sonnet-4, anthropic/claude-3-5-sonnet, openai/gpt-4o, xai/grok-4, and deepseek/deepseek-v4-pro, deepseek/deepseek-chat, deepseek/deepseek-reasoner.
Any other model id has no price. An API-key run that needs one is refused.
Deployment daily ceiling
On top of the per-pull-request budget.usd, the hosted deployment has a daily API-key ceiling. The default is 25 USD (daily_api_key_ceiling_usd). Subscription runs do not add to it, because they settle at 0. This ceiling is operator configuration, not a key in .autofeat/config.yml.
Dry run
autonomy.dry_run defaults to true.
A dry run still writes the journal, the sticky comment, and check runs. It does not push, submit a review, merge, or change labels. Check conclusions are neutral.
security.allow_same_uid: true is valid only when dry_run is true. Do not use it on a shared runner. See Security.
How to go paid
- Run one pull request to a clean dry-run finish (
neutralchecks, sticky statereadyfor the default merge mode). - On the default branch, set
autonomy.dry_run: false. - Merge that config change. The next pull request uses the new
policy_sha.
Leave merge_mode: stop_before_merge until you intend for autofeat to merge. See Merge modes. doctor prints a warning when dry_run is false and merge_mode is auto.