Per-Agent Budgets
An agent with no ceiling is a cost you cannot forecast. Give an LLM agent or an external agent a monthly budget, in tokens, in dollars, or both, and it stops before it spends past it.
Configuration
agents:
research_agent:
name: research_agent
agent_type: llm
model: claude-sonnet-4-6
prompt: Research the question and cite your sources.
monthly_token_budget: 2000000
monthly_cost_budget: 150
budget_on_exhaust: escalate| Field | Meaning |
|---|---|
monthly_token_budget | Most tokens the agent may use in a calendar month. |
monthly_cost_budget | Most it may spend in a calendar month, in US dollars. |
budget_on_exhaust | What happens when it would go over: graceful (the default) returns a "budget exhausted" result and stops quietly; escalate hands the situation to the Manager so a person hears about it. |
Budgets are off unless you set them. Months are calendar months in UTC. A budget on a human agent has no effect; on a programmatic agent it applies to the calls its integration makes.
How it is enforced
Reserved before the call, settled after it. Before every model call, the call's expected cost is reserved against the agent's month. If the reservation would cross the budget, the call is not made. After the call, the reservation is replaced by what the call really spent. Because the reservation happens first, several calls running at the same moment cannot all slip under the cap.
Every tool round is gated. When the model uses tools, each further round re-sends the whole request plus the tool results so far, and each round is reserved before it runs. A round that would cross the budget is not run; the agent answers with what it already has.
Fails closed. If the usage store cannot be reached to check the budget, the call is refused — an unverifiable budget is never treated as an open one.
A budget stop is not treated as an agent failure: the agent's output says
plainly that its budget is spent, and budget_on_exhaust decides between a
quiet stop and escalation. Those runs are also kept out of the agent's
memory, so it never learns "do nothing" from them.
External agents
Every external agent can have a monthly budget. It is checked before every call to it, with the same rules: refused when spent, refused when the usage store cannot be reached.
Measured or estimated. Where the external platform reports what a call used, that is what counts into the month. Where it does not, the mesh estimates each call from what it sends (the input, the request form and any conversation history) and what comes back. An estimate does not see work the far side did out of sight, so it is marked as estimated.
Give an estimated agent a price. An estimate is in tokens. Set
price_per_1k_tokens so it has a cost too, and a monthly_cost_budget
applies. Without it, only a monthly_token_budget can stop an estimated
agent.
agents:
order_workflow:
name: order_workflow
agent_type: external
framework: n8n
monthly_token_budget: 500000
monthly_cost_budget: 40
price_per_1k_tokens: 0.02
budget_on_exhaust: escalateReserved before the call, paced over the month. Before each call the
mesh reserves what the agent's last call cost, so calls racing for the last
of a budget cannot overspend it together. The first call of a new agent
reserves nothing and always goes. A call that would put the agent ahead of
the month's even pace is held back, and budget_on_exhaust decides whether
it stops or escalates. Your escalation contact is told once a day while it
is ahead of pace.
price_per_1k_tokens applies to external agents and to a programmatic
agent's integration.
Pacing over the month: lean mode
A budget is meant to last the month, not be spent in two days. When an LLM agent is spending ahead of the month's pace (its share of the month gone, plus a few days' headroom), it goes into lean mode:
- It keeps taking every task. Nothing is refused or delayed.
- Each task gets a normal task's share of tokens: what a typical task of this agent costs, or, before it has learned that, the rest of the month's budget spread over the days left. It is told so, and uses fewer tool calls.
- Your escalation contact gets one high-priority Inbox notice a day saying how much of the budget is used, how much of the month has gone, and the day the budget runs out at this rate.
- It is back to normal as soon as it is on pace again.
The monthly cap is still the hard stop. An external agent is held back instead, as described above.
What one task may spend
Every run of an LLM agent is a task, and its tokens are measured. Once an agent has 10 normal tasks behind it, a task may spend up to 4 times a typical task (or 1.5 times its heaviest ones, if that is more). Nothing to configure.
When a task reaches that, the tool call that would pass it is not made, the
agent is told why, and it answers with what it already has. A task is
never cut off without an answer, and its first model call always goes. A task
that was stopped, ran in lean mode, failed or was a version trial is not
learned from, so the ceiling never teaches itself to shrink. Super-agents keep
their own cost_ceiling.
The trace shows each task's ceiling, its tokens, and whether it was stopped.
Agents are told their budget
On every model call, the agent is told its monthly allocation, where it stands against an even pace, and what one more tool round costs — so it can plan its own work inside the budget instead of discovering the limit by hitting it.
Watching spend
Studio shows each agent's spend against its budget. Over the API:
| Endpoint | Purpose |
|---|---|
GET /api/budgets | Every agent's spend and budget, filterable by status — capped, exhausted, near (80% or more), active or uncapped — and sortable by tokens, cost or percentage used. |
GET /api/budgets/{agent} | One agent. |
These are read-only. Change a budget in the agent's configuration.
Model prices
Cost is tokens times price per 1M tokens: input, output, and cached input read or written. LeafCraft ships a standard price list. Pricing is its own page in Studio, where you keep price records: a name and its prices, for example a negotiated rate or a vendor's new price. You tag a record to any model, a provider's or one you added, and one record can price many models.
A tagged model's every cost uses its record: budgets, the budgets page, and each trace's per-loop cost. Untag it to go back to the standard price. Records are kept in the mesh's database, not in config.
| Endpoint | Purpose |
|---|---|
GET /api/pricing · POST /api/pricing | Your price records (each with the models it prices), or a new one: {name, input, output, cache_read?, cache_write?} in USD per 1M tokens. |
PUT · DELETE /api/pricing/{price_id} | Change a record (every model it prices follows), or remove it. A record still in use is kept unless you pass untag=true. |
POST /api/pricing/{price_id}/models · DELETE …/models/{model} | Tag the record to a model, or untag it. |
GET /api/pricing/standard | The standard prices, read-only. |
GET /api/pricing/history | Every change, newest first. |
A record is one flat price for every call of the models it prices. The standard list's long-prompt, peak-hour and dated prices don't apply to it. A model with no price at all shows its calls as "cost unknown", never $0.
Next Steps
LeafMesh — spend you can forecast and cap