docs · guides
Budgets and cost#
A budget caps how many tokens, or how many estimated dollars, an agent may use in one run or over its whole life. When usage reaches a cap, Hekma applies the agent's breach action: pause it (the default), stop it, or just record a warning. Hekma checks budgets only while a hekma command or an embedding program holds the engine, so keep one running beside any agent whose spend matters.
Changing. This page describes budgets as they work in 0.11.0. In development: budgets become one kind of limit a Policy can set by label, and
warn, with loud signals, becomes the default breach action, so a breach no longer stops work unless you ask it to. Agents that rely on today'spausedefault keep it. See Policies and the warn default.
Set a budget#
Budgets are ordinary config keys on the agent. Set them with hekma agent config set, at any time, running or not:
# Stop this agent after 200,000 tokens in one run.
hekma agent config set my-agent budget.tokens.per_run 200000
hekma agent config set my-agent budget.breach_action stop| Key | Value | Meaning |
|---|---|---|
budget.tokens.per_run | whole number of tokens | Cap for the current run. |
budget.tokens.cumulative | whole number of tokens | Cap over every run of the agent. |
budget.dollars.per_run | dollar amount, such as 5.00 | Estimated-cost cap for the current run. Needs a rate. |
budget.dollars.cumulative | dollar amount | Estimated-cost cap over every run. Needs a rate. |
budget.breach_action | pause, stop or warn | What happens when any cap is reached. Defaults to pause. |
Tokens here means input plus output. Cached tokens are part of the input, so they count once.
You can set any mix of the four caps. Hekma checks them all after each usage event, and one breach action applies to every cap. Values are checked when you set them, and a bad value changes nothing:
✗ invalid value 'throttle' for config key 'budget.breach_action': 'throttle' is not a valid breach action (expected one of: pause, stop, warn). Nothing was changed. Fix the value and try again.To remove a budget, edit or delete the key in the agent's config.toml in its Agent Home; config set has no unset in 0.11.0. Config, secrets and memory covers the config file and its layers.
Per run or cumulative#
A per-run cap resets when the agent starts a new run: each start, and each automatic restart after a crash, begins at 0. A cumulative cap never resets; it counts every token the agent has ever reported to this Hekma installation.
A detached agent stays in one run for its whole life, across every command that adopts it, so its per-run total keeps growing until it really stops. See Supervision and detached runs.
A cap breaches when usage reaches it, not when it goes past. With budget.tokens.per_run 3000 and an agent that reports 1,500 tokens at a time, the breach fires on the second report, at exactly 3,000. If a per-run and a cumulative cap trip on the same event, Hekma records the per-run one.
Breach actions#
| Action | What Hekma does | When to use it |
|---|---|---|
pause (default) | Suspends the agent's process. It stays paused, even between commands, until you resume or stop it. | You want to look before deciding. Needs an agent whose pause capability is not unsupported. |
stop | Stops the agent: a graceful signal, then a forced kill after the stop window. | Hard ceilings, unattended agents. |
warn | Records the breach and does nothing else. The agent keeps running. | Learning an agent's normal spend before enforcing anything. |
A guaranteed pause really freezes the process (on Linux and macOS, with SIGSTOP). On Windows, or for an agent that declares pause best-effort, the agent is marked paused but may not stop working at once. If the agent declares pause unsupported, a pause action cannot freeze it; use stop for that agent.
When budgets are enforced#
Hekma checks budgets as it reads each usage event, and it reads usage only while some process holds the engine: a running hekma command, or a program that embeds the engine. Most commands finish in a fraction of a second, so for a detached agent you need a long-running command such as:
hekma agent logs my-agent --followWhile it runs, budgets are enforced live. When it is not running, the agent can spend without limit, and that usage is not counted later either. Supervision and detached runs covers the patterns that keep an agent watched.
Two more rules:
- One breach per run. Each cap fires once per run. After a breach, later usage in the same run does not fire it again, even if you resume the agent. A new run resets this.
- Adoption checks at once. When a command adopts a detached agent that is already over a cap it has not breached in this run, Hekma applies the action straight away instead of waiting for the next usage event.
What a breach looks like#
With pause, a running logs --follow ends with:
• note: Agent Instance 'ticker' is paused; no further output until it is resumed.
[hekma] ticker: the paused detached child was NOT resumed at engine release — it was paused by a BUDGET BREACH, and resuming it here would run it unsupervised in the enforcement-free between-commands window; it stays suspended until a later command resumes or stops itWith stop, it ends with:
• note: Agent Instance 'spender' is stopped; no further output will arrive.With warn, nothing appears on the terminal. Every breach, whatever the action, is written as one JSON line to logs/breaches.log in the Agent Home:
{"schema_version":1,"instance":"watcher","run_id":"run-1792696159956498000-0","scope":"per-run","dimension":"tokens","limit":3000,"observed":3000,"action":"warn","metering_source":"self-reported","at":"2026-10-22T19:09:23Z"}scope is per-run or cumulative, dimension is tokens or dollars, and limit and observed are tokens or micro-dollars to match. For pause and stop, the agent's state change is also recorded in logs/instance.log with the cause budget-exceeded.
hekma agent list shows the budget as remaining over limit, with the action in brackets. cum 0/6000 tok (pause) means a cumulative token cap of 6,000 with 0 left; run $0.02/$0.02 (stop) means a per-run dollar cap of $0.02, shown as remaining over limit.
Resume after a breach#
A paused agent waits for you. To let it carry on in the same run, resume it:
hekma agent resume ticker✓ Resumed Agent Instance ticker
runningResuming does not re-arm the cap that fired. The breach is spent for this run, so that cap never fires again until the agent stops, even if you raise it first. In a 0.11.0 run, a cumulative cap raised from 6,000 to 12,000 before the resume let the agent reach 16,800 tokens, well past the new cap, without a second pause. To keep the agent under a limit, set the new cap and start a new run:
hekma agent config set ticker budget.tokens.cumulative 20000
hekma agent stop ticker
hekma agent start ticker --detachA stopped agent (from the stop action) starts again with a normal hekma agent start. Its cumulative total is kept, so a cumulative cap that is already used up trips again as soon as Hekma next checks it: at the first usage event of the new run, or, for a detached agent, as soon as the next command adopts it.
Dollar costs#
Hekma can turn tokens into an estimated dollar cost and cap that too. Set a rate: dollars per million tokens, for input and output separately, and optionally for cached input.
hekma agent config set spender cost.rate.input 3.00
hekma agent config set spender cost.rate.output 15.00
hekma agent config set spender cost.rate.cached 0.30
hekma agent config set spender budget.dollars.per_run 0.02| Key | Meaning |
|---|---|
cost.rate.input | Dollars per 1M input tokens. Required for any dollar figure. |
cost.rate.output | Dollars per 1M output tokens. Required for any dollar figure. |
cost.rate.cached | Dollars per 1M cached input tokens. Optional; without it, cached tokens are priced at the input rate. |
Both cost.rate.input and cost.rate.output must be set. With only one, or neither, Hekma shows no dollar figures and dollar caps do nothing. Rates accept up to six decimal places (0.000001 is one micro-dollar) and no currency sign.
How cost is worked out#
For each usage event, Hekma prices each part separately and rounds each part to the nearest micro-dollar (a millionth of a dollar), then adds them:
- uncached input: (input tokens minus cached tokens) × input rate ÷ 1,000,000
- cached input: cached tokens × cached rate ÷ 1,000,000
- output: output tokens × output rate ÷ 1,000,000
With the rates above, an event of 1,200 input tokens (800 of them cached) and 300 output tokens costs $0.0012 + $0.00024 + $0.0045 = $0.00594, stored as 5,940 micro-dollars. Four such events reach 23,760 micro-dollars, past a $0.02 cap, so the fourth event trips it. That is what the real run below shows.
Money is stored as whole micro-dollars, never as floating point, so totals add up exactly. Each event keeps the rate that was in force when it was recorded: changing a rate prices future usage only and never rewrites history.
Every dollar figure Hekma prints is labelled (estimated). It is derived from the tokens the agent or the proxy reported and the rates you entered, not from your provider's bill. Use it to catch runaway spend, and use your provider's billing for invoices.
A dollar cap in action#
The agent below reports 1,200 input tokens (800 cached) and 300 output tokens every two seconds, with the rates and the $0.02 per-run cap set above and budget.breach_action stop. After the fourth report, Hekma stops it:
▸ Fleet (1 row)
Name Kind State Supervision Restarts Budget (tok, est. $) Usage (tok, est. $) Agent Home
────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
spender worker stopped — 0 run $0.02/$0.02 (stop) in 4800 / out 1200 / cach… /Users/you/Library/…
Fleet total: in 4800 / out 1200 / cached 3200 · ≈ $0.02 (estimated)The table rounds to cents. --json gives the exact micro-dollars:
hekma agent usage spender --json{
"schema_version": 2,
"instance": "spender",
"usage": {
"cumulative_input_tokens": 4800,
"cumulative_output_tokens": 1200,
"current_run_input_tokens": 0,
"current_run_output_tokens": 0,
"cumulative_dollars": 23760,
"current_run_dollars": 0,
"estimate_label": "estimated",
"cumulative_cached_tokens": 3200,
"current_run_cached_tokens": 0
}
}The current-run figures are 0 because the run ended when the agent stopped. JSON output documents every field.
Read next#
- Meter token usage: where the token counts come from.
- Supervision and detached runs: keep budgets enforced while agents run.
- Config keys: every budget, rate and metering key in one table.
- Logs, JSON and scripting: watch spend from a script.