9.8 KiB
Agent Pairing Guide — Workspace ↔ Hermes Agent
Audience: AI agents helping users set up Hermes Workspace. Run these steps in order. Each step has a verification command. Do not skip ahead, and do not start a second gateway until the current one fails the checks below.
Architecture (30-second version)
┌─────────────────┐ HTTP :8642 ┌──────────────────┐
│ Claude Gateway │◄──────────────────────►│ Hermes Workspace │
│ (Python, FastAPI)│ /health, /v1/chat, │ (Node, Vite) │
│ hermes gateway │ /api/sessions, etc. │ pnpm dev │
│ run │ │ port 3000 │
└─────────────────┘ └──────────────────┘
Workspace talks to Hermes Agent over HTTP. No WebSocket. No magic.
A fully paired local setup has two services:
hermes gateway runon :8642 for chat, models, and streaminghermes dashboardon :9119 for sessions, skills, config, and jobs
If curl http://127.0.0.1:8642/health and curl http://127.0.0.1:9119/ both
return successfully, they can pair.
Step 1 — Is hermes-agent installed?
hermes --version
Pass: prints Hermes Agent vX.Y.Z.
Fail: command not found.
Fix (if hermes-agent not installed)
# Official Nous installer — works on macOS, Linux, WSL
curl -fsSL https://raw.githubusercontent.com/NousResearch/hermes-agent/main/scripts/install.sh | bash
After install, restart your shell or run:
export PATH="$HOME/.local/bin:$PATH"
hermes --version
Step 2 — Is the API server enabled?
The gateway exposes an HTTP API on port 8642, but only if API_SERVER_ENABLED=true
is set in the Hermes env file.
# Find the env file
HERMES_ENV="$(hermes config env-path 2>/dev/null || echo "$HOME/.hermes/.env")"
echo "Hermes env file: $HERMES_ENV"
# Check for the key
grep -i "API_SERVER" "$HERMES_ENV" 2>/dev/null || echo "NO API_SERVER KEYS FOUND"
Pass: output includes API_SERVER_ENABLED=true (with underscores).
Common failure — wrong env var names:
# ❌ WRONG (missing underscores — gateway silently ignores these)
APISERVERENABLED=true
APISERVERHOST=0.0.0.0
# ✅ CORRECT
API_SERVER_ENABLED=true
API_SERVER_HOST=127.0.0.1
Critical: env var names MUST have underscores.
APISERVERENABLED≠API_SERVER_ENABLED. The gateway reads exact names viaos.getenv(). Typos are silently ignored — no warning, no error, just no API server.
Fix
HERMES_ENV="$(hermes config env-path 2>/dev/null || echo "$HOME/.hermes/.env")"
mkdir -p "$(dirname "$HERMES_ENV")"
# Remove any typo'd versions first
sed -i.bak '/^APISERVERENABLED/d; /^APISERVERHOST/d; /^APISERVERKEY/d; /^APISERVERPORT/d' "$HERMES_ENV" 2>/dev/null || true
# Write correct keys (idempotent — updates existing or appends)
grep -q '^API_SERVER_ENABLED=' "$HERMES_ENV" 2>/dev/null && \
sed -i.bak 's/^API_SERVER_ENABLED=.*/API_SERVER_ENABLED=true/' "$HERMES_ENV" || \
echo 'API_SERVER_ENABLED=true' >> "$HERMES_ENV"
Do NOT set API_SERVER_HOST=0.0.0.0 unless the user explicitly wants
network access AND sets API_SERVER_KEY=<some-secret>. The gateway refuses
to bind non-loopback without a key (silent failure). Default 127.0.0.1 is
correct for local Workspace.
Step 3 — Is the gateway process running?
pgrep -af "hermes.*gateway" || echo "NOT RUNNING"
Pass: shows a hermes gateway run (or similar) process.
Fail: nothing.
Fix
# Start in foreground (recommended for debugging — you see all output)
hermes gateway run
# OR if using systemd
hermes gateway install # creates the service
systemctl --user start claude-gateway
First run: Hermes may prompt for initial setup (provider, model). Complete the interactive setup before continuing.
Step 4 — Is port 8642 bound?
# Linux / WSL
ss -tlnp | grep 8642 || echo "PORT NOT BOUND"
# macOS
lsof -iTCP:8642 -sTCP:LISTEN || echo "PORT NOT BOUND"
# Universal fallback
curl -sf http://127.0.0.1:8642/health && echo "OK" || echo "NOT REACHABLE"
Pass: port is bound AND curl /health returns {"status": "ok", "platform": "hermes-agent"}.
Fail — gateway running but port not bound: API server didn't start. Go back to Step 2 and verify the env vars have underscores.
Fail — port bound by something else:
# Find what's on the port
lsof -i :8642 # macOS
ss -tlnp | grep 8642 # Linux
# Kill the stale process, then restart gateway
Step 4b — Is the dashboard running on 9119?
curl -sf http://127.0.0.1:9119/ && echo "DASHBOARD OK" || echo "DASHBOARD NOT REACHABLE"
Pass: returns HTTP 200 (HTML or JSON is fine).
Fix
hermes dashboard
Step 5 — Is Workspace pointed at the gateway?
# In the hermes-workspace directory
cat .env | grep HERMES_API_URL
Pass: HERMES_API_URL=http://127.0.0.1:8642
Also set the dashboard URL:
grep HERMES_DASHBOARD_URL .env
Pass: HERMES_DASHBOARD_URL=http://127.0.0.1:9119
Fail or missing:
# In the hermes-workspace directory
echo 'HERMES_API_URL=http://127.0.0.1:8642' >> .env
echo 'HERMES_DASHBOARD_URL=http://127.0.0.1:9119' >> .env
If .env doesn't exist:
cp .env.example .env
# Then set HERMES_API_URL as above
Step 6 — Start Workspace and verify pairing
cd ~/hermes-workspace # or wherever it's installed
pnpm dev
Look for this in the startup output:
[claude-api] Configured API: http://127.0.0.1:8642
[gateway] gateway=http://127.0.0.1:8642 ... mode=enhanced-fork core=[health, chatCompletions, models, streaming]
mode=enhanced-fork = paired successfully. Sessions, memory, skills all
available.
Critical verification before starting another gateway
curl -sf http://127.0.0.1:8642/health
curl -sf http://127.0.0.1:3000/api/sessions | jq '.sessions | length' 2>/dev/null || curl -sf http://127.0.0.1:3000/api/sessions
If /api/sessions returns sessions (or an empty array) the pairing is alive.
Do not start another gateway just because the UI still says Offline —
refresh or reprobe the workspace UI first.
mode=disconnected = pairing failed. Go back to Step 4.
Step 7 — Verify in browser
Open http://localhost:3000 (or whatever port Vite reports).
- Full UI with chat = success.
- "Connect Backend" / "Skip setup" onboarding screen = gateway not reachable from the Vite SSR server. Re-check Steps 4–5.
- 500 error / blank page = Vite build issue, not a pairing problem. Check terminal for build errors.
Quick-fix cheat sheet (copy-paste block)
For users who just want it to work — run this entire block:
# 1. Find Hermes env
HERMES_ENV="$(hermes config env-path 2>/dev/null || echo "$HOME/.hermes/.env")"
mkdir -p "$(dirname "$HERMES_ENV")"
# 2. Enable API server (idempotent)
grep -q '^API_SERVER_ENABLED=' "$HERMES_ENV" 2>/dev/null && \
sed -i.bak 's/^API_SERVER_ENABLED=.*/API_SERVER_ENABLED=true/' "$HERMES_ENV" || \
echo 'API_SERVER_ENABLED=true' >> "$HERMES_ENV"
# 3. Clean up common typos
sed -i.bak '/^APISERVERENABLED/d; /^APISERVERHOST/d' "$CLAUDE_ENV" 2>/dev/null || true
# 4. Restart gateway
hermes gateway stop 2>/dev/null; sleep 2; hermes gateway run &
sleep 8
# 5. Verify
curl -sf http://127.0.0.1:8642/health && echo "✅ Gateway API is up" || echo "❌ Gateway API not reachable"
# 6. Set workspace env
cd ~/hermes-workspace 2>/dev/null || cd "$(find ~ -maxdepth 2 -name hermes-workspace -type d | head -1)"
grep -q '^HERMES_API_URL=' .env 2>/dev/null && \
sed -i.bak 's|^HERMES_API_URL=.*|HERMES_API_URL=http://127.0.0.1:8642|' .env || \
echo 'HERMES_API_URL=http://127.0.0.1:8642' >> .env
echo "✅ Done. Run: pnpm dev"
Platform-specific notes
WSL (Windows Subsystem for Linux)
- Python cold-start is slower on WSL due to filesystem I/O overhead. The gateway may take 10–15 seconds to bind port 8642.
- If Workspace's health check times out before the gateway is ready,
start the gateway separately first (
hermes gateway run), wait for the port to bind, then start Workspace in a second terminal. - Use
127.0.0.1, notlocalhost— WSL2 sometimes resolveslocalhostto the Windows host instead of the WSL VM.
macOS
- No special considerations. Default setup works.
- If using Homebrew Python, ensure
claudeis on PATH:export PATH="$HOME/.local/bin:$PATH"
Linux (native)
- systemd users:
hermes gateway installcreates a user service. Check status withsystemctl --user status claude-gateway. - If using a different
$HOMEfor the systemd service (e.g. running as a different user), the.envfile location changes. Useclaude config env-pathto find it.
Still broken?
Collect this diagnostic bundle and share it:
echo "=== claude version ===" && claude --version 2>&1
echo "=== claude env path ===" && claude config env-path 2>&1
echo "=== claude env (redacted) ===" && grep -E "^(API_SERVER|CLAUDE_)" "$(claude config env-path 2>/dev/null || echo ~/.hermes/.env)" 2>&1
echo "=== gateway process ===" && pgrep -af "claude.*gateway" 2>&1 || echo "not running"
echo "=== port 8642 ===" && (ss -tlnp 2>/dev/null || lsof -iTCP:8642 -sTCP:LISTEN 2>/dev/null) | grep 8642 || echo "not bound"
echo "=== health check ===" && curl -sf http://127.0.0.1:8642/health 2>&1 || echo "not reachable"
echo "=== workspace .env ===" && grep CLAUDE ~/hermes-workspace/.env 2>&1 || echo "no .env"
echo "=== OS ===" && uname -a
echo "=== Node ===" && node --version
echo "=== Python ===" && python3 --version 2>&1
This gives any human or agent enough context to diagnose the issue in one read.