Files
hermes-skills/hermes-api-server/SKILL.md
Hermes Agent b0d790be34 Add all 104 active skills from all 16 Hermes profiles
12 unversioned skills now versioned at 1.0.0:
agent-communication, ascii-video, external-reasoning-augmentation,
jotty-notes-api, minecraft-modpack-server, obsidian, pokemon-player,
powerpoint, social-search, songwriting-and-ai-music,
workspace-context-organization, youtube-content

Total repo: 141 skills across all profile scopes
2026-07-04 11:44:04 -05:00

7.9 KiB

name, description, version, author
name description version author
hermes-api-server Expose a Hermes profile as an OpenAI-compatible API server for Open WebUI and other consumers. 1.0.0 Hermes Agent

Hermes API Server

Expose a Hermes profile as an OpenAI-compatible /v1/chat/completions and /v1/models endpoint. Used to connect Open WebUI, chatbots, or any OpenAI-compatible client to a Hermes profile.

Quick Start

# Install as user systemd service (autostart on login, survives logout)
# The -p flag is REQUIRED for non-default profiles
hermes -p <profile> gateway install --start-now --start-on-login

# Verify
curl -s http://127.0.0.1:8653/health
# Expected: {"status":"ok","platform":"hermes-agent","version":"X.Y.Z"}

After install, always set the model name so Open WebUI shows a recognizable label:

echo 'API_SERVER_MODEL_NAME=Hermes Agent (<profile>)' >> ~/.hermes/profiles/<profile>/.env
systemctl --user restart hermes-gateway-<profile>

If API_SERVER_MODEL_NAME is not set, the gateway defaults to hermes-agent (default profile) or the bare profile name — neither is a good label in Open WebUI's model dropdown.

Cross-Host Access (Critical)

The gateway defaults to 127.0.0.1 — only localhost can reach it. If the consumer is on a different host (e.g., Open WebUI on 10.0.0.204, Hermes on 10.0.0.42), you MUST bind to 0.0.0.0:

# Add to the profile's .env
echo "API_SERVER_HOST=0.0.0.0" >> ~/.hermes/profiles/<profile>/.env

# Restart
systemctl --user restart hermes-gateway-<profile>

Verify the bind changed:

ss -tlnp | grep 8653
# Should show: LISTEN 0 128 0.0.0.0:8653

End-to-End Verification

From the consumer host, test with the real API key:

# Get the key
KEY=$(grep '^API_SERVER_KEY=' ~/.hermes/profiles/<profile>/.env | cut -d= -f2-)

# Test from consumer host
ssh user@consumer-host "curl -s -H 'Authorization: Bearer $KEY' http://<hermes-ip>:8653/v1/models"

Expected: HTTP 200 with {"object":"list","data":[{"id":"Hermes Agent (<profile>)",...}]}.

The id field is the model name that will appear in Open WebUI's External Models list.

Key Locations

Item Path
API key ~/.hermes/profiles/<profile>/.envAPI_SERVER_KEY
Port ~/.hermes/profiles/<profile>/.envAPI_SERVER_PORT (default 8653)
Bind address ~/.hermes/profiles/<profile>/.envAPI_SERVER_HOST (default 127.0.0.1)
Model name ~/.hermes/profiles/<profile>/.envAPI_SERVER_MODEL_NAME
Service unit systemctl --user status hermes-gateway-<profile>

Reference Files

  • references/openwebui-multi-user.md — Open WebUI multi-user setup: groups, model presets, visibility, kid guardrails, setup order.

Pitfalls

  • Default 127.0.0.1 bind blocks cross-host access. Always check ss -tlnp | grep 8653 — if it shows 127.0.0.1:8653, the consumer on another host cannot reach it. Add API_SERVER_HOST=0.0.0.0 and restart.
  • Linger required for logout survival. hermes gateway install enables linger automatically, but if the service dies on logout, run loginctl enable-linger $USER.
  • API key is in .env, not config.yaml. The API_SERVER_KEY is auto-generated and stored in the profile's .env file. Do not look for it in config.yaml.
  • Model name matters. The API_SERVER_MODEL_NAME value is what Open WebUI displays. Set it to something recognizable like Hermes Agent (open1). If unset, the gateway defaults to hermes-agent (default profile) or the bare profile name — neither is a good label in Open WebUI's model dropdown. Set it immediately after gateway install.
  • Port conflicts. If 8653 is taken, set API_SERVER_PORT to another port in the profile's .env and restart.
  • Open WebUI model id is the id field from /v1/models, not the profile name. Always verify with curl -H "Authorization: Bearer $KEY" http://<ip>:8653/v1/models and use the exact id value when creating model presets in Open WebUI. Guessing hermes-agent or the profile name will break preset creation.
  • Kokoro TTS voices use af_ prefix. The voice list from /v1/audio/voices returns names like af_nova, af_sky, af_onyx — not nova, sky, onyx. Open WebUI's TTS voice field must match exactly. Always query the live voice list before setting TTS in model presets.
  • The patch tool refuses to edit .env files. Use shell append (echo 'KEY=value' >> path/.env) or write_file instead. This is a security guard — .env files contain secrets.
  • Single profile doesn't isolate long-term memory. If different users need separate persistent memory (e.g., Zoe's school memories vs. Rob's operational memories), one profile isn't enough — Hindsight banks are per-profile via HINDSIGHT_BANK_ID. Create a second profile with its own bank. See references/openwebui-multi-user.md → "Two-Profile Memory Isolation."
  • Direct-DB editing of Open WebUI is a dead end for the agent. The Open WebUI SQLite DB lives at /root/.open-webui/webui.db on the WebUI host, owned by root. The agent cannot reach it: root SSH is typically disabled, and sudo -S (password via stdin) is blocked by the terminal guard as a brute-force vector. The agent can pre-flight backends and verify from the Hermes host, but WebUI panel config (connections, groups, users, presets) must be done by the operator in the browser. Do not attempt to SSH in and edit the DB — it wastes turns.

Pre-Flight Verification (Do Before Handing Off to Operator)

When setting up Open WebUI, the agent can run the exact API calls the WebUI will make BEFORE the operator configures the WebUI panel. This proves backends work so WebUI config failures are isolated to the WebUI panel, not the backends.

Pattern: For each backend the WebUI will call (TTS, STT, LLM), run the exact curl command with the exact params the WebUI panel will use. Save sample output files so the operator can listen/verify quality.

# TTS pre-flight — exact params the WebUI Audio panel will use
curl -s -X POST -H "Content-Type: application/json" \
  -d '{"model":"kokoro","input":"Test message.","voice":"af_heart"}' \
  http://<tts-host>:8880/v1/audio/speech -o /tmp/tts_sample.mp3

# STT pre-flight — real speech input
espeak-ng -w /tmp/speech.wav "Hello this is a test"
curl -s -X POST -F "file=@/tmp/speech.wav" -F "model_name=whisper-1" \
  http://<stt-host>:9000/v1/audio/transcriptions

# LLM pre-flight — full chat-completions round trip
curl -s -H "Authorization: Bearer $KEY" \
  -d '{"model":"Hermes Agent (<profile>)","messages":[{"role":"user","content":"Reply: TTS_OK"}]}' \
  http://127.0.0.1:8653/v1/chat/completions

Why this matters: If the WebUI verify step fails after the operator pastes config, the problem is in the WebUI panel (wrong URL, wrong model name, missing field) — NOT in the backends. The backends are proven. This saves debugging cycles.

Verification

End-to-end from consumer host

# Get the key
KEY=$(grep '^API_SERVER_KEY=' ~/.hermes/profiles/<profile>/.env | cut -d= -f2-)

# Test from consumer host
ssh user@consumer-host "curl -s -H 'Authorization: Bearer $KEY' http://<hermes-ip>:8653/v1/models"

Expected: HTTP 200 with {"object":"list","data":[{"id":"Hermes Agent (<profile>)",...}]}.

Peer Hermes read-only validation

For complex setup plans (checklists, configs), spawn a peer Hermes to validate before executing:

hermes chat -q -p <profile> -t safe,file -s hermes-agent

Then instruct the peer: "Read /path/to/checklist.md. Validate every step. Report BLOCKERs, IMPORTANT issues, and NICE-TO-HAVE improvements. Do NOT execute anything — read-only review." The peer returns a structured report. Apply IMPORTANT fixes before proceeding with execution.

Pitfall: -t safe alone strips file and terminal tools — the peer can't read the checklist. Use -t safe,file to add read-only file access. The peer will still lack terminal (no execution risk) but can read and analyze files.