agentguard-spend-hermes
One-step install of AgentGuard® Spend into Hermes Agent (Nous Research).
Adds local spend caps + Ed25519-signed audit logs to every Anthropic and OpenAI call your Hermes agent makes. No proxy. No cloud component. Prompts and provider keys never leave your machine.
Built for Hermes's unattended-by-default workflow: cron jobs, sleep loops, multi-platform messaging bridges (Telegram, Discord, Slack, WhatsApp, Signal).
Install
# In the same virtualenv as Hermes
uv pip install agentguard-spend-hermes
That's it. Hermes's plugin manager auto-discovers the plugin via the hermes_agent.plugins entry point on next startup.
First-run auto-bootstrap
On first Hermes startup after install, the plugin:
- Generates
~/.hermes/agentguard/private.key+public.key(Ed25519). The directory is created0700and the private key0600, owner-only from the moment it is created. - Writes a default
policy.yaml($5/day soft cap downgrades Opus → Sonnet, $20/day hard cap blocks, $2/min burst guard) - Monkey-patches the Anthropic and OpenAI client constructors so every LLM call is policy-checked + signed
You'll see in the Hermes log:
agentguard-spend: wrote default policy to ~/.hermes/agentguard/policy.yaml (locale: en-US)
agentguard-spend: generated signing keypair (private=..., public=...)
agentguard-spend: active (anthropic=True, openai=early, policy=...)
The policy file is localized to your system locale at first-write (en-US, es-419, or pt-BR).
When a cap fires
Downgrade (soft cap):
[hermes] anthropic.messages.create model=claude-opus-4-7
[agentguard] downgrade: claude-opus-4-7 -> claude-sonnet-4-6 (daily soft cap)
[hermes] continuing with sonnet
Block (hard cap):
[hermes] anthropic.messages.create model=claude-opus-4-7
[agentguard] block: hard daily ceiling exceeded
[hermes] AgentGuardBlockedError raised — agent halts this turn
Configure
Edit ~/.hermes/agentguard/policy.yaml and restart Hermes. Example:
id: hermes-default-v1
name: Hermes default caps
version: 1
effectiveFrom: "2026-01-01T00:00:00Z"
mode: enforce
scope:
tenantId: hermes-personal
caps:
- amountCents: 500 # $5/day soft cap
window: per_day
action: downgrade
downgradeTo: claude-sonnet-4-6
- amountCents: 2000 # $20/day hard cap
window: per_day
action: block
- amountCents: 200 # $2/minute burst guard
window: per_minute
action: block
Disable temporarily
export AGENTGUARD_DISABLE=1 # plugin loads but does nothing
Per-agent spend caps
There is no per-cap scope: field. A SpendCap is amountCents, window, action, and optionally downgradeTo / reason. Spend is bucketed by the policy's scope, not by anything on the individual cap, so one policy file is one budget and a cap cannot carve itself out of it.
To give each bridge its own budget, run one Hermes process per bridge, each with its own HERMES_HOME (so it gets its own policy.yaml and its own ledger) and a matching HERMES_AGENT_ID:
# Telegram bridge process
export HERMES_HOME=~/.hermes-telegram
export HERMES_AGENT_ID=hermes-telegram
# Discord bridge process
export HERMES_HOME=~/.hermes-discord
export HERMES_AGENT_ID=hermes-discord
# Cron job
export HERMES_HOME=~/.hermes-cron
export HERMES_AGENT_ID=hermes-cron
Then pin each policy to that agent:
# ~/.hermes-telegram/agentguard/policy.yaml
scope:
tenantId: hermes-personal
agentId: hermes-telegram # must equal that process's HERMES_AGENT_ID
caps:
- amountCents: 1000 # $10/day for the Telegram bridge
window: per_day
action: block
The two agentId values have to match. A policy applies only to calls whose scope matches every field the policy sets, so a policy.scope.agentId naming an agent the process is not running as means the policy never matches and every call is allowed. Omit agentId from scope: (the bootstrapped default) and the policy governs whatever that process runs as.
Spend windows are tracked in-process, so two processes never share a live budget even if you point them at the same policy. The signed ledger on disk is the durable record.
Verify the audit log
Every decision is appended to ~/.hermes/agentguard/decisions.ndjson (one signed, hash-chained JSON entry per line). The file appears on the first guarded LLM call and survives restarts, so the chain keeps extending across runs.
from agentguard_spend import verify_chain
import pathlib, json
public_key = pathlib.Path("~/.hermes/agentguard/public.key").expanduser().read_bytes()
entries_path = pathlib.Path("~/.hermes/agentguard/decisions.ndjson").expanduser()
entries = [json.loads(line) for line in entries_path.read_text().splitlines()]
result = verify_chain(entries, public_key)
print("OK" if result.ok else f"Chain broken at #{result.sequence}: {result.reason}")
What this plugin does NOT change in Hermes
- Hermes's request retry logic
- Hermes's credential refresh flow
- Hermes's interrupt / cancel pattern
- Hermes's MCP / tool-call layer
- Any of the existing skills
Strictly an LLM-call-intercept layer between Hermes and the Anthropic/OpenAI wire.
Localization
Block traces render in the active locale:
- 🇺🇸
en-US(default) - 🇲🇽 🇦🇷 🇨🇴 🇨🇱
es-419(Latin American Spanish) - 🇧🇷
pt-BR(Brazilian Portuguese)
Resolution chain: explicit AGENTGUARD_LOCALE env var → LC_ALL / LC_MESSAGES / LANG → system locale → en-US fallback.
License
BUSL-1.1. Free for production deployments processing up to 10,000 enforcement calls per calendar month. Commercial licensing for higher volumes or service redistribution: invest@agentguard.run.
Patents
Certain AgentGuard technologies are patent pending in the United States. See https://agentguard.run/patents.
Links
- Homepage: https://agentguard.run
- Underlying SDK:
agentguard-spend(PyPI) - TypeScript counterpart:
@agentguard-run/spend(npm) - Hermes Agent: https://github.com/NousResearch/hermes-agent
- Contact:
invest@agentguard.run
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file agentguard_spend_hermes-0.2.3.tar.gz.
File metadata
- Download URL: agentguard_spend_hermes-0.2.3.tar.gz
- Upload date:
- Size: 18.3 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via:
twine/7.0.0 CPython/3.12.8
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
b84adf650bc7300bd877c781d26aab365404cf9be53c4d5516481532d07f106b
|
|
| MD5 |
9df1762dbf2d217e8f7d1dc19c5d5efd
|
|
| BLAKE2b-256 |
6e3b395f25e059590809f39e0d932dc9f1706b6fe327813b77f4d878fd4b9eba
|
File details
Details for the file agentguard_spend_hermes-0.2.3-py3-none-any.whl.
File metadata
- Download URL: agentguard_spend_hermes-0.2.3-py3-none-any.whl
- Upload date:
- Size: 15.8 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via:
twine/7.0.0 CPython/3.12.8
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
626c76fcae97ca263741d57a706d6bf4c5a616f87b13ba2f1df82f7e2846f4a6
|
|
| MD5 |
2a03e7414bd0e337bd6eaea94f1071c8
|
|
| BLAKE2b-256 |
bc9594f5c86d8ec15ba5c9c34855b46c8e6ee87085973980521b4aacb7239f3d
|