aquaman-hermes
Credential isolation for the Hermes agent host - using the vault you already have. API keys live in your existing backend (Keychain, 1Password, HashiCorp Vault, Bitwarden, KeePassXC, systemd-creds, or encrypted-file) and are injected by the aquaman proxy. They never enter the Hermes process, and you never copy them into a new store.
This is the optional, in-session "sugar" layer. The actual isolation is done by
aquaman-proxy: it runs an opt-in loopback listener and Hermes is pointed at it via
its native ANTHROPIC_BASE_URL / OPENAI_BASE_URL env vars (written to
~/.hermes/.env) plus a placeholder api_key that the proxy strips and replaces with
the real credential. This plugin adds:
/aquaman-status: slash command showing proxy reachability + wiring.aquaman_status: an agent-facing tool with the same info.on_session_start: a one-shot health probe that warns if the proxy is down.aquamansecret source (Hermes ≥ 0.18.1): resolves project/tool secrets (GitHub tokens, database URLs, anything undersecrets.aquaman.env) from your vault at startup, through the proxy's token-gated broker. See below.
How it works
Hermes process aquaman-proxy (separate process)
┌────────────────────────┐ ┌────────────────────────────────┐
│ ANTHROPIC_BASE_URL = │── HTTP ────▶│ 127.0.0.1:8585 loopback │
│ http://127.0.0.1:8585 │ (loopback, │ • validates loopback token │
│ /anthropic │ token- │ • injects real key from vault │
│ ANTHROPIC_API_KEY = │ gated) │ • forwards to api.anthropic │
│ <loopback token> │◀────────────│ • writes hash-chained audit │
│ NO real credentials │ └────────────────────────────────┘
└────────────────────────┘
Install
You need the proxy (aquaman-proxy, from npm) and this plugin (from PyPI):
# 1. Proxy + vault (Node)
npm install -g aquaman-proxy
aquaman setup # pick a backend, store keys
aquaman credentials add anthropic api_key sk-ant-...
# 2. This plugin (Python)
pip install aquaman-hermes # or: uv tool install aquaman-hermes
aquaman-hermes install # drops the plugin into ~/.hermes/plugins/aquaman/
hermes plugins enable aquaman # add to plugins.enabled
# 3. Wire Hermes at the proxy + start it
aquaman hermes setup # writes ~/.hermes/.env, enables the loopback listener
aquaman daemon & # start the proxy
# 4. Verify
aquaman hermes doctor # deep diagnostic (proxy side)
hermes # then run: /aquaman-status
aquaman-hermes install honors HERMES_HOME (the same var the Hermes CLI uses to
relocate its config dir); it defaults to ~/.hermes.
Transport and access control
Hermes reaches the proxy over the token-gated loopback listener 127.0.0.1:<port>, because Hermes builds its own HTTP client and cannot dial a Unix socket. Since aquaman v0.15.0 OpenClaw's model traffic uses the same listener, for the same reason; coding agents still use the socket ~/.aquaman/proxy.sock (0600).
The token is a capability to reach the local proxy, not a credential: generated per install, stored in ~/.aquaman/config.yaml (0600) and in the managed block of ~/.hermes/.env, and stripped by the proxy before your real key is injected. Any local process can reach a loopback port, including other users, where the socket's 0600 shuts them out. The token is the gate there, and the listener stays off until you run aquaman hermes setup.
Project secrets (secret source, Hermes ≥ 0.18.1)
LLM keys are only half the problem. Agents also need GitHub tokens, database URLs,
and other project secrets that usually end up in a plaintext .env. On Hermes ≥
0.18.1 this plugin registers an aquaman secret source so those come from your
vault instead. Bind them in ~/.hermes/config.yaml:
secrets:
aquaman:
enabled: true
env:
GITHUB_TOKEN: aquaman://github/token
DATABASE_URL: aquaman://supabase/db_url
Then declare the same refs to the proxy. Since aquaman 0.15 the daemon hands out only refs you have declared, so a binding in Hermes' config alone is refused:
aquaman broker allow aquaman://github/token aquaman://supabase/db_url
aquaman hermes doctor # flags any binding that isn't declared yet
At startup the source resolves each binding through the proxy's token-gated loopback broker (per-read, hash-chain audited) and hands the values to Hermes' secret orchestrator. Notes on the security model:
- LLM provider keys are refused, by this source and by the proxy itself.
ANTHROPIC_API_KEY/OPENAI_API_KEYbindings are rejected with a warning, and the proxy never hands out anthropic/openai keys over the loopback listener even if they are declared. Those stay on the loopback proxy path, where the real key never enters the Hermes process at all. - Project secrets resolved this way do live in Hermes' process env (that's what a
Hermes secret source is). What you gain over a
.envline: vault-at-rest storage, per-read tamper-evident audit, instant rotation, and no plaintext files on disk. - Fail-open by design: if the proxy is down, Hermes still starts (with a warning).
- One bad ref never blocks the others; errors/warnings never contain the token.
On Hermes 0.19+ the source participates in the full orchestrator: mapped-vs-bulk
precedence (an explicit env: binding outranks a bulk project dump), first-claim-wins
across sources with conflict warnings, and (from Aquaman Proxy) provenance labels.
Order it against other sources with secrets.sources: [aquaman, bitwarden]. The source
passes Hermes' own secret-source conformance kit (see tests/test_conformance.py).
Timing caveat: plugin discovery runs later in Hermes' startup than the first
load_hermes_dotenv() call, so a plugin-provided source is not consulted by the very
first env load of the process that discovers it. It is consulted by every subsequently
spawned Hermes process (gateway children, cron sessions, subagents). Bundled sources
cover first-process bootstrap; that's a Hermes design property, not an aquaman gap.
Uninstall
hermes plugins disable aquaman
aquaman-hermes uninstall
Notes
- The status/command/hook surface holds no credentials. It only reads the provider
base-URL env vars and probes the proxy's token-exempt
/_healthendpoint. The secret source transits credentials only while handing them to Hermes' orchestrator. - It depends only on the Python standard library.
- LLM providers wired via base-URL: Anthropic + OpenAI. Channels are out of scope for the Hermes path (no base-URL lever); project secrets go through the secret source.
- Hermes >=0.17 "managed scope": a root-owned
/etc/hermes/.envoverrides~/.hermes/.env. If an admin pins theANTHROPIC_*/OPENAI_*vars there, the proxy is bypassed.aquaman hermes doctordetects and flags this. - With
gateway.multiplex_profilesenabled (off by default), env is scoped per profile: add the aquaman block to each profile's env file. - Hermes 0.18's cron exfil guard refuses cron jobs that pair a named provider with
an off-host
base_urloverride; normal jobs inheriting the session runtime (the env vars aquaman writes) are unaffected.
Release files for aquaman-hermes 0.15.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| aquaman_hermes-0.15.0.tar.gz | 25.1 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| aquaman_hermes-0.15.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 40.1 kB
Release files / aquaman_hermes-0.15.0.tar.gz
| Download URL | aquaman_hermes-0.15.0.tar.gz |
|---|---|
| Size | 25.1 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
cd498625307f02a31e7d390d0c38f90be0133ffc2cf52156b8b271e36ee525e3
|
|
BLAKE2b-256 checksum How to use checksums |
bf816b47bb191436128925885f53302b7827d0d70d4506e06c457afca7739636
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 20, 2026.
Transparency logRelease files / aquaman_hermes-0.15.0-py3-none-any.whl
| Download URL | aquaman_hermes-0.15.0-py3-none-any.whl |
|---|---|
| Size | 14.9 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
4782a4c84c87ec19669596cc341373e9e186bd2806db4b215390aecd7b483ec5
|
|
BLAKE2b-256 checksum How to use checksums |
5bdd3a7304c989934e7b1caabb8f5845d5785a1eb6b20d5668ca11eaa054dff3
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 20, 2026.
Transparency log