All plugins

budget-leash

Hard budget enforcement for Hermes sessions. Tracks estimated model spend (token usage x per-model prices, cache read/write tokens included) and tool-call counts against a per-session cap and a persistent per-day cap; blocks tool calls via pre_tool_call once a cap is exhausted and cuts off the model calls themselves via the llm_execution middleware, answering with a synthetic budget-exhausted reply so the provider is never invoked (fail-closed), so unattended agents cannot run up unbounded cost; warns at 80% of a cap via context injection, keeps a flock-guarded day-ledger on disk that survives restarts and is shared safely across processes, and writes a per-session JSONL spend report. Disclosure — local code only; meters estimated model spend from token-usage metadata and tool-call counts, and with the defaults ($2 per session, $10 per day, 200 tool calls per session, 1000 per day) refuses tool calls and answers model calls with a synthetic budget-exhausted reply once a cap is reached; spend figures are estimates from a user-editable price table (default $1/$3 per million input/output tokens), not provider bills; reads its settings from budget-leash.json in the Hermes home and writes ledger.json, its lock file and reports.jsonl under plugin-data/budget-leash/ there; no network calls, no subprocesses.

jusstAutomationv0.1.2Updated 5 hours ago

About

Hard budget enforcement for Hermes sessions. Tracks estimated model spend (token usage x per-model prices, cache read/write tokens included) and tool-call counts against a per-session cap and a persistent per-day cap; blocks tool calls via pre_tool_call once a cap is exhausted and cuts off the model calls themselves via the llm_execution middleware, answering with a synthetic budget-exhausted reply so the provider is never invoked (fail-closed), so unattended agents cannot run up unbounded cost; warns at 80% of a cap via context injection, keeps a flock-guarded day-ledger on disk that survives restarts and is shared safely across processes, and writes a per-session JSONL spend report. Disclosure — local code only; meters estimated model spend from token-usage metadata and tool-call counts, and with the defaults ($2 per session, $10 per day, 200 tool calls per session, 1000 per day) refuses tool calls and answers model calls with a synthetic budget-exhausted reply once a cap is reached; spend figures are estimates from a user-editable price table (default $1/$3 per million input/output tokens), not provider bills; reads its settings from budget-leash.json in the Hermes home and writes ledger.json, its lock file and reports.jsonl under plugin-data/budget-leash/ there; no network calls, no subprocesses.

Budget Leash

Most agent "budgets" are dashboards — they tell you what you spent after
the money is gone.
The Leash enforces before dispatch: when the cap is
reached, the tool call does not run — and the next model call doesn't
happen either.

The scenario it exists for is everyday: unattended agents — cron fleets,
overnight loops, always-on gateways — spend money while nobody is
watching, and a dashboard only tells you afterwards. What the Leash caps
is exactly what it can see: estimated model spend (token usage priced
per model) and tool-call counts. A tool that bills outside the model
is never priced or gated on a guess — it only counts when you list it
yourself under tool_costs with the price you choose. The Leash is that
enforcement as a first-class plugin, on Hermes' own hook surface.

How it works

Two meters, each tracked per session and per UTC day:

| Meter | Source | Notes |
| --- | --- | --- |
| Estimated model spend (USD) | post_api_request token usage × per-model price table | Prices configurable per model; a default price covers unlisted models. Cache read/write tokens are priced too (Anthropic cache_read_input_tokens / cache_creation_input_tokens, OpenAI prompt_tokens_details.cached_tokens, Gemini cached_content_token_count); set cache_read / cache_write per model, otherwise each defaults to that model's input price |
| Tool calls | post_tool_call (blocked calls are not metered) | Optional flat per-tool USD costs for tools that bill outside the model (paid APIs, device rentals) |

Enforcement points:

  • pre_tool_call returns a block when the session cap, the daily cap,
    either tool-call cap is exhausted — or when a flat-cost tool call would
    itself push the session over its cap.
  • The llm_execution middleware closes the remaining gap: blocking
    tool calls alone still let a capped session burn spend on tool-free
    reasoning turns. Once any cap is exhausted, the middleware answers the
    agent loop with a synthetic provider-shaped "budget exhausted" reply
    and the provider call is never made — enforcement covers the model
    itself, not just its tools. On OpenAI-compatible and Anthropic API
    modes the reply is a real SDK response object and the session ends
    with that explanation; on stricter modes a rejected synthetic reply
    just retries into the same cut-off, so the cap holds either way. Cut-off
    calls are counted per session (blocked_api_calls in the report).
  • pre_llm_call injects a one-time warning at 80% of a cap, so the
    model can wrap up instead of being cut off mid-task.
  • The daily ledger persists on disk
    (~/.hermes/plugin-data/budget-leash/ledger.json, one per Hermes
    profile), so restarts and parallel processes share one ceiling — a cron
    fleet can't multiply the budget by respawning. Every ledger read and
    write happens under an exclusive file lock (flock on
    ledger.json.lock) and re-reads the file first, so the CLI
    and the gateway can no longer overwrite each other's totals. A ledger
    left by an older version in the Hermes home root is migrated on first
    load, so a day's totals never reset on upgrade.
  • on_session_end appends a spend report to
    ~/.hermes/plugin-data/budget-leash/reports.jsonl. /leash shows live status;
    /leash report prints the last session's numbers.

A blocked agent can still write its final answer — plain replies are not
tool calls — and the block message tells it to explain the budget stop to
the user.

Configuration

Defaults: session cap $2.00, daily cap $10.00, 200 tool calls/session,
1000/day, warn at 80%. Override in ~/.hermes/budget-leash.json:

{
  "session_cap_usd": 5.00,
  "daily_cap_usd": 25.00,
  "prices": {"gemini-3.5-flash-lite": {"input": 0.10, "output": 0.40}},
  "tool_costs": {"rent_device": 1.50}
}

Cache pricing, per model (defaults to the model's input price when omitted —
a conservative over-estimate, not a silent under-count):

{
  "prices": {"claude-sonnet-4-5": {"input": 3.00, "output": 15.00,
                                   "cache_read": 0.30, "cache_write": 3.75}}
}

Environment overrides: LEASH_SESSION_CAP_USD, LEASH_DAILY_CAP_USD,
LEASH_SESSION_TOOL_CALLS, LEASH_DAILY_TOOL_CALLS. LEASH_DISABLE=1
is a kill switch.

Safety & scope

  • Fail-closed on budget, fail-open on bugs: hook exceptions are
    swallowed (a Leash bug never breaks the agent loop), but a reached cap
    always blocks.
  • Spend is an estimate from reported token usage and your price table —
    exact billing remains the provider's invoice. For free models, set
    prices to 0 and enforce purely on call counts.
  • No credentials are read; no network calls are made.

Install

Drop this directory into ~/.hermes/plugins/budget-leash/, enable it
(hermes plugins enable budget-leash), and restart Hermes.

Tests

python3 tests/test_leash.py — spend accumulation, session/daily cap
blocking, ledger persistence across processes, tool-call caps, flat tool
costs, the one-time 80% warning, cache-token pricing (configured rates,
input-price default, nested OpenAI details), the ledger race
(interleaved processes sum instead of clobbering, stale readers refresh
before deciding, two real processes racing the ledger), and the
llm_execution cut-off (pass-through under the cap, provider never
invoked over it, synthetic reply shape).

README from the reviewed commit 7b41267; it updates when the author re-pins.

More by jusst

3 plugins by jusst in the catalog.

jusstconstraint-vaultPins the user exact constraints (numbers, addresses, hard rules) as structured local data and re-injects them verbatim into the model context on every turn and immediately after every context compaction, with a SHA-256 hash-logged injection record, because memory providers and compression silently paraphrase or drop exact values. Not a memory provider and not a compressor: a guard layer above both. Disclosure — local code only, no network or processes; stores constraints in constraint-vault.json in the Hermes home and appends a hash record to constraint-vault-injections.jsonl on every turn; the model can pin or drop constraints through its own tools without asking, and pinned text is injected into the model context on every turn of every session until dropped.Communitygeneraljusstescalation-governorDeterministic stuck-detection for Hermes sessions. Watches tool/API failure signals (consecutive tool errors, repeated identical calls, API error bursts, model calls without progress) and, when a threshold trips, injects a structured escalation packet (goal, what was tried, what failed) directing the agent to delegate the remaining work to a stronger model via delegate_task instead of retrying blindly; writes a per-session JSONL report with escalation and token-usage accounting. Disclosure — local code only: injects an escalation packet (the session's first user message and recent tool targets/errors) into tool results and into each following turn's context once a stuck threshold trips, directing the agent to call delegate_task (which spends model usage on a subagent); reads an optional escalation-governor.json and appends one line per session to a shared escalation-governor-reports.jsonl in the Hermes home; adds a /governor status command; opens no network connections, starts no processes and never blocks a tool call.Communityautomation

Developer Mode

Explore built-in Hermes toolsets and actions.

HermesAgent

Developer?

Create a Hermes extension for Desktop or agent workflows.

Developer Section