Skip to main content

Govern your Hermes agent: approvals on your phone, spend you can see

Your agent decides to run kubectl delete deployment api. You are not at the keyboard. Right now it just runs.

preloop-hermes-plugin connects Hermes to Preloop, the open-source AI agent control plane. With the plugin installed, that command pauses, the request lands on your phone, watch, Slack, Mattermost, email, or the web console, and you tap Approve or Deny. The agent continues or gets blocked with your reason. Everything it did is recorded.

What you get

  • Dangerous commands wait for you instead of just running. Hermes has no local allow or deny lists for its native tools, so every single tool call goes to your central policy. Allow, deny, or hold for a human, per tool and per argument.
  • Approve from wherever you actually are. Push to phone or watch, Slack, Mattermost, email, an outbound webhook, or the Preloop console. The tool call stays blocked while you decide, for up to 24 hours by default, so "I will look at it after lunch" is a valid answer.
  • Nothing runs ungoverned when Preloop is down. The gate fails closed by default. An unreachable control plane, a 5xx, a bad token, a malformed reply or malformed YAML in your config all block the call rather than waving it through.
  • Talk to an agent that is already running. A durable control channel stays open, so you can send a message, dictate one, or interrupt the current turn from the console or the mobile apps, long after you walked away from the terminal.
  • A record of what the agent did, and who let it. Every governed call is logged with the matched rule, the approver, the arguments, and the outcome.
  • One screen for every agent you run, with its bill. Per-agent spend, budget ceilings that stop the spend, and a session timeline. This part needs the agent onboarded to Preloop as well as the plugin installed. See What onboarding unlocks.

The Preloop console overview: pending approvals waiting for a decision, budget health against soft and hard ceilings, and the list of active agents with per-agent spend and a Talk button on each

Two pieces, because they install differently:

  • The plugin (this package) gates the tools Hermes reaches for, the shell commands and file writes the model decides to run, and holds open the control channel for messages and interrupts.
  • Onboarding Hermes to Preloop (one extra CLI command, below) routes its MCP and model traffic through Preloop, which is what produces per-agent cost attribution, budgets, allowed-model lists, and session cost optimization. The plugin does not do this on its own.

Install the plugin and you get governance. Onboard the agent and you also get the bill, itemized, across every agent you run rather than just Hermes.

It is Apache-2.0, and it works against either the open-source Preloop control plane you host yourself, or the hosted Preloop Cloud.

Watch it work. Onboarding, tool governance, approvals, and cutting session cost, recorded end to end against a real stack:

Preloop video series: see your agents, govern them, cut their cost

60 seconds to install

Python 3.11+ and Hermes v0.10.0 or newer are required. The version floor is load-bearing for the approval gate. Read Hermes version below before you rely on it.

pip install preloop-hermes-plugin

If your Hermes build wraps PyPI installs:

hermes plugins install preloop-hermes-plugin

Hermes discovers the plugin through the hermes_agent.plugins entry point after install. Restart Hermes afterwards.

You also need a Preloop control plane to approve against, either Preloop Cloud (nothing to run) or the open-source stack on your own machine:

curl -fsSL https://preloop.ai/install/oss | sh

Connect it

The plugin ships its own login helper, so you never hand-author a token:

preloop-hermes-plugin login
preloop-hermes-plugin verify

login opens Preloop's OAuth flow, mints a runtime bearer token, and writes the preloop.control block into the discovered config file (backing up the existing file alongside it first). verify checks the config shape and that the plugin loads.

Config discovery order: --config <path> (if given), then $HERMES_HOME/config.yaml and config.yml, then ~/.hermes/config.yaml and config.yml. When several of those files exist, the plugin prefers the first that contains a preloop.control block, so a systemd user unit with a different HERMES_HOME does not mask the file onboarding wrote. When no config file exists yet, $HERMES_HOME/config.yaml is preferred if the variable is set so the new file lands where Hermes will read it. Pass --config explicitly to override.

Or let the Preloop CLI do all of it

If you have (or want) the Preloop CLI, it discovers your Hermes install, backs up the config, installs this plugin, and writes the credentials for you:

curl -fsSL https://preloop.ai/install/cli | sh
preloop signup                        # or: preloop login --url http://localhost:3000
preloop agents onboard hermes
preloop agents install-plugin hermes
preloop agents validate hermes

This is the path that also routes Hermes' MCP tool calls through the Preloop MCP firewall and its model traffic through the Preloop gateway, which is where the budgets and per-agent cost attribution come from. The plugin alone covers native tool approvals and the control channel.

Undo anything with preloop agents restore hermes or preloop agents offboard hermes.

Hermes version

The gate works by returning {"action": "block", ...} from a pre_tool_call plugin hook. Hermes only started acting on that return value in v0.10.0 (tag v2026.4.16). Before that, pre_tool_call callbacks were observer-only and their return value was discarded.

So on Hermes v0.9.0 and older this plugin installs cleanly, connects to Preloop, shows the agent as online, and gates nothing. Tool calls run unchecked while the console looks healthy. There is no error to notice.

Check what you are running:

hermes --version

If you need to confirm the enforcement path directly rather than trust the version string:

python3 -c "import hermes_cli.plugins as p; print(hasattr(p, 'get_pre_tool_call_block_message'))"

True means the build acts on block directives. Newer builds route the same decision through resolve_pre_tool_block, which also carries the {"action": "approve"} escalation Hermes added in v0.18.1. This plugin does not depend on that path, because approvals are decided in Preloop and returned as a block, not handed to Hermes' local prompt.

What happens on the first dangerous tool call

The model picks a tool. Before Hermes runs it, the plugin's pre_tool_call hook stops it and works through three steps.

  1. Preloop evaluates your central policy. Unlike some runtimes, Hermes has no local allow or deny lists for native tools, so the plugin escalates every call rather than resolving anything itself. Rules match on the tool name and its arguments, written either as simple conditions or as CEL expressions, and the whole policy can be exported and imported as YAML. A rule can allow the call, deny it, or require a human. Most calls resolve here without bothering anyone.
  2. If a human is required, the request goes out and the tool waits. A notification with the full command lands on your phone, watch, Slack, Mattermost, email, an outbound webhook, or the console. The tool call is still blocked while you think. The default wait budget is 24 hours.
  3. The answer comes back and is recorded. Approve and the tool runs. Deny and Hermes receives a block envelope carrying the reason you gave, which the agent sees as the tool result and usually works around. Either way the decision is written to the same audit trail as your MCP tool calls.

When things go wrong, the call blocks. Only a valid allow lets a tool run. A returned deny, including an approval that expired (timed_out: true), blocks even if you turned fail-open on. Transport errors, timeouts and HTTP 5xx block by default and are the only failures that an explicit fail-open can waive. HTTP 4xx (including 401 and 403), malformed decisions, missing credentials, unreadable config and invalid configuration always block. enabled and fail_open must be real YAML booleans; a quoted string such as "false" is rejected and never opts you into ungoverned execution.

The Preloop tools page with rules on an MCP tool: deny above one threshold, require approval in the middle band, allow below it, each rule written as a CEL expression over the tool arguments

Configuration reference

The plugin reads the preloop.control block from the discovered Hermes config ($HERMES_HOME/config.yaml or .yml, then ~/.hermes/config.yaml or .yml; see Connect it):

preloop:
  control:
    enabled: true
    protocol: preloop.agent_control.v1
    runtime: hermes
    control_ws_url: wss://app.preloop.ai/api/v1/agents/control/ws
    bearer_token: agt_...
    runtime_principal_id: hermes-...
    runtime_principal_name: Hermes
    tool_approval:
      enabled: true
      fail_open: false
Setting Default What it does
tool_approval.enabled true Set to false to turn the native tool-call gate off entirely
tool_approval.fail_open false Fail-closed by default: if Preloop is unreachable, the tool call is blocked. Set true only if you accept ungoverned execution during an outage
tool_approval.timeout_seconds 86400 Workflow wait budget, an integer from 30 to 86400 seconds; HTTP adds 15 seconds and the synchronous hook bridge adds another 15 seconds
PRELOOP_TOOL_APPROVAL_FAIL_OPEN unset Environment override for fail_open (1/true/yes/on)

Wait budgets

The default budget covers approval workflows up to 24 hours, including a workflow selected by a central rule. It does not change the workflow expiry: a five-minute workflow still expires after five minutes. A shorter configured budget must cover every workflow this agent can select, because reaching the HTTP or bridge deadline follows the failure behaviour above. Missing config uses the default; invalid values block and are rejected by verify.

Bundled standalone and Helm nginx configurations allow 86460 seconds only on /api/v1/agents/permission-check. Other ingress, load-balancer and Hermes host limits must also permit the chosen wait.

Disabling the plugin gate skips central policy. Preloop's server-side approvals-off setting only disables human escalation and does not bypass an explicit central require-approval rule.

Manual Test Without Preloop CLI

The plugin does not need the Preloop CLI at runtime. To check an install by hand:

pip install preloop-hermes-plugin
preloop-hermes-plugin login          # or: --config /path/to/config.yaml
preloop-hermes-plugin verify
preloop-hermes-plugin run

run opens the Agent Control WebSocket and advertises capabilities without Hermes attached. In Preloop the agent should show as online, and Talk controls should appear in the console and mobile apps. To test message delivery end to end, run the plugin inside Hermes itself (not via run, which has no session attached), then pick the Hermes agent in the console, click Talk, and send a short message.

What the plugin actually does

Scoped honestly, so you know what you are installing:

  • Maintains a WebSocket to Preloop's Agent Control endpoint, with reconnect backoff and heartbeat, so the channel survives laptop sleep and network changes.
  • Advertises capabilities: new and existing sessions, text, voice transcripts, interrupt, tool approval.
  • Delivers operator messages and voice transcripts into the running Hermes session, and relays interrupts.
  • Gates every native tool call through pre_tool_call, fail-closed, bridging Hermes' synchronous hook onto its own event loop so the decision is a plain dict by the time Hermes reads it.

What it does not do: it is not a content filter or a prompt-injection defense. Preloop's protection against prompt injection is partial. Policy and approvals mean an injected instruction still has to get past your rules and, for anything risky, past you. That is a meaningful barrier, not a guarantee. It does not see Hermes' MCP tool calls at all: those are governed by the MCP firewall, which requires onboarding. It does not itself route model traffic, and so it does not by itself produce cost attribution, budgets, or optimization findings. And it cannot enforce anything the host runtime does not enforce for it: the gate is only as good as Hermes' pre_tool_call handling, which is why the version floor above is a hard requirement rather than a recommendation.

What onboarding unlocks

Preloop is the open-source AI agent control plane (Apache-2.0, self-hostable, with Preloop Cloud as a hosted option). Once an agent's traffic runs through it, alongside approvals you get:

  • MCP firewall. Allow, deny, require approval, or require a justification on every MCP tool call, as YAML plus CEL policy.
  • AI model gateway. OpenAI- and Anthropic-compatible, with per-agent budgets, allowed-model lists, and cost attribution. Provider keys stay with Preloop instead of inside agent containers.
  • Cost analytics and budgets. Spend explained by model, agent, session, API key, and user, with soft and hard budget ceilings and budget-health alerts.
  • Session cost optimization. Evidence-grounded waste findings per session, one-click apply, and consent-gated replay verification of the savings. This ships in the open-source core, using your own model keys.
  • Runtime session observability. One timeline per session covering tool calls, model calls, policy decisions, approvals, and spend.
  • Audit trails. Durable records with the matched policy, approver, inputs, timestamps, and outcome.

The Preloop cost view: estimated spend and token totals for the period, per-agent cost breakdown, and budget health against soft and hard ceilings

The Preloop audit timeline: a live, filterable stream of model requests, runtime sessions, token counts, cost per call, and outcomes

The point of the combination: one control plane over every agent you run, not a separate dashboard per runtime. Preloop works with any MCP-compatible agent, including Hermes, OpenClaw, Claude Code, Codex CLI, Cursor, Gemini CLI and OpenCode. The same Hermes, still running at full speed, but now something you can see while it works, stop before it does damage, talk to from anywhere, and account for afterwards.

Editions: Preloop is the open-source edition. Preloop Cloud is the hosted service. Preloop Enterprise is the commercial self-hosted edition.

Learn more

Apache-2.0. Copyright (c) 2026 Spacecode AI Inc.

Metadata

Release files for preloop-hermes-plugin 0.3.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for preloop-hermes-plugin 0.3.1
File Size Uploaded
preloop_hermes_plugin-0.3.1.tar.gz 34.4 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for preloop-hermes-plugin 0.3.1
File Interpreter ABI Platform
preloop_hermes_plugin-0.3.1-py3-none-any.whl Python 3 none any Details

Total release size: 54.7 kB

Release files / preloop_hermes_plugin-0.3.1.tar.gz

Download URL preloop_hermes_plugin-0.3.1.tar.gz
Size 34.4 kB
Tags Source
SHA-256 checksum
How to use checksums
075cce1d83ee931ba173708cbe508aa8689bcc4df0b810d14bb4632407a4a707
BLAKE2b-256 checksum
How to use checksums
806c52666d57f0f01a5b32345f8187d30cb877c7c28051760f7470bfa08a004e
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.12.14

Release files / preloop_hermes_plugin-0.3.1-py3-none-any.whl

Download URL preloop_hermes_plugin-0.3.1-py3-none-any.whl
Size 20.2 kB
Tags Python 3
SHA-256 checksum
How to use checksums
753dae45b1c542e52a5e9c0d6905e0d89a782319cc57058df75528e95ba7011f
BLAKE2b-256 checksum
How to use checksums
0acf0f8bf84fd7ff21cd7b2cb0e6a59fa848b267b4469a6c95673d2dee70e48a
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.12.14

Release history Release notifications | RSS feed

This release

0.3.1 This release

2 release files

0.2.2

2 release files

0.2.1

2 release files

0.2.0

2 release files

0.1.1

2 release files

0.1.0

2 release 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