openguardrails-instrumentation-hermes
Guard a Hermes agent and its
sandbox through the OpenGuardrails (OGR)
protocol. One policy.json enforces across three altitudes — correlated by
guard_id and provenance.
pip install openguardrails-instrumentation-hermes
(pulls in openguardrails, the zero-dependency reference runtime.)
Installing the Python package does not activate a Hermes plugin by itself.
Hermes discovers plugins from $HERMES_HOME/plugins (normally
~/.hermes/plugins) and the plugin must be enabled:
# Development checkout of the OpenGuardrails repository
python -m pip install -e integrations/agent/hermes
mkdir -p "${HERMES_HOME:-$HOME/.hermes}/plugins"
ln -sfn "$PWD/integrations/agent/hermes/src/openguardrails_instrumentation_hermes" \
"${HERMES_HOME:-$HOME/.hermes}/plugins/ogr-guard"
hermes plugins enable ogr-guard
hermes plugins list
Run these commands from the OpenGuardrails repository root, then restart Hermes. This plugin is used for in-process enforcement; Session/Run/Turn reconstruction at the external gateway does not depend on the client plugin.
Why a plugin, not a proxy
Hermes already exposes the interception points OGR needs, so no proxy and no core patching is required for 3 of the 4 altitudes:
| OGR altitude | Hermes surface | Enforce? | Sees |
|---|---|---|---|
gateway (LLM I/O) |
pre/post_api_request hooks |
observe | full prompt + completion |
agent_hook (tool lifecycle) |
pre_tool_call hook |
block | tool name + args, pre-dispatch |
| provenance | post_tool_call hook |
taint | tool results (web/mcp → untrusted) |
sandbox (real exec) |
wraps BaseEnvironment.execute |
block | real argv + secret env keys + cwd |
Only the sandbox altitude needs a wrapper, because Hermes has no
environment-level hook. It is installed from register(), is idempotent, and
fails open if Hermes' layout differs.
Install into a real Hermes
# in a Hermes plugin entrypoint:
from openguardrails_instrumentation_hermes import register
register(ctx) # binds the 4 hooks + installs the sandbox wrapper
Or drop the bundled plugin.yaml into a Hermes plugin dir. Override the policy
with OGR_POLICY=/path/to/policy.json; a Hermes-tuned default ships inside the
package.
What Hermes calls a "sandbox" (and which to use)
There is no syscall sandbox by default. "Sandbox" = a pluggable Environment
backend: local = subprocess.Popen on the host (zero isolation, the
default), docker = docker exec into a container, plus Modal/SSH/Daytona. All
funnel through the one BaseEnvironment.execute() chokepoint we wrap.
Pick the OS-level enforcement backend with OGR_SANDBOX:
OGR_SANDBOX |
Scenario | Enforcement |
|---|---|---|
argv (default) |
quick start | OGR decision only — no OS isolation |
srt |
personal (one laptop, no Docker) | Anthropic Sandbox Runtime: sandbox-exec/bubblewrap enforces the real syscall boundary |
| OpenShell (gateway) | multi-tenant (shared fleet) | container + OPA/Rego egress proxy + gateway credential injection |
The same OGR sandbox policy block compiles to both backends — see
openguardrails_instrumentation_hermes.sandbox.srt and .sandbox.openshell.
No sandbox? OGR degrades, it doesn't fail.
With local there is no isolation boundary, so the only enforcement altitude
is pre_tool_call (inspect argv before exec and block). You keep policy,
provenance, and gateway detection — but lose the adversary-proof view, so a clever
agent can obfuscate argv past the intent check. Run tools under srt/docker so
the sandbox altitude exists and closes that blind spot.
Run the self-test (no Hermes install needed)
python -m openguardrails_instrumentation_hermes.selftest
Drives four scenarios through the real hook signatures: benign / injection-blocked / same-command-trusted / defense-in-depth.
Status
v0.1. Verified against real Hermes (2026-06-28): all four hooks bound, benign
commands executed, credential reads and untrusted-origin curl | bash blocked at
the altitude that saw them first.
Platform reporting with an enrolled identity (optional)
Set OGR_RUNTIME_URL + OGR_API_KEY and the plugin also ships every
GuardEvent to an OpenGuardrails runtime — fire-and-forget, local enforcement
stays authoritative. On first use it enrolls a per-instance Ed25519 key
(POST /enroll, the API key is the bootstrap token) and signs each batch
with OGR-Batch-Signature, so the runtime records this instance's identity
at its enrollment scope instead of an unverified claim
(spec: specification/attestation.md).
Hermes is the "many instances per machine" case: name each one with
OGR_INSTANCE (default default). The instance asserts
subject.agent_id = hermes-<instance> and appears as its own Agent in the
console. OGR_KEYFILE overrides the keypair path
(~/.ogr/hermes-<instance>-ed25519.json), OGR_PRINCIPAL the principal
(default user:<login>).
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 openguardrails_instrumentation_hermes-0.1.1.tar.gz.
File metadata
- Download URL: openguardrails_instrumentation_hermes-0.1.1.tar.gz
- Upload date:
- Size: 17.4 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/6.1.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
3024fe6b8166ce7f6b5182491ee77151f9acf5093a57f9745be7f758bb9836c3
|
|
| MD5 |
0e7ae7d1e50de07fd890c04253f88e63
|
|
| BLAKE2b-256 |
22db8c8a3afaa674dfabb5ed88aa61c939e68981482291adc5f2ef2fd6a570ea
|
Provenance
The following attestation bundles were made for openguardrails_instrumentation_hermes-0.1.1.tar.gz:
Publisher:
publish-pypi.yml on openguardrails/openguardrails
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
openguardrails_instrumentation_hermes-0.1.1.tar.gz -
Subject digest:
3024fe6b8166ce7f6b5182491ee77151f9acf5093a57f9745be7f758bb9836c3 - Sigstore transparency entry: 2216592534
- Sigstore integration time:
-
Permalink:
openguardrails/openguardrails@d76634b5843ae98e167400d99786790e78bb2f6d -
Branch / Tag:
refs/tags/hermes-v0.1.1 - Owner: https://github.com/openguardrails
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish-pypi.yml@d76634b5843ae98e167400d99786790e78bb2f6d -
Trigger Event:
push
-
Statement type:
File details
Details for the file openguardrails_instrumentation_hermes-0.1.1-py3-none-any.whl.
File metadata
- Download URL: openguardrails_instrumentation_hermes-0.1.1-py3-none-any.whl
- Upload date:
- Size: 21.5 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/6.1.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
11a63ac14d3e2996c457647402ca64fc4af2c5d37cb20418c7ee884735ecec86
|
|
| MD5 |
e5d698b6f76de85b9c9e288ebcba3f66
|
|
| BLAKE2b-256 |
ef7fb8708c5cff82106471fbcec06e934024f45533ee88d56156ec9b5910af84
|
Provenance
The following attestation bundles were made for openguardrails_instrumentation_hermes-0.1.1-py3-none-any.whl:
Publisher:
publish-pypi.yml on openguardrails/openguardrails
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
openguardrails_instrumentation_hermes-0.1.1-py3-none-any.whl -
Subject digest:
11a63ac14d3e2996c457647402ca64fc4af2c5d37cb20418c7ee884735ecec86 - Sigstore transparency entry: 2216592555
- Sigstore integration time:
-
Permalink:
openguardrails/openguardrails@d76634b5843ae98e167400d99786790e78bb2f6d -
Branch / Tag:
refs/tags/hermes-v0.1.1 - Owner: https://github.com/openguardrails
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish-pypi.yml@d76634b5843ae98e167400d99786790e78bb2f6d -
Trigger Event:
push
-
Statement type: