Skip to main content

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:

  1. Generates ~/.hermes/agentguard/private.key + public.key (Ed25519). The directory is created 0700 and the private key 0600, owner-only from the moment it is created.
  2. Writes a default policy.yaml ($5/day soft cap downgrades Opus → Sonnet, $20/day hard cap blocks, $2/min burst guard)
  3. 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

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

agentguard_spend_hermes-0.2.3.tar.gz (18.3 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

agentguard_spend_hermes-0.2.3-py3-none-any.whl (15.8 kB view details)

Uploaded Python 3

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

Hashes for agentguard_spend_hermes-0.2.3.tar.gz
Algorithm Hash digest
SHA256 b84adf650bc7300bd877c781d26aab365404cf9be53c4d5516481532d07f106b
MD5 9df1762dbf2d217e8f7d1dc19c5d5efd
BLAKE2b-256 6e3b395f25e059590809f39e0d932dc9f1706b6fe327813b77f4d878fd4b9eba

See more details on using hashes here.

File details

Details for the file agentguard_spend_hermes-0.2.3-py3-none-any.whl.

File metadata

File hashes

Hashes for agentguard_spend_hermes-0.2.3-py3-none-any.whl
Algorithm Hash digest
SHA256 626c76fcae97ca263741d57a706d6bf4c5a616f87b13ba2f1df82f7e2846f4a6
MD5 2a03e7414bd0e337bd6eaea94f1071c8
BLAKE2b-256 bc9594f5c86d8ec15ba5c9c34855b46c8e6ee87085973980521b4aacb7239f3d

See more details on using hashes here.

Release history Release notifications | RSS feed

This release

0.2.3 This release

2 files

0.2.2

2 files

0.2.1

2 files

0.2.0

2 files

0.1.4

2 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page