hermes-agent/website/docs/user-guide/secrets/index.md
Taylor H. Perkins 5c4c0e9d9b feat(secrets): add 1Password (op://) secret source
Resolve provider credentials from 1Password op://vault/item/field references
at startup via the official `op` CLI, alongside the existing Bitwarden source.
Users map env-var names to references in secrets.onepassword.env; after .env
loads, each is resolved with `op read` and injected into os.environ. Auth is
whatever `op` already uses (service-account token or desktop/interactive
session) — Hermes never authenticates or installs `op` itself.

Startup-safe and fail-open: a missing binary, expired auth, a bad reference,
or an empty value each warn and fall back to existing credentials, never
blocking startup. Successful, complete pulls are cached in-process and on disk
(<hermes_home>/cache/op_cache.json, 0600) via the shared DiskCache; only
secret values are stored, never the token (auth is fingerprinted into the
key). Adds `hermes secrets onepassword {setup,status,set,remove,sync,disable}`
(aliases op/1password), config defaults, the cli-config example, docs, and
hermetic tests.

Hardening applied across both backends in env_loader: each source runs in its
own guard, config sections are coerced to dict, and cache_ttl_seconds is
coerced defensively — so a malformed secrets: section can't abort startup.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-06 04:58:07 -07:00

2.7 KiB

Secrets

Hermes can pull API keys from external secret managers at process startup instead of storing them in ~/.hermes/.env. The bootstrap token for the secret manager lives in .env; every other provider key (OpenAI, Anthropic, OpenRouter, etc.) can stay in the manager and rotate centrally.

Supported:

  • Bitwarden Secrets Managerbws CLI, lazy-installed, free tier works.
  • 1Passwordop:// references via the official op CLI; service-account or desktop session auth.

Multiple sources at once

You can enable more than one secret source at the same time — for example a team Bitwarden project alongside a personal vault plugin. Sources compose per env var with a deterministic precedence ladder:

  1. Your .env / shell wins by default. A source only replaces a pre-existing value when its own override_existing: true is set (Bitwarden defaults to true so central rotation works).
  2. Mapped sources beat bulk sources. A source where you explicitly bind env vars to references (an env: map) outranks a source that injects a whole project of secrets implicitly, regardless of ordering.
  3. First source wins. Within the same shape, the order of the optional secrets.sources list (or registration order) decides. Later claims on an already-claimed var are skipped — with a startup warning, never silently.

override_existing never lets one source overwrite a var another source already claimed, and no source can ever overwrite another source's bootstrap token (e.g. BWS_ACCESS_TOKEN).

secrets:
  sources: [bitwarden]     # optional explicit ordering
  bitwarden:
    enabled: true
    project_id: "..."

Every credential injected by a source is labelled with its origin — setup flows and hermes model show (from Bitwarden) next to detected keys so you always know where a value came from.

Adding your own backend

Third-party secret managers ship as standalone plugins, not core PRs. A backend subclasses agent.secret_sources.base.SecretSource (one required method: fetch(cfg, home_path) -> FetchResult) and registers via ctx.register_secret_source(MySource()) in the plugin's register(ctx). The orchestrator owns precedence, conflict handling, timeouts, and provenance — your source only fetches. Contract rules: fetch() never raises, never prompts, and returns within its timeout budget; validate your implementation against the conformance kit in tests/secret_sources/conformance.py.

The bundled set is deliberately closed (same policy as memory providers): Bitwarden and 1Password ship in-tree. Everything else — Infisical, Proton Pass, HashiCorp Vault, AWS Secrets Manager, OS keystores — belongs in plugin repos; share them in the Nous Research Discord (#plugins-skills-and-skins).