Current identity-routing guidance — 2026-09-15: This notebook preserves historical setup notes. Its unprofiled launch/resume examples and session-only identity explanation are superseded for NIGHTINGALE seats. Use
/home/hatch/workspace/bin/hermes-seat mit chator/home/hatch/workspace/bin/hermes-seat cornell chat, and resume only a session belonging to that profile. Current standing handles:/home/hatch/workspace/agents/hermes-seats.json. Current operating guide:/home/hatch/workspace/agents/HERMES_PROFILES.md. Separate sessions alone do not isolate persistent memory; separate profiles do.
A running log of operating Hermes on this machine — every command, config, and "why", written so it can be followed step-by-step to set up Hermes on any other machine later.
Machine: Ubuntu 24.04, Python 3.12.3, Node v24.20.0
Steps:
python3 -m venv ~/workspace/venvs/hermes
~/workspace/venvs/hermes/bin/pip install hermes-agent
Result: Hermes Agent v0.19.0 (2026.7.20)
Why a venv: it keeps Hermes's Python packages isolated from the system
Python, and everything lives under ~/workspace, which survives VM restarts.
(~/.venvs would work too; ~/workspace/venvs/ keeps all agent envs in one
visible place.)
Key paths:
- Binary: ~/workspace/venvs/hermes/bin/hermes
- Python packages: ~/workspace/venvs/hermes/lib/python3.12/site-packages
- Hermes's own data dir (created on first run): ~/.hermes/
Not yet done: no model provider / API key configured, so hermes chat
can't actually talk to a model yet. That's the next step (likely OpenRouter).
hermes chat -q "your prompt here" # one-shot, non-interactive
hermes chat --query-file - < prompt.txt # prompt from stdin, verbatim
hermes chat --resume <session_id> -q "..." # continue a persistent session
hermes chat --provider openrouter -q "..." # force OpenRouter
hermes chat -Q -q "..." # quiet: script-friendly output
hermes --resume latest # reopen the most recent session
The --resume pattern is the whole "persistent agent" trick: one long-lived
session that keeps memory across calls, driven from the shell.
Walk through ~/.hermes/config.yaml once the first run creates it.
What happened: AK created a 1Password service account (a special
login meant for software, not humans) in the 1Password web app under
Developer → Service accounts, scoped to a dedicated vault, and pasted the
token into a secure entry page. The token now lives in the Secure Vault as
the custom.1password connector. I also scaffolded a 1password skill at
~/workspace/skills/1password/ (built with
/opt/hatch/skills/skill-creator/bin/scaffold-connector-skill --provider 1password).
The wrinkle (verified, not guessed): the vault hands out credentials
only inside web requests — it swaps a placeholder (hsurr:...) for the
real secret as the request leaves the machine. But the op command-line
tool needs the actual token text in its OP_SERVICE_ACCOUNT_TOKEN
environment variable, and it checks the token's format before doing
anything on the network. I tested it: op rejected the placeholder with
failed to parseToken, format is invalid. And 1Password publishes no
public web API that accepts service-account tokens (the only 1Password
HTTP API belongs to 1Password Connect, a separate self-hosted server
with its own tokens).
What this means in plain terms: the token is safely stored, but I
can't plug it into op from inside the vault's rules. The loop closes
when the token reaches this machine's environment through a channel AK
controls — e.g. the planned Ansible pull setup, which can deploy the
token as an environment variable. Long-term alternative: run a 1Password
Connect server on AK's own infrastructure; its web API does fit the
vault's pattern (and a service-account token can bootstrap the Connect
server itself).
Commands used (all safe — no secret ever printed):
/opt/hatch/skills/skill-creator/bin/scaffold-connector-skill --provider 1password
# created ~/workspace/skills/1password/SKILL.md
python3 -c "... dynamic_credential_entry('custom.1password', 'access_token') ..."
# confirmed the vault returns a surrogate placeholder, not the secret
OP_SERVICE_ACCOUNT_TOKEN="<surrogate>" ~/workspace/bin/op vault list
# -> [ERROR] failed to DecodeSACredentials: failed to parseToken, format is invalid
# (proves the CLI validates locally; the placeholder never leaves the machine)
Skill layout: ~/workspace/skills/1password/SKILL.md documents the
gap honestly; bin/op_api.py is a minimal authenticated-HTTP helper for
the connector's native pattern (useful if we ever point it at a Connect
server).
Decision (AK, 2026-09-14): no API keys, no OpenRouter — both agents
authenticate with OpenAI OAuth. Model: gpt-5.6-terra, thinking high.
PATH fix: ~/workspace/venvs/hermes/bin was appended to ~/.bashrc
(2026-09-14). Note: Muse's own exec sessions run with a clean environment
(bash --norc --noprofile), so every command below needs
export PATH="$HOME/workspace/venvs/hermes/bin:$PATH" explicitly.
The proxy bug (real, diagnosed): the first hermes auth add --type oauth
openai-codex --no-browser attempt died with
httpx.InvalidURL: Invalid port: ':1]'. Root cause: httpx 0.28.1's
get_environment_proxies() turns every no_proxy entry into a
URLPattern, and this machine's no_proxy contains bracketed IPv6
addresses ([::1], [fd8b:...]), which produce unparsable patterns like
all://*[::1]. Verified by constructing URLPattern per key in the venv
Python — exactly the IPv6-derived keys failed.
Workaround: run Hermes with the IPv6 entries stripped from no_proxy:
export NO_PROXY="localhost,127.0.0.1,198.19.0.1,198.19.0.2"
export no_proxy="localhost,127.0.0.1,198.19.0.1,198.19.0.2"
Shell gotcha that cost a retry: export A="x" B="$A" expands $A before
the assignment, so B gets the OLD value. Set them in two separate
export statements. (httpx reads lowercase no_proxy first, so the
broken one wins if you get this wrong.)
Auth flow (device code, headless-safe):
export PATH="$HOME/workspace/venvs/hermes/bin:$PATH"
export NO_PROXY="localhost,127.0.0.1,198.19.0.1,198.19.0.2"
export no_proxy="$NO_PROXY"
script -qec "hermes auth add --type oauth openai-codex --no-browser" /dev/null
# -> prints https://auth.openai.com/codex/device + a code like CB32-BI7ZS
# -> user opens the URL on their phone, enters the code, approves
# -> "Added openai-codex OAuth credential #1"
script supplies the pseudo-terminal the login flow demands. The
--no-browser flag keeps it from trying to open a browser on the VM.
Verify (no secrets printed):
hermes auth list # shows: openai-codex (1 credentials): #1 ... oauth device_code
hermes doctor # "✓ OpenAI Codex auth (logged in)"
Model + provider selection (non-interactive): hermes model is
interactive-only, but the config file takes the same values. The schema is
model: {provider, default}:
hermes config set model.provider openai-codex
hermes config set model.default gpt-5.6-terra
hermes config set agent.reasoning_effort high
Resulting ~/.hermes/config.yaml:
model:
provider: openai-codex
default: gpt-5.6-terra
agent:
reasoning_effort: high
Per-invocation overrides also exist: hermes -m <model> and the
HERMES_INFERENCE_MODEL / HERMES_INFERENCE_PROVIDER env vars.
What models does this OAuth login actually unlock? The openai-codex
provider talks to the Codex backend (chatgpt.com/backend-api/codex/models),
whose model list differs from OpenClaw's catalog. Queried live with the
stored OAuth token (transient, in-memory only — never printed or saved):
gpt-6-astra, gpt-reserve, gpt-5.6-sol, gpt-5.6-terra, gpt-5.6-luna,
gpt-5.5, gpt-5.3-codex-spark, codex-auto-review. The 5.6 family
(sol/terra/luna) exists here — AK's gpt-5.6-terra pick is valid on
both agents.
End-to-end test (2026-09-14):
hermes -z "Reply with exactly: HERMES-OK" # -> HERMES-OK (~8s)
Key files: ~/.hermes/auth.json (OAuth tokens, 600 perms — never copy
these anywhere), ~/.hermes/config.yaml (model/provider/reasoning),
~/.hermes/sessions/ (persistent sessions for --resume).
Shared record of every Hermes run — prompt, what it did, outcome. (Starts 2026-09-14; earlier history: none, provider was just configured.)
| Date | Prompt | Actions | Outcome |
|---|---|---|---|
| 2026-09-14 | Reply with exactly: HERMES-OK |
One-shot -z turn via openai-codex / gpt-5.6-terra |
OK — HERMES-OK in ~8s |