| 2026-05-20 04-36-30 |
85,394 chars |
2026-05-20_04-36-30.md |
Cron Job: autonomous-agent-lab-v1-orchestrator
Job ID: 35127ff89556
Run Time: 2026-05-20 04:36:30
Schedule: every 15m
Prompt
[IMPORTANT: The user has invoked the "hermes-agent" skill, indicating they want you to follow its instructions. The full skill content is loaded below.]
---
name: hermes-agent
description: "Configure, extend, or contribute to Hermes Agent."
version: 2.1.0
author: Hermes Agent + Teknium
license: MIT
platforms: [linux, macos, windows]
metadata:
hermes:
tags: [hermes, setup, configuration, multi-agent, spawning, cli, gateway, development]
homepage: https://github.com/NousResearch/hermes-agent
related_skills: [claude-code, codex, opencode]
---
Hermes Agent
Hermes Agent is an open-source AI agent framework by Nous Research that runs in your terminal, messaging platforms, and IDEs. It belongs to the same category as Claude Code (Anthropic), Codex (OpenAI), and OpenClaw โ autonomous coding and task-execution agents that use tool calling to interact with your system. Hermes works with any LLM provider (OpenRouter, Anthropic, OpenAI, DeepSeek, local models, and 15+ others) and runs on Linux, macOS, and WSL.
What makes Hermes different:
- Self-improving through skills โ Hermes learns from experience by saving reusable procedures as skills. When it solves a complex problem, discovers a workflow, or gets corrected, it can persist that knowledge as a skill document that loads into future sessions. Skills accumulate over time, making the agent better at your specific tasks and environment.
- Persistent memory across sessions โ remembers who you are, your preferences, environment details, and lessons learned. Pluggable memory backends (built-in, Honcho, Mem0, and more) let you choose how memory works.
- Multi-platform gateway โ the same agent runs on Telegram, Discord, Slack, WhatsApp, Signal, Matrix, Email, and 10+ other platforms with full tool access, not just chat.
- Provider-agnostic โ swap models and providers mid-workflow without changing anything else. Credential pools rotate across multiple API keys automatically.
- Profiles โ run multiple independent Hermes instances with isolated configs, sessions, skills, and memory.
- Extensible โ plugins, MCP servers, custom tools, webhook triggers, cron scheduling, and the full Python ecosystem.
People use Hermes for software development, research, system administration, data analysis, content creation, home automation, and anything else that benefits from an AI agent with persistent context and full system access.
This skill helps you work with Hermes Agent effectively โ setting it up, configuring features, spawning additional agent instances, troubleshooting issues, finding the right commands and settings, and understanding how the system works when you need to extend or contribute to it.
Docs: https://hermes-agent.nousresearch.com/docs/
Quick Start
Install
curl -fsSL https://raw.githubusercontent.com/NousResearch/hermes-agent/main/scripts/install.sh | bash
Interactive chat (default)
hermes
Single query
hermes chat -q "What is the capital of France?"
Setup wizard
hermes setup
Change model/provider
hermes model
Check health
hermes doctor
---
CLI Reference
Global Flags
hermes [flags] [command]
--version, -V Show version
--resume, -r SESSION Resume session by ID or title
--continue, -c [NAME] Resume by name, or most recent session
--worktree, -w Isolated git worktree mode (parallel agents)
--skills, -s SKILL Preload skills (comma-separate or repeat)
--profile, -p NAME Use a named profile
--yolo Skip dangerous command approval
--pass-session-id Include session ID in system prompt
No subcommand defaults to chat.
Chat
hermes chat [flags]
-q, --query TEXT Single query, non-interactive
-m, --model MODEL Model (e.g. anthropic/claude-sonnet-4)
-t, --toolsets LIST Comma-separated toolsets
--provider PROVIDER Force provider (openrouter, anthropic, nous, etc.)
-v, --verbose Verbose output
-Q, --quiet Suppress banner, spinner, tool previews
--checkpoints Enable filesystem checkpoints (/rollback)
--source TAG Session source tag (default: cli)
Configuration
hermes setup [section] Interactive wizard (model|terminal|gateway|tools|agent)
hermes model Interactive model/provider picker
hermes config View current config
hermes config edit Open config.yaml in $EDITOR
hermes config set KEY VAL Set a config value
hermes config path Print config.yaml path
hermes config env-path Print .env path
hermes config check Check for missing/outdated config
hermes config migrate Update config with new options
hermes doctor [--fix] Check dependencies and config
Credential Pools
hermes auth add Interactive credential wizard (oauth, api-key)
hermes auth list [PROVIDER] List pooled credentials
hermes auth remove P INDEX Remove by provider + index
hermes auth reset PROVIDER Clear exhaustion status
hermes logout Clear stored auth
Tools & Skills
hermes tools Interactive tool enable/disable (curses UI)
hermes tools list Show all tools and status
hermes tools enable NAME Enable a toolset
hermes tools disable NAME Disable a toolset
hermes skills list List installed skills
hermes skills search QUERY Search the skills hub
hermes skills install ID Install a skill (ID can be a hub identifier OR a direct https://โฆ/SKILL.md URL; pass --name to override when frontmatter has no name)
hermes skills inspect ID Preview without installing
hermes skills config Enable/disable skills per platform
hermes skills check Check for updates
hermes skills update Update outdated skills
hermes skills uninstall N Remove a hub skill
hermes skills publish PATH Publish to registry
hermes skills browse Browse all available skills
hermes skills tap add REPO Add a GitHub repo as skill source
MCP Servers
hermes mcp serve Run Hermes as an MCP server
hermes mcp add NAME Add an MCP server (--url or --command)
hermes mcp remove NAME Remove an MCP server
hermes mcp list List configured servers
hermes mcp test NAME Test connection
hermes mcp configure NAME Toggle tool selection
Gateway (Messaging Platforms)
hermes gateway run Start gateway foreground
hermes gateway install Install as background service
hermes gateway start/stop Control the service
hermes gateway restart Restart the service
hermes gateway status Check status
hermes gateway setup Configure platforms
Supported platforms: Telegram, Discord, Slack, WhatsApp, Signal, Email, SMS, Matrix, Mattermost, Home Assistant, DingTalk, Feishu, WeCom, BlueBubbles (iMessage), Weixin (WeChat), API Server, Webhooks. Open WebUI connects via the API Server adapter.
Platform docs: https://hermes-agent.nousresearch.com/docs/user-guide/messaging/
Discord-specific walkthrough (token, intents, service install, access control): see references/discord-gateway-setup.md in this skill.
- Per-channel personas and skill bindings: see
references/gateway-channel-personas.md (works on Discord, Slack, Telegram, Mattermost, Matrix).
- For long-running Discord-first operations, purpose-specific channel routing, periodic summaries, weekly Dreaming/audit reports, and log-safety patterns: see
references/discord-operating-planes.md.
- For broad Hermes/LifeOS/SQAF ecosystem audits (cron inventory, live services, dashboards, provider/model warnings, and control-plane gaps), see
references/ecosystem-audit.md.
Sessions
hermes sessions list List recent sessions
hermes sessions browse Interactive picker
hermes sessions export OUT Export to JSONL
hermes sessions rename ID T Rename a session
hermes sessions delete ID Delete a session
hermes sessions prune Clean up old sessions (--older-than N days)
hermes sessions stats Session store statistics
For browser-based viewing of existing Hermes CLI/Discord/cron session transcripts, prefer a lightweight static export from ~/.hermes/state.db into a private web root instead of assuming Open WebUI can browse Hermes' native session store. See references/hermes-session-static-web-viewer.md for the SQLite schema, static HTML export workflow, redaction/truncation cautions, and the user's Mac mini deployment (/hermes-sessions/ under the Tailscale-only ~/hermes-web site).
For cron job execution history, the same static-export pattern applies to ~/.hermes/cron/jobs.json and ~/.hermes/cron/output/{job_id}/*.md. See references/cron-history-web-viewer.md for the cron data model, schedule-dict pitfall, and the user's deployed /cron-history/ dashboard.
Cron Jobs
hermes cron list List jobs (--all for disabled)
hermes cron create SCHED Create: '30m', 'every 2h', '0 9 *'
hermes cron edit ID Edit schedule, prompt, delivery
hermes cron pause/resume ID Control job state
hermes cron run ID Trigger on next tick
hermes cron remove ID Delete a job
hermes cron status Scheduler status
For bounded autonomous lab/orchestrator cron jobs that use file-based state, subagent lanes, artifact publishing, and status transitions (active โ complete/blocked/inactive), see references/autonomous-agent-lab-cron-cycle.md. A reusable verification script template lives at scripts/verify-completion-template.py.
For a worked example of evolving an autonomous lab into a config-driven, themeable, Docker-ready installable product, see references/autonomous-lab-product-architecture.md. For CI, integration testing, pluggable adapter architecture, bounded cycle orchestration, and post-productization patterns, see references/product-maturity-patterns.md.
For the final completion verification checklist โ the explicit audit pattern to run before marking status: complete on an installable-solution mission, see references/autonomous-lab-completion-verification.md.
For the reactivation protocol when a completed lab receives new P0 feedback or the user contradicts a completion claim, see references/autonomous-lab-reactivation-protocol.md.
For the config/CHANGELOG version drift pitfall that occurs when autonomous labs evolve over many cycles, and for the related source vs. published file drift problem where the live web root diverges from the project source, see references/autonomous-lab-version-drift.md.
For adding historical trend tracking (SQLite-backed agent status transitions + vanilla JS SVG sparklines) to an autonomous lab dashboard, see references/history-tracking-sparkline-pattern.md.
For preventing unbounded SQLite growth in long-running labs, see references/autonomous-lab-data-retention.md โ covers automatic per-refresh pruning and a standalone manual prune utility.
- For reusable dashboard UX patterns (onboarding tours, data freshness badges, keyboard shortcuts, progressive disclosure inspectors, cross-linking between views, inspector deep-linking), see
references/dashboard-ux-patterns.md.
For the daily operational briefing modal โ a one-screen human-first summary of agent counts, blocked work, recent events, health status, and upcoming cron schedules โ see references/daily-briefing-modal.md.
For the aggressive human-first inspector refinement โ when users report that details are hard to understand and the fix is to strip technical labels from the default view โ see references/progressive-disclosure-human-first.md.
For programmatic verification of CSS custom-property theme systems โ catching scoping bugs, confirming theme distinctness, and validating JS switching logic โ see references/theme-system-verification.md.
- For Son's Discord-first autonomous experiments where a channel hosts a repeated multi-agent loop, use the Autonomous Discord Agent Lab pattern: create file-based durable state, a paused cron orchestrator delivered to
discord:<channel_id>, then activate it from a user mission trigger. See references/autonomous-discord-agent-lab.md.
- For verifying that a release package (
tar.gz) is actually installable by third parties and contains no stale artifacts or hardcoded references, see references/release-package-verification.md and the reusable script at scripts/release-verify.sh.
Webhooks
hermes webhook subscribe N Create route at /webhooks/<name>
hermes webhook list List subscriptions
hermes webhook remove NAME Remove a subscription
hermes webhook test NAME Send a test POST
Profiles
hermes profile list List all profiles
hermes profile create NAME Create (--clone, --clone-all, --clone-from)
hermes profile use NAME Set sticky default
hermes profile delete NAME Delete a profile
hermes profile show NAME Show details
hermes profile alias NAME Manage wrapper scripts
hermes profile rename A B Rename a profile
hermes profile export NAME Export to tar.gz
hermes profile import FILE Import from archive
Credential Pools
hermes auth add Interactive credential wizard
hermes auth list [PROVIDER] List pooled credentials
hermes auth remove P INDEX Remove by provider + index
hermes auth reset PROVIDER Clear exhaustion status
Other
hermes insights [--days N] Usage analytics
hermes update Update to latest version
hermes pairing list/approve/revoke DM authorization
hermes plugins list/install/remove Plugin management
hermes honcho setup/status Honcho memory integration (requires honcho plugin)
hermes memory setup/status/off Memory provider config
hermes completion bash|zsh Shell completions
hermes acp ACP server (IDE integration)
hermes claw migrate Migrate from OpenClaw
hermes uninstall Uninstall Hermes
---
Slash Commands (In-Session)
Type these during an interactive chat session. New commands land fairly
often; if something below looks stale, run /help in-session for the
authoritative list or see the [live slash commands reference](https://hermes-agent.nousresearch.com/docs/reference/slash-commands).
The registry of record is hermes_cli/commands.py โ every consumer
(autocomplete, Telegram menu, Slack mapping, /help) derives from it.
Session Control
/new (/reset) Fresh session
/clear Clear screen + new session (CLI)
/retry Resend last message
/undo Remove last exchange
/title [name] Name the session
/compress Manually compress context
/stop Kill background processes
/rollback [N] Restore filesystem checkpoint
/snapshot [sub] Create or restore state snapshots of Hermes config/state (CLI)
/background <prompt> Run prompt in background
/queue <prompt> Queue for next turn
/steer <prompt> Inject a message after the next tool call without interrupting
/agents (/tasks) Show active agents and running tasks
/resume [name] Resume a named session
/goal [text|sub] Set a standing goal Hermes works on across turns until achieved
(subcommands: status, pause, resume, clear)
/redraw Force a full UI repaint (CLI)
Configuration
/config Show config (CLI)
/model [name] Show or change model
/personality [name] Set personality
/reasoning [level] Set reasoning (none|minimal|low|medium|high|xhigh|show|hide)
/verbose Cycle: off โ new โ all โ verbose
/voice [on|off|tts] Voice mode
/yolo Toggle approval bypass
/busy [sub] Control what Enter does while Hermes is working (CLI)
(subcommands: queue, steer, interrupt, status)
/indicator [style] Pick the TUI busy-indicator style (CLI)
(styles: kaomoji, emoji, unicode, ascii)
/footer [on|off] Toggle gateway runtime-metadata footer on final replies
/skin [name] Change theme (CLI)
/statusbar Toggle status bar (CLI)
Tools & Skills
/tools Manage tools (CLI)
/toolsets List toolsets (CLI)
/skills Search/install skills (CLI)
/skill <name> Load a skill into session
/reload-skills Re-scan ~/.hermes/skills/ for added/removed skills
/reload Reload .env variables into the running session (CLI)
/reload-mcp Reload MCP servers
/cron Manage cron jobs (CLI)
/curator [sub] Background skill maintenance (status, run, pin, archive, โฆ)
/kanban [sub] Multi-profile collaboration board (tasks, links, comments)
/plugins List plugins (CLI)
Gateway
/approve Approve a pending command (gateway)
/deny Deny a pending command (gateway)
/restart Restart gateway (gateway)
/sethome Set current chat as home channel (gateway)
/update Update Hermes to latest (gateway)
/topic [sub] Enable or inspect Telegram DM topic sessions (gateway)
/platforms (/gateway) Show platform connection status (gateway)
Utility
/branch (/fork) Branch the current session
/fast Toggle priority/fast processing
/browser Open CDP browser connection
/history Show conversation history (CLI)
/save Save conversation to file (CLI)
/copy [N] Copy the last assistant response to clipboard (CLI)
/paste Attach clipboard image (CLI)
/image Attach local image file (CLI)
Info
/help Show commands
/commands [page] Browse all commands (gateway)
/usage Token usage
/insights [days] Usage analytics
/gquota Show Google Gemini Code Assist quota usage (CLI)
/status Session info (gateway)
/profile Active profile info
/debug Upload debug report (system info + logs) and get shareable links
Exit
/quit (/exit, /q) Exit CLI
---
Key Paths & Config
~/.hermes/config.yaml Main configuration
~/.hermes/.env API keys and secrets
$HERMES_HOME/skills/ Installed skills
~/.hermes/sessions/ Session transcripts
~/.hermes/logs/ Gateway and error logs
~/.hermes/auth.json OAuth tokens and credential pools
~/.hermes/hermes-agent/ Source code (if git-installed)
Profiles use ~/.hermes/profiles/<name>/ with the same layout.
Config Sections
Edit with hermes config edit or hermes config set section.key value.
| Section | Key options |
|---------|-------------|
| model | default, provider, base_url, api_key, context_length |
| agent | max_turns (90), tool_use_enforcement |
| terminal | backend (local/docker/ssh/modal), cwd, timeout (180) |
| compression | enabled, threshold (0.50), target_ratio (0.20) |
| display | skin, tool_progress, show_reasoning, show_cost |
| stt | enabled, provider (local/groq/openai/mistral) |
| tts | provider (edge/elevenlabs/openai/minimax/mistral/neutts) |
| memory | memory_enabled, user_profile_enabled, provider |
| security | tirith_enabled, website_blocklist |
| delegation | model, provider, base_url, api_key, max_iterations (50), reasoning_effort |
| checkpoints | enabled, max_snapshots (50) |
| fallback_model | provider, model, base_url, key_env |
Fallback Providers
Hermes can automatically fail over to a backup provider:model when the primary is unavailable. This is turn-scoped โ each new user message starts with the primary restored; fallback only activates mid-turn when the primary fails.
Configuration ( ~/.hermes/config.yaml):
fallback_model:
provider: opencode-go
model: kimi-k2.6
Or use the interactive manager:
hermes fallback add # interactive picker
hermes fallback list # show fallback chain
hermes fallback remove # remove by index
Legacy note: fallback_model (singular) is the legacy single-fallback key. fallback_providers (list) supports multiple ordered fallbacks. When both exist, fallback_providers takes priority.
Trigger conditions (after exhausting retries where applicable):
- Rate limits (HTTP 429)
- Server errors (HTTP 500, 502, 503)
- Auth failures (HTTP 401, 403) โ immediately
- Not found (HTTP 404) โ immediately
- Invalid / empty responses repeatedly
Supported providers include all standard providers (OpenRouter, Anthropic, OpenCode Go/ Zen, Kimi, etc.) plus custom endpoints with base_url + key_env. Full provider docs: https://hermes-agent.nousresearch.com/docs/integrations/providers
Limitations:
- Subagent delegation does not inherit fallback config
- Cron jobs do not use fallback (use per-job provider/model overrides)
- Auxiliary tasks (vision, compression, etc.) use their own
auxiliary.* provider chain
For a deep-dive with worked examples and model lists, see references/fallback-providers.md.
Full config reference: https://hermes-agent.nousresearch.com/docs/user-guide/configuration
Providers
20+ providers supported. Set via hermes model or hermes setup.
| Provider | Auth | Key env var |
|----------|------|-------------|
| OpenRouter | API key | OPENROUTER_API_KEY |
| Anthropic | API key | ANTHROPIC_API_KEY |
| Nous Portal | OAuth | hermes auth |
| OpenAI Codex | OAuth | hermes auth |
| GitHub Copilot | Token | COPILOT_GITHUB_TOKEN |
| Google Gemini | API key | GOOGLE_API_KEY or GEMINI_API_KEY |
| DeepSeek | API key | DEEPSEEK_API_KEY |
| xAI / Grok | API key | XAI_API_KEY |
| Hugging Face | Token | HF_TOKEN |
| Z.AI / GLM | API key | GLM_API_KEY |
| MiniMax | API key | MINIMAX_API_KEY |
| MiniMax CN | API key | MINIMAX_CN_API_KEY |
| Kimi / Moonshot | API key | KIMI_API_KEY |
| Alibaba / DashScope | API key | DASHSCOPE_API_KEY |
| Xiaomi MiMo | API key | XIAOMI_API_KEY |
| Kilo Code | API key | KILOCODE_API_KEY |
| AI Gateway (Vercel) | API key | AI_GATEWAY_API_KEY |
| OpenCode Zen | API key | OPENCODE_ZEN_API_KEY |
| OpenCode Go | API key | OPENCODE_GO_API_KEY |
| Qwen OAuth | OAuth | hermes auth add qwen-oauth |
| Custom endpoint | Config | model.base_url + model.api_key in config.yaml |
| GitHub Copilot ACP | External | COPILOT_CLI_PATH or Copilot CLI |
Full provider docs: https://hermes-agent.nousresearch.com/docs/integrations/providers
Toolsets
Enable/disable via hermes tools (interactive) or hermes tools enable/disable NAME.
| Toolset | What it provides |
|---------|-----------------|
| web | Web search and content extraction |
| search | Web search only (subset of web) |
| browser | Browser automation (Browserbase, Camofox, or local Chromium) |
| terminal | Shell commands and process management |
| file | File read/write/search/patch |
| code_execution | Sandboxed Python execution |
| vision | Image analysis |
| image_gen | AI image generation |
| video | Video analysis and generation |
| tts | Text-to-speech |
| skills | Skill browsing and management |
| memory | Persistent cross-session memory |
| session_search | Search past conversations |
| delegation | Subagent task delegation |
| cronjob | Scheduled task management |
| clarify | Ask user clarifying questions |
| messaging | Cross-platform message sending |
| todo | In-session task planning and tracking |
| kanban | Multi-agent work-queue tools (gated to workers) |
| debugging | Extra introspection/debug tools (off by default) |
| safe | Minimal, low-risk toolset for locked-down sessions |
| spotify | Spotify playback and playlist control |
| homeassistant | Smart home control (off by default) |
| discord | Discord integration tools |
| discord_admin | Discord admin/moderation tools |
| feishu_doc | Feishu (Lark) document tools |
| feishu_drive | Feishu (Lark) drive tools |
| yuanbao | Yuanbao integration tools |
| rl | Reinforcement learning tools (off by default) |
| moa | Mixture of Agents (off by default) |
Full enumeration lives in toolsets.py as the TOOLSETS dict; _HERMES_CORE_TOOLS is the default bundle most platforms inherit from.
Tool changes take effect on /reset (new session). They do NOT apply mid-conversation to preserve prompt caching.
---
Security & Privacy Toggles
Common "why is Hermes doing X to my output / tool calls / commands?" toggles โ and the exact commands to change them. Most of these need a fresh session (/reset in chat, or start a new hermes invocation) because they're read once at startup.
Secret redaction in tool output
Secret redaction is off by default โ tool output (terminal stdout, read_file, web content, subagent summaries, etc.) passes through unmodified. If the user wants Hermes to auto-mask strings that look like API keys, tokens, and secrets before they enter the conversation context and logs:
hermes config set security.redact_secrets true # enable globally
Restart required. security.redact_secrets is snapshotted at import time โ toggling it mid-session (e.g. via export HERMES_REDACT_SECRETS=true from a tool call) will NOT take effect for the running process. Tell the user to run hermes config set security.redact_secrets true in a terminal, then start a new session. This is deliberate โ it prevents an LLM from flipping the toggle on itself mid-task.
Disable again with:
hermes config set security.redact_secrets false
PII redaction in gateway messages
Separate from secret redaction. When enabled, the gateway hashes user IDs and strips phone numbers from the session context before it reaches the model:
hermes config set privacy.redact_pii true # enable
hermes config set privacy.redact_pii false # disable (default)
Command approval prompts
By default (approvals.mode: manual), Hermes prompts the user before running shell commands flagged as destructive (rm -rf, git reset --hard, etc.). The modes are:
manual โ always prompt (default)
smart โ use an auxiliary LLM to auto-approve low-risk commands, prompt on high-risk
off โ skip all approval prompts (equivalent to --yolo)
hermes config set approvals.mode smart # recommended middle ground
hermes config set approvals.mode off # bypass everything (not recommended)
Per-invocation bypass without changing config:
hermes --yolo โฆ
export HERMES_YOLO_MODE=1
Note: YOLO / approvals.mode: off does NOT turn off secret redaction. They are independent.
Shell hooks allowlist
Some shell-hook integrations require explicit allowlisting before they fire. Managed via ~/.hermes/shell-hooks-allowlist.json โ prompted interactively the first time a hook wants to run.
Disabling the web/browser/image-gen tools
To keep the model away from network or media tools entirely, open hermes tools and toggle per-platform. Takes effect on next session (/reset). See the Tools & Skills section above.
---
Voice & Transcription
STT (Voice โ Text)
Voice messages from messaging platforms are auto-transcribed.
Provider priority (auto-detected):
1. Local faster-whisper โ free, no API key: pip install faster-whisper
2. Groq Whisper โ free tier: set GROQ_API_KEY
3. OpenAI Whisper โ paid: set VOICE_TOOLS_OPENAI_KEY
4. Mistral Voxtral โ set MISTRAL_API_KEY
Config:
stt:
enabled: true
provider: local # local, groq, openai, mistral
local:
model: base # tiny, base, small, medium, large-v3
TTS (Text โ Voice)
| Provider | Env var | Free? |
|----------|---------|-------|
| Edge TTS | None | Yes (default) |
| ElevenLabs | ELEVENLABS_API_KEY | Free tier |
| OpenAI | VOICE_TOOLS_OPENAI_KEY | Paid |
| MiniMax | MINIMAX_API_KEY | Paid |
| Mistral (Voxtral) | MISTRAL_API_KEY | Paid |
| NeuTTS (local) | None (pip install neutts[all] + espeak-ng) | Free |
Voice commands: /voice on (voice-to-voice), /voice tts (always voice), /voice off.
---
Spawning Additional Hermes Instances
Run additional Hermes processes as fully independent subprocesses โ separate sessions, tools, and environments.
When to Use This vs delegate_task
| | delegate_task | Spawning hermes process |
|-|-----------------|--------------------------|
| Isolation | Separate conversation, shared process | Fully independent process |
| Duration | Minutes (bounded by parent loop) | Hours/days |
| Tool access | Subset of parent's tools | Full tool access |
| Interactive | No | Yes (PTY mode) |
| Use case | Quick parallel subtasks | Long autonomous missions |
One-Shot Mode
terminal(command="hermes chat -q 'Research GRPO papers and write summary to ~/research/grpo.md'", timeout=300)
Background for long tasks:
terminal(command="hermes chat -q 'Set up CI/CD for ~/myapp'", background=true)
Interactive PTY Mode (via tmux)
Hermes uses prompt_toolkit, which requires a real terminal. Use tmux for interactive spawning:
Start
terminal(command="tmux new-session -d -s agent1 -x 120 -y 40 'hermes'", timeout=10)
Wait for startup, then send a message
terminal(command="sleep 8 && tmux send-keys -t agent1 'Build a FastAPI auth service' Enter", timeout=15)
Read output
terminal(command="sleep 20 && tmux capture-pane -t agent1 -p", timeout=5)
Send follow-up
terminal(command="tmux send-keys -t agent1 'Add rate limiting middleware' Enter", timeout=5)
Exit
terminal(command="tmux send-keys -t agent1 '/exit' Enter && sleep 2 && tmux kill-session -t agent1", timeout=10)
Multi-Agent Coordination
Agent A: backend
terminal(command="tmux new-session -d -s backend -x 120 -y 40 'hermes -w'", timeout=10)
terminal(command="sleep 8 && tmux send-keys -t backend 'Build REST API for user management' Enter", timeout=15)
Agent B: frontend
terminal(command="tmux new-session -d -s frontend -x 120 -y 40 'hermes -w'", timeout=10)
terminal(command="sleep 8 && tmux send-keys -t frontend 'Build React dashboard for user management' Enter", timeout=15)
Check progress, relay context between them
terminal(command="tmux capture-pane -t backend -p | tail -30", timeout=5)
terminal(command="tmux send-keys -t frontend 'Here is the API schema from the backend agent: ...' Enter", timeout=5)
Session Resume
Resume most recent session
terminal(command="tmux new-session -d -s resumed 'hermes --continue'", timeout=10)
Resume specific session
terminal(command="tmux new-session -d -s resumed 'hermes --resume 20260225_143052_a1b2c3'", timeout=10)
Tips
- Prefer
delegate_task for quick subtasks โ less overhead than spawning a full process
- Use
-w (worktree mode) when spawning agents that edit code โ prevents git conflicts
- Set timeouts for one-shot mode โ complex tasks can take 5-10 minutes
- Use
hermes chat -q for fire-and-forget โ no PTY needed
- Use tmux for interactive sessions โ raw PTY mode has
\r vs \n issues with prompt_toolkit
- For scheduled tasks, use the
cronjob tool instead of spawning โ handles delivery and retry
---
Durable & Background Systems
Four systems run alongside the main conversation loop. Quick reference
here; full developer notes live in AGENTS.md, user-facing docs under
website/docs/user-guide/features/.
Delegation (delegate_task)
Synchronous subagent spawn โ the parent waits for the child's summary
before continuing its own loop. Isolated context + terminal session.
- Single:
delegate_task(goal, context, toolsets).
- Batch:
delegate_task(tasks=[{goal, ...}, ...]) runs children in
parallel, capped by delegation.max_concurrent_children (default 3).
- Roles:
leaf (default; cannot re-delegate) vs orchestrator
(can spawn its own workers, bounded by delegation.max_spawn_depth).
- Not durable. If the parent is interrupted, the child is
cancelled. For work that must outlive the turn, use cronjob or
terminal(background=True, notify_on_complete=True).
Config: delegation.* in config.yaml.
Tuning max_concurrent_children
Default is 3. Rule of thumb for raising it:
- Light tasks (web search, file grep): up to
6-8
- Medium tasks (code execution, browser):
4-5
- Heavy tasks (builds, large data):
2-3
- Actual bottleneck is usually the API rate limit, not local CPU/RAM. On a 10-core M4 with 16GB RAM, CPU is rarely the constraint.
- Formula: start at
5, raise only if profiling shows idle time between API responses.
Cron (scheduled jobs)
Durable scheduler โ cron/jobs.py + cron/scheduler.py. Drive it via
the cronjob tool, the hermes cron CLI (list, add, edit,
pause, resume, run, remove), or the /cron slash command.
- Schedules: duration (
"30m", "2h"), "every" phrase
( "every monday 9am"), 5-field cron ( "0 9 *"), or ISO timestamp.
- Per-job knobs:
skills, model/provider override, script
(pre-run data collection; no_agent=True makes the script the whole
job), context_from (chain job A's output into job B), workdir
(run in a specific dir with its AGENTS.md / CLAUDE.md loaded),
multi-platform delivery.
- Invariants: 3-minute hard interrupt per run,
.tick.lock file
prevents duplicate ticks across processes, cron sessions pass
skip_memory=True by default, and cron deliveries are framed with a
header/footer instead of being mirrored into the target gateway
session (keeps role alternation intact).
User docs: https://hermes-agent.nousresearch.com/docs/user-guide/features/cron
Curator (skill lifecycle)
Background maintenance for agent-created skills. Tracks usage, marks
idle skills stale, archives stale ones, keeps a pre-run tar.gz backup
so nothing is lost.
- CLI:
hermes curator <verb> โ status, run, pause, resume,
pin, unpin, archive, restore, prune, backup, rollback.
- Slash:
/curator <subcommand> mirrors the CLI.
- Scope: only touches skills with
created_by: "agent" provenance.
Bundled + hub-installed skills are off-limits. Never deletes โ
max destructive action is archive. Pinned skills are exempt from
every auto-transition and every LLM review pass.
- Telemetry: sidecar at
~/.hermes/skills/.usage.json holds
per-skill use_count, view_count, patch_count,
last_activity_at, state, pinned.
Config: curator.* (enabled, interval_hours, min_idle_hours,
stale_after_days, archive_after_days, backup.*).
User docs: https://hermes-agent.nousresearch.com/docs/user-guide/features/curator
Dreaming (periodic memory/skill consolidation)
For Anthropic-style "dreaming" workflows, combine cron + session_search + memory + skills + curator into a scheduled review loop. Start with a weekly, proposal-only report that audits recent sessions, repeated user corrections, memory conflicts, skill patch candidates, and cron/automation improvements. Do not automatically delete/replace memory or patch/archive skills unless the user explicitly approves the proposed changes. See references/weekly-dreaming-routine.md for the recommended prompt, report format, safety policy, and cron creation pattern.
Kanban (multi-agent work queue)
Durable SQLite board for multi-profile / multi-worker collaboration.
Users drive it via hermes kanban <verb>; dispatcher-spawned workers
see a focused kanban_* toolset gated by HERMES_KANBAN_TASK so the
schema footprint is zero outside worker processes.
- CLI verbs (common):
init, create, list (alias ls),
show, assign, link, unlink, comment, complete, block,
unblock, archive, tail. Less common: watch, stats, runs,
log, dispatch, daemon, gc.
- Worker toolset:
kanban_show, kanban_complete, kanban_block,
kanban_heartbeat, kanban_comment, kanban_create, kanban_link.
- Dispatcher runs inside the gateway by default
( kanban.dispatch_in_gateway: true) โ reclaims stale claims,
promotes ready tasks, atomically claims, spawns assigned profiles.
Auto-blocks a task after ~5 consecutive spawn failures.
- Isolation: board is the hard boundary (workers get
HERMES_KANBAN_BOARD pinned in env); tenant is a soft namespace
within a board for workspace-path + memory-key isolation.
User docs: https://hermes-agent.nousresearch.com/docs/user-guide/features/kanban
Log Relay (Hermes โ Discord)
A background Python script that tails ~/.hermes/logs/*.log and batches lines to a Discord channel. Includes session-ID extraction, rate-limit handling, and auto-restart via launchd/systemd. Useful for remote monitoring and audit trails.
- Reference:
references/discord-log-relay.md โ full setup, tuning, macOS/Linux service install, pitfalls.
- Template:
templates/discord-log-relay.py โ copy, set CHANNEL_ID, and deploy.
- Discord operations:
references/discord-operating-planes.md โ channel-purpose routing, periodic-summary vs Dreaming report formats, and safety/cost notes for Discord-first Hermes deployments.
Key pitfall: ask the user about batch frequency upfront rather than defaulting to real-time streaming. Most users prefer 10-minute or hourly batches. High-volume raw logs should be batched, summarized, or stored out-of-band; avoid Discord message storms during error loops.
Weekly Dreaming / Memory Curation
For long-running Hermes deployments, users may want an Anthropic-style "Dreaming" loop: a scheduled review that consolidates experience, proposes memory/skill/cron changes, and identifies what to keep, weaken, archive, or delete. Hermes has the building blocks (sessions, session_search, memory, skills, curator, cron), but the safe default is proposal mode:
1. Inspect recent usage and sessions.
2. Extract repeated success patterns, failure patterns, and user corrections.
3. Propose memory updates/removals without applying them silently.
4. Propose skill patches/archive candidates and cron/reporting improvements.
5. End with explicit approval checkboxes.
Do not silently rewrite or delete memory/skills from a Dreaming report unless the user explicitly authorized automatic application. See references/discord-operating-planes.md for a report template and routing heuristics.
---
Windows-Specific Quirks
Hermes runs natively on Windows (PowerShell, cmd, Windows Terminal, git-bash
mintty, VS Code integrated terminal). Most of it just works, but a handful
of differences between Win32 and POSIX have bitten us โ document new ones
here as you hit them so the next person (or the next session) doesn't
rediscover them from scratch.
Input / Keybindings
Alt+Enter doesn't insert a newline. Windows Terminal intercepts Alt+Enter
at the terminal layer to toggle fullscreen โ the keystroke never reaches
prompt_toolkit. Use Ctrl+Enter instead. Windows Terminal delivers
Ctrl+Enter as LF ( c-j), distinct from plain Enter ( c-m / CR), and the
CLI binds c-j to newline insertion on win32 only (see
_bind_prompt_submit_keys + the Windows-only c-j binding in cli.py).
Side effect: the raw Ctrl+J keystroke also inserts a newline on Windows โ
unavoidable, because Windows Terminal collapses Ctrl+Enter and Ctrl+J to
the same keycode at the Win32 console API layer. No conflicting binding
existed for Ctrl+J on Windows, so this is a harmless side effect.
mintty / git-bash behaves the same (fullscreen on Alt+Enter) unless you
disable Alt+Fn shortcuts in Options โ Keys. Easier to just use Ctrl+Enter.
Diagnosing keybindings. Run python scripts/keystroke_diagnostic.py
(repo root) to see exactly how prompt_toolkit identifies each keystroke
in the current terminal. Answers questions like "does Shift+Enter come
through as a distinct key?" (almost never โ most terminals collapse it
to plain Enter) or "what byte sequence is my terminal sending for
Ctrl+Enter?" This is how the Ctrl+Enter = c-j fact was established.
Config / Files
HTTP 400 "No models provided" on first run. config.yaml was saved
with a UTF-8 BOM (common when Windows apps write it). Re-save as UTF-8
without BOM. hermes config edit writes without BOM; manual edits in
Notepad are the usual culprit.
execute_code / Sandbox
WinError 10106 ("The requested service provider could not be loaded
or initialized") from the sandbox child process โ it can't create an
AF_INET socket, so the loopback-TCP RPC fallback fails before
connect(). Root cause is usually not a broken Winsock LSP; it's
Hermes's own env scrubber dropping SYSTEMROOT / WINDIR / COMSPEC
from the child env. Python's socket module needs SYSTEMROOT to locate
mswsock.dll. Fixed via the _WINDOWS_ESSENTIAL_ENV_VARS allowlist in
tools/code_execution_tool.py. If you still hit it, echo os.environ
inside an execute_code block to confirm SYSTEMROOT is set. Full
diagnostic recipe in references/execute-code-sandbox-env-windows.md.
Testing / Contributing
scripts/run_tests.sh doesn't work as-is on Windows โ it looks for
POSIX venv layouts ( .venv/bin/activate). The Hermes-installed venv at
venv/Scripts/ has no pip or pytest either (stripped for install size).
Workaround: install pytest + pytest-xdist + pyyaml into a system Python
3.11 user site, then invoke pytest directly with PYTHONPATH set:
"/c/Program Files/Python311/python" -m pip install --user pytest pytest-xdist pyyaml
export PYTHONPATH="$(pwd)"
"/c/Program Files/Python311/python" -m pytest tests/foo/test_bar.py -v --tb=short -n 0
Use -n 0, not -n 4 โ pyproject.toml's default addopts already
includes -n, and the wrapper's CI-parity guarantees don't apply off POSIX.
POSIX-only tests need skip guards. Common markers already in the codebase:
- Symlinks โ elevated privileges on Windows
0o600 file modes โ POSIX mode bits not enforced on NTFS by default
signal.SIGALRM โ Unix-only (see tests/conftest.py::_enforce_test_timeout)
- Winsock / Windows-specific regressions โ
@pytest.mark.skipif(sys.platform != "win32", ...)
Use the existing skip-pattern style (sys.platform == "win32" or
sys.platform.startswith("win")) to stay consistent with the rest of the
suite.
Path / Filesystem
Line endings. Git may warn LF will be replaced by CRLF the next time
Git touches it. Cosmetic โ the repo's .gitattributes normalizes. Don't
let editors auto-convert committed POSIX-newline files to CRLF.
Forward slashes work almost everywhere. C:/Users/... is accepted by
every Hermes tool and most Windows APIs. Prefer forward slashes in code
and logs โ avoids shell-escaping backslashes in bash.
---
Troubleshooting
Voice not working
1. Check stt.enabled: true in config.yaml
2. Verify provider: pip install faster-whisper or set API key
3. In gateway: /restart. In CLI: exit and relaunch.
Tool not available
1. hermes tools โ check if toolset is enabled for your platform
2. Some tools need env vars (check .env)
3. /reset after enabling tools
Model/provider issues
1. hermes doctor โ check config and dependencies
2. hermes auth add <provider> โ re-authenticate OAuth providers (use --type oauth)
3. Check .env has the right API key
4. Copilot 403: gh auth login tokens do NOT work for Copilot API. You must use the Copilot-specific OAuth device code flow via hermes model โ GitHub Copilot.
Changes not taking effect
- Tools/skills:
/reset starts a new session with updated toolset
- Config changes: In gateway:
/restart. In CLI: exit and relaunch.
- Code changes: Restart the CLI or gateway process
Deployed web dashboard shows stale CSS or theme changes
- Browser cache: Add
?v=N cache-busting query strings to CSS/JS/theme links in HTML.
- Service Worker cache: Bump
CACHE_NAME in sw.js to invalidate old shell caches.
- Automated bump script: For projects with multiple HTML entry points (dashboard, gather, etc.), use
scripts/bump-build.py to atomically update all build badges, cache-busting query strings, and service worker cache names in one command. See references/autonomous-lab-version-drift.md for usage.
- Data freshness: Use
fetch(url, {cache:'no-store'}) for live JSON feeds.
- Auto-detection: Embed
data-build in <html> and compare server build vs loaded build on page load to show a "new version available" banner. See references/static-site-cache-invalidation.md for the full diagnostic recipe and auto-detection pattern.
- Theme switcher reliability: If theme switching works in Chrome but not Samsung Internet, or feels broken on mobile, see
references/theme-switcher-reliability.md for the create-new-link โ load โ remove-old pattern.
- Emergency recovery: If a bad deploy breaks the main app JS, users need a standalone reset page. See
references/emergency-reset-page.md for a zero-dependency reset.html that clears Service Workers and caches without relying on the main app's JS.
Dashboard inspector feels too technical
- The default inspector view should contain only plain-language sentences: headline, "what they're doing now", "why it matters", and a silent visual progress bar (no text label).
- Move all technical fields (source IDs, confidence scores, progress labels, status slugs, badges) behind a "Show technical details" toggle.
- If users say "details are hard to understand," the fix is to remove more fields from the default view, not to add explanations. Explanations of technical fields are still technical.
- See
references/progressive-disclosure-human-first.md for the aggressive simplification pattern.
Pixel-art characters look wrong on mobile
- Decorative CSS elements (cheeks, ears, tails, badges) can be misread as facial features or appendages when avatars shrink below ~50 px.
- Hide them inside
@media (max-width:480px) so only the essential silhouette remains.
- See
references/pixel-art-mobile-readability.md for the exact selectors and rationale.
Skills not showing
1. hermes skills list โ verify installed
2. hermes skills config โ check platform enablement
3. Load explicitly: /skill name or hermes -s name
Gateway issues
Check logs first:
grep -i "failed to send\|error" ~/.hermes/logs/gateway.log | tail -20
Common gateway problems:
- Gateway dies on SSH logout: Enable linger:
sudo loginctl enable-linger $USER
- Gateway dies on WSL2 close: WSL2 requires
systemd=true in /etc/wsl.conf for systemd services to work. Without it, gateway falls back to nohup (dies when session closes).
- Gateway crash loop: Reset the failed state:
systemctl --user reset-failed hermes-gateway
- macOS: bot shows offline after idle time: The gateway runs as a user agent (
LimitLoadToSessionType=Aqua), so macOS suspends it when the system sleeps. The platform websocket drops and the bot appears offline until the network returns. Fix: keep the Mac awake (System Settings -> Energy -> Prevent automatic sleeping, or caffeinate -d -i -s -u &). Low Power Mode makes this worse, not better. See references/macos-gateway-sleep-disconnect.md for the full diagnostic recipe.
Platform-specific issues
- Discord bot silent: Must enable Message Content Intent in Bot โ Privileged Gateway Intents. See full Discord setup reference:
references/discord-gateway-setup.md.
- Slack bot only works in DMs: Must subscribe to
message.channels event. Without it, the bot ignores public channels.
- Windows-specific issues (
Alt+Enter newline, WinError 10106, UTF-8 BOM config, test suite, line endings): see the dedicated Windows-Specific Quirks section above.
Auxiliary models not working
If auxiliary tasks (vision, compression, session_search) fail silently, the auto provider can't find a backend. Either set OPENROUTER_API_KEY or GOOGLE_API_KEY, or explicitly configure each auxiliary task's provider:
hermes config set auxiliary.vision.provider <your_provider>
hermes config set auxiliary.vision.model <model_name>
Full system auth provisioning
For a one-shot workflow to maximize available credentials โ installing gh, generating SSH keys, configuring git, enabling all Hermes toolsets, and auditing current auth state โ see references/system-auth-setup.md.
Editing large files with patch
When a file is read with read_file(offset=...) (pagination), the tool warns that the view is partial. If you attempt patch without re-reading the full file first, you will likely hit non-unique match errors or corrupt the file. Fix: always call read_file without offset to load the whole file before patching. The tool explicitly warns: "โฆwas last read with offset/limit pagination (partial view). Re-read the whole file before overwriting it." โ heed this warning. For append-only updates (e.g., adding a cycle log entry to state.md), do not use terminal(command="cat >> file << 'EOF'...EOF") โ the terminal tool on macOS/Linux misinterprets heredoc << as backgrounding and fails. Instead, write a short Python script via write_file and execute it with terminal(command="python3 /tmp/script.py"). See references/terminal-heredoc-workaround.md for the full pattern.
Shell scripts that call Python with dependencies
Project shell scripts ( test.sh, publish.sh, validate_setup.sh) often call python3 to parse YAML or run helpers. On macOS and some Linux systems, the system python3 lacks PyYAML, causing scripts to fail with ModuleNotFoundError. See references/shell-script-python-auto-detection.md for a reusable find_python() pattern that auto-detects a Python interpreter with the required packages.
Sibling subagent file overwrites
When multiple subagents are running in parallel (e.g. via delegate_task batch mode or kanban worker lanes), a file may be modified by one subagent while another is about to write to it. If you use write_file or patch on a file that was last read before a sibling subagent modified it, your write may silently truncate or revert the sibling's changes. The tool may show a warning like "this file was modified by sibling subagent X but this agent never read it."
Fix:
1. Heed the warning. If the tool reports a sibling modification, re-read the file with read_file before writing.
2. Prefer patch over write_file for partial updates โ patch only changes the matched region and is less likely to wipe unrelated content.
3. If the file is already published/deployed, and the local working copy gets corrupted, recover from the published copy:
cp ~/hermes-web/agent-pets/css/dashboard.css ~/.hermes/autonomous-agent-lab/pixel-pet-ops/web/css/dashboard.css
4. For append-only updates, write a small Python script and execute it rather than using write_file on the whole file.
Prevention: In kanban/multi-agent workflows, assign file-level ownership so only one worker touches each file. If parallel workers must edit the same file, have them write to separate temp files and let the orchestrator merge.
---
Windows-Specific Quirks
| Looking for... | Location |
|----------------|----------|
| Config options | hermes config edit or [Configuration docs](https://hermes-agent.nousresearch.com/docs/user-guide/configuration) |
| Available tools | hermes tools list or [Tools reference](https://hermes-agent.nousresearch.com/docs/reference/tools-reference) |
| Slash commands | /help in session or [Slash commands reference](https://hermes-agent.nousresearch.com/docs/reference/slash-commands) |
| Skills catalog | hermes skills browse or [Skills catalog](https://hermes-agent.nousresearch.com/docs/reference/skills-catalog) |
| Provider setup | hermes model or [Providers guide](https://hermes-agent.nousresearch.com/docs/integrations/providers) |
| Platform setup | hermes gateway setup or [Messaging docs](https://hermes-agent.nousresearch.com/docs/user-guide/messaging/) |
| MCP servers | hermes mcp list or [MCP guide](https://hermes-agent.nousresearch.com/docs/user-guide/features/mcp) |
| Profiles | hermes profile list or [Profiles docs](https://hermes-agent.nousresearch.com/docs/user-guide/profiles) |
| Cron jobs | hermes cron list or [Cron docs](https://hermes-agent.nousresearch.com/docs/user-guide/features/cron) |
| Memory | hermes memory status or [Memory docs](https://hermes-agent.nousresearch.com/docs/user-guide/features/memory) |
| Env variables | hermes config env-path or [Env vars reference](https://hermes-agent.nousresearch.com/docs/reference/environment-variables) |
| CLI commands | hermes --help or [CLI reference](https://hermes-agent.nousresearch.com/docs/reference/cli-commands) |
| Gateway logs | ~/.hermes/logs/gateway.log |
| Session files | ~/.hermes/sessions/ or hermes sessions browse |
| Source code | ~/.hermes/hermes-agent/ |
---
Contributor Quick Reference
For occasional contributors and PR authors. Full developer docs: https://hermes-agent.nousresearch.com/docs/developer-guide/
Project Layout
hermes-agent/
โโโ run_agent.py # AIAgent โ core conversation loop
โโโ model_tools.py # Tool discovery and dispatch
โโโ toolsets.py # Toolset definitions
โโโ cli.py # Interactive CLI (HermesCLI)
โโโ hermes_state.py # SQLite session store
โโโ agent/ # Prompt builder, context compression, memory, model routing, credential pooling, skill dispatch
โโโ hermes_cli/ # CLI subcommands, config, setup, commands
โ โโโ commands.py # Slash command registry (CommandDef)
โ โโโ config.py # DEFAULT_CONFIG, env var definitions
โ โโโ main.py # CLI entry point and argparse
โโโ tools/ # One file per tool
โ โโโ registry.py # Central tool registry
โโโ gateway/ # Messaging gateway
โ โโโ platforms/ # Platform adapters (telegram, discord, etc.)
โโโ cron/ # Job scheduler
โโโ tests/ # ~3000 pytest tests
โโโ website/ # Docusaurus docs site
Config: ~/.hermes/config.yaml (settings), ~/.hermes/.env (API keys).
Adding a Tool (3 files)
1. Create tools/your_tool.py:
import json, os
from tools.registry import registry
def check_requirements() -> bool:
return bool(os.getenv("EXAMPLE_API_KEY"))
def example_tool(param: str, task_id: str = None) -> str:
return json.dumps({"success": True, "data": "..."})
registry.register(
name="example_tool",
toolset="example",
schema={"name": "example_tool", "description": "...", "parameters": {...}},
handler=lambda args, **kw: example_tool(
param=args.get("param", ""), task_id=kw.get("task_id")),
check_fn=check_requirements,
requires_env=["EXAMPLE_API_KEY"],
)
2. Add to toolsets.py โ _HERMES_CORE_TOOLS list.
Auto-discovery: any tools/*.py file with a top-level registry.register() call is imported automatically โ no manual list needed.
All handlers must return JSON strings. Use get_hermes_home() for paths, never hardcode ~/.hermes.
Adding a Slash Command
1. Add CommandDef to COMMAND_REGISTRY in hermes_cli/commands.py
2. Add handler in cli.py โ process_command()
3. (Optional) Add gateway handler in gateway/run.py
All consumers (help text, autocomplete, Telegram menu, Slack mapping) derive from the central registry automatically.
Agent Loop (High Level)
run_conversation():
1. Build system prompt
2. Loop while iterations < max:
a. Call LLM (OpenAI-format messages + tool schemas)
b. If tool_calls โ dispatch each via handle_function_call() โ append results โ continue
c. If text response โ return
3. Context compression triggers automatically near token limit
Testing
python -m pytest tests/ -o 'addopts=' -q # Full suite
python -m pytest tests/tools/ -q # Specific area
- Tests auto-redirect
HERMES_HOME to temp dirs โ never touch real ~/.hermes/
- Run full suite before pushing any change
- Use
-o 'addopts=' to clear any baked-in pytest flags
Windows contributors: scripts/run_tests.sh currently looks for POSIX venvs ( .venv/bin/activate / venv/bin/activate) and will error out on Windows where the layout is venv/Scripts/activate + python.exe. The Hermes-installed venv at venv/Scripts/ also has no pip or pytest โ it's stripped for end-user install size. Workaround: install pytest + pytest-xdist + pyyaml into a system Python 3.11 user site ( /c/Program Files/Python311/python -m pip install --user pytest pytest-xdist pyyaml), then run tests directly:
export PYTHONPATH="$(pwd)"
"/c/Program Files/Python311/python" -m pytest tests/tools/test_foo.py -v --tb=short -n 0
Use -n 0 (not -n 4) because pyproject.toml's default addopts already includes -n, and the wrapper's CI-parity story doesn't apply off-POSIX.
Cross-platform test guards: tests that use POSIX-only syscalls need a skip marker. Common ones already in the codebase:
- Symlink creation โ
@pytest.mark.skipif(sys.platform == "win32", reason="Symlinks require elevated privileges on Windows") (see tests/cron/test_cron_script.py)
- POSIX file modes (0o600, etc.) โ
@pytest.mark.skipif(sys.platform.startswith("win"), reason="POSIX mode bits not enforced on Windows") (see tests/hermes_cli/test_auth_toctou_file_modes.py)
signal.SIGALRM โ Unix-only (see tests/conftest.py::_enforce_test_timeout)
- Live Winsock / Windows-specific regression tests โ
@pytest.mark.skipif(sys.platform != "win32", reason="Windows-specific regression")
Monkeypatching sys.platform is not enough when the code under test also calls platform.system() / platform.release() / platform.mac_ver(). Those functions re-read the real OS independently, so a test that sets sys.platform = "linux" on a Windows runner will still see platform.system() == "Windows" and route through the Windows branch. Patch all three together:
monkeypatch.setattr(sys, "platform", "linux")
monkeypatch.setattr(platform, "system", lambda: "Linux")
monkeypatch.setattr(platform, "release", lambda: "6.8.0-generic")
See tests/agent/test_prompt_builder.py::TestEnvironmentHints for a worked example.
Extending the system prompt's execution-environment block
Factual guidance about the host OS, user home, cwd, terminal backend, and shell (bash vs. PowerShell on Windows) is emitted from agent/prompt_builder.py::build_environment_hints(). This is also where the WSL hint and per-backend probe logic live. The convention:
- Local terminal backend โ emit host info (OS,
$HOME, cwd) + Windows-specific notes (hostname โ username, terminal uses bash not PowerShell).
- Remote terminal backend (anything in
_REMOTE_TERMINAL_BACKENDS: docker, singularity, modal, daytona, ssh, vercel_sandbox, managed_modal) โ suppress host info entirely and describe only the backend. A live uname/whoami/pwd probe runs inside the backend via tools.environments.get_environment(...).execute(...), cached per process in _BACKEND_PROBE_CACHE, with a static fallback if the probe times out.
- Key fact for prompt authoring: when
TERMINAL_ENV != "local", every file tool (read_file, write_file, patch, search_files) runs inside the backend container, not on the host. The system prompt must never describe the host in that case โ the agent can't touch it.
Full design notes, the exact emitted strings, and testing pitfalls:
references/prompt-builder-environment-hints.md.
Refactor-safety pattern (POSIX-equivalence guard): when you extract inline logic into a helper that adds Windows/platform-specific behavior, keep a _legacy_<name> oracle function in the test file that's a verbatim copy of the old code, then parametrize-diff against it. Example: tests/tools/test_code_execution_windows_env.py::TestPosixEquivalence. This locks in the invariant that POSIX behavior is bit-for-bit identical and makes any future drift fail loudly with a clear diff.
Commit Conventions
type: concise subject line
Optional body.
Types: fix:, feat:, refactor:, docs:, chore:
Key Rules
- Never break prompt caching โ don't change context, tools, or system prompt mid-conversation
- Message role alternation โ never two assistant or two user messages in a row
- Use
get_hermes_home() from hermes_constants for all paths (profile-safe)
- Config values go in
config.yaml, secrets go in .env
- New tools need a
check_fn so they only appear when requirements are met
[IMPORTANT: The user has invoked the "kanban-orchestrator" skill, indicating they want you to follow its instructions. The full skill content is loaded below.]
---
name: kanban-orchestrator
description: Decomposition playbook + anti-temptation rules for an orchestrator profile routing work through Kanban. The "don't do the work yourself" rule and the basic lifecycle are auto-injected into every kanban worker's system prompt; this skill is the deeper playbook when you're specifically playing the orchestrator role.
version: 3.0.0
platforms: [linux, macos, windows]
metadata:
hermes:
tags: [kanban, multi-agent, orchestration, routing]
related_skills: [kanban-worker]
---
Kanban Orchestrator โ Decomposition Playbook
> The core worker lifecycle (including the kanban_create fan-out pattern and the "decompose, don't execute" rule) is auto-injected into every kanban process via the KANBAN_GUIDANCE system-prompt block. This skill is the deeper playbook when you're an orchestrator profile whose whole job is routing.
Profiles are user-configured โ not a fixed roster
Hermes setups vary widely. Some users run a single profile that does everything; some run a small fleet (docker-worker, cron-worker); some run a curated specialist team they've named themselves. There is no default specialist roster โ the orchestrator skill does not know what profiles exist on this machine.
Before fanning out, you must ground the decomposition in the profiles that actually exist. The dispatcher silently fails to spawn unknown assignee names โ it doesn't autocorrect, doesn't suggest, doesn't fall back. So a card assigned to researcher on a setup that only has docker-worker just sits in ready forever.
Step 0: discover available profiles before planning.
Use one of these:
hermes profile list โ prints the table of profiles configured on this machine. Run it through your terminal tool if you have one; otherwise ask the user.
kanban_list(assignee="<some-name>") โ sanity-check a single name. Returns an empty list (rather than an error) for an unknown assignee, so this only confirms a name you're already considering.
- Just ask the user. "What profiles do you have set up?" is a fine first turn when the goal needs more than one specialist.
Cache the result in your working memory for the rest of the conversation. Re-asking every turn wastes a tool call.
When to use the board (vs. just doing the work)
Create Kanban tasks when any of these are true:
1. Multiple specialists are needed. Research + analysis + writing is three profiles.
2. The work should survive a crash or restart. Long-running, recurring, or important.
3. The user might want to interject. Human-in-the-loop at any step.
4. Multiple subtasks can run in parallel. Fan-out for speed.
5. Review / iteration is expected. A reviewer profile loops on drafter output.
6. The audit trail matters. Board rows persist in SQLite forever.
If none of those apply โ it's a small one-shot reasoning task โ use delegate_task instead or answer the user directly.
The anti-temptation rules
Your job description says "route, don't execute." The rules that enforce that:
- Do not execute the work yourself. Your restricted toolset usually doesn't even include terminal/file/code/web for implementation. If you find yourself "just fixing this quickly" โ stop and create a task for the right specialist.
- For any concrete task, create a Kanban task and assign it. Every single time.
- Split multi-lane requests before creating cards. A user prompt can contain several independent workstreams. Extract those lanes first, then create one card per lane instead of bundling unrelated work into a single implementer card.
- Run independent lanes in parallel. If two cards do not need each other's output, leave them unlinked so the dispatcher can fan them out. Link only true data dependencies.
- If no specialist fits the available profiles, ask the user which profile to create or which existing profile to use. Do not invent profile names; the dispatcher will silently drop unknown assignees.
- Decompose, route, and summarize โ that's the whole job.
Exception: micro-UI polish cycles
There is one narrow exception where the orchestrator may execute directly instead of creating Kanban cards: tiny UI-only polish cycles (e.g., adding a CSS class, a theme preview dot, a hover state, a cross-link, or a HUD button) that are purely presentational, require no cross-file logic changes, and fit comfortably inside a single bounded cycle with no need for review or parallel work. If the change is limited to HTML/CSS/JS cosmetics, no other profile has a stake in it, and the user did not ask for a design review, the orchestrator should just edit and publish rather than paying the kanban-overhead tax. This exception does NOT apply to architecture changes, adapter logic, plugin interfaces, or anything that touches the data layer.
Decomposition playbook
Step 1 โ Understand the goal
Ask clarifying questions if the goal is ambiguous. Cheap to ask; expensive to spawn the wrong fleet.
Step 2 โ Sketch the task graph
Before creating anything, draft the graph out loud (in your response to the user). Treat every concrete workstream as a candidate card:
1. Extract the lanes from the request.
2. Map each lane to one of the profiles you discovered in Step 0. If a lane doesn't fit any existing profile, ask the user which to use or create.
3. Decide whether each lane is independent or gated by another lane.
4. Create independent lanes as parallel cards with no parent links.
5. Create synthesis/review/integration cards with parent links to the lanes they depend on.
Examples of prompts that should fan out (using placeholder profile names โ substitute whatever exists on the user's setup):
- "Build an app" โ one card to a design-oriented profile for product/UI direction, one or two cards to engineering profiles for implementation, plus a later integration/review card if the user has a reviewer profile.
- "Fix blockers and check model variants" โ one implementation card for the blocker fixes plus one discovery/research card for config/source verification. A final reviewer card can depend on both.
- "Research docs and implement" โ a docs-research card can run in parallel with a codebase-discovery card; implementation waits only if it truly needs those findings.
- "Analyze this screenshot and find the related code" โ one card to a vision-capable profile for the visual analysis while another searches the codebase.
Words like "also," "finally," or "and" do not automatically imply a dependency. They often mean "make sure this is covered before reporting back." Only link tasks when one card cannot start until another card's output exists.
Show the graph to the user before creating cards. Let them correct it โ including which actual profile name should own each lane.
Step 3 โ Create tasks and link
Use the profile names from Step 0. The example below uses placeholders <profile-A>, <profile-B>, <profile-C> โ replace them with what the user actually has.
t1 = kanban_create(
title="research: Postgres cost vs current",
assignee="<profile-A>", # whichever profile handles research on this setup
body="Compare estimated infrastructure costs, migration costs, and ongoing ops costs over a 3-year window. Sources: AWS/GCP pricing, team time estimates, current Postgres bills from peers.",
tenant=os.environ.get("HERMES_TENANT"),
)["task_id"]
t2 = kanban_create(
title="research: Postgres performance vs current",
assignee="<profile-A>", # same profile, run in parallel
body="Compare query latency, throughput, and scaling characteristics at our expected data volume (~500GB, 10k QPS peak). Sources: benchmark papers, public case studies, pgbench results if easy.",
)["task_id"]
t3 = kanban_create(
title="synthesize migration recommendation",
assignee="<profile-B>", # whichever profile does synthesis/analysis
body="Read the findings from T1 (cost) and T2 (performance). Produce a 1-page recommendation with explicit trade-offs and a go/no-go call.",
parents=[t1, t2],
)["task_id"]
t4 = kanban_create(
title="draft decision memo",
assignee="<profile-C>", # whichever profile drafts user-facing prose
body="Turn the analyst's recommendation into a 2-page memo for the CTO. Match the tone of previous decision memos in the team's knowledge base.",
parents=[t3],
)["task_id"]
parents=[...] gates promotion โ children stay in todo until every parent reaches done, then auto-promote to ready. No manual coordination needed; the dispatcher and dependency engine handle it.
Step 4 โ Complete your own task
If you were spawned as a task yourself (e.g. a planner profile was assigned T0: "investigate Postgres migration"), mark it done with a summary of what you created:
kanban_complete(
summary="decomposed into T1-T4: 2 research lanes in parallel, 1 synthesis on their outputs, 1 prose draft on the recommendation",
metadata={
"task_graph": {
"T1": {"assignee": "<profile-A>", "parents": []},
"T2": {"assignee": "<profile-A>", "parents": []},
"T3": {"assignee": "<profile-B>", "parents": ["T1", "T2"]},
"T4": {"assignee": "<profile-C>", "parents": ["T3"]},
},
},
)
Step 5 โ Report back to the user
Tell them what you created in plain prose, naming the actual profiles you used:
> I've queued 4 tasks:
> - T1 (<profile-A>): cost comparison
> - T2 (<profile-A>): performance comparison, in parallel with T1
> - T3 (<profile-B>): synthesizes T1 + T2 into a recommendation
> - T4 (<profile-C>): turns T3 into a CTO memo
>
> The dispatcher will pick up T1 and T2 now. T3 starts when both finish. You'll get a gateway ping when T4 completes. Use the dashboard or hermes kanban tail <id> to follow along.
Common patterns
Fan-out + fan-in (research โ synthesize): N research-style cards with no parents, one synthesis card with all of them as parents.
Parallel implementation + validation: one implementer card makes the change while one explorer/researcher card verifies config, docs, or source mapping. A reviewer card can depend on both. Do not make the implementer own unrelated verification just because the user mentioned both in one sentence.
Pipeline with gates: planner โ implementer โ reviewer. Each stage's parents=[previous_task]. Reviewer blocks or completes; if reviewer blocks, the operator unblocks with feedback and respawns.
Same-profile queue: N tasks, all assigned to the same profile, no dependencies between them. Dispatcher serializes โ that profile processes them in priority order, accumulating experience in its own memory.
Parallel UI/frontend lanes: When the goal touches multiple independent HTML/CSS/JS files (e.g., a dashboard page and a 2D gather view), fan out to separate subagents per file. Each lane edits its own file, then the orchestrator integrates, fixes cross-file references (theme paths, shared JSON endpoints), and publishes. This avoids merge conflicts in single-file HTML dashboards and keeps each subagent's context focused. See references/parallel-ui-lanes-and-publishing.md for the post-subagent integration checklist and rsync safety notes.
Human-in-the-loop: Any task can kanban_block() to wait for input. Dispatcher respawns after /unblock. The comment thread carries the full context.
Pitfalls
Inventing profile names that don't exist. The dispatcher silently fails to spawn unknown assignees โ the card just sits in ready forever. Always assign to a profile from your Step 0 discovery; ask the user if you're unsure.
Bundling independent lanes into one card. If the user asks for two independent outcomes, create two cards. Example: "fix blockers and check model variants" is not one fixer task; create a fixer/engineer card for the fixes and an explorer/researcher card for the variant check, then optionally gate review on both.
Over-linking because of wording. "Finally check X" may still be parallel with implementation if X is static config, docs, or source discovery. Link it after implementation only when the check depends on the implementation result.
Forgetting dependency links. If the task graph says research -> implement -> review, do not create all tasks as independent ready cards. Use parent links so implement/review cannot run before their inputs exist.
Reassignment vs. new task. If a reviewer blocks with "needs changes," create a NEW task linked from the reviewer's task โ don't re-run the same task with a stern look. The new task is assigned to the original implementer profile.
Argument order for links. kanban_link(parent_id=..., child_id=...) โ parent first. Mixing them up demotes the wrong task to todo.
Ignoring explicit user feedback to keep building infrastructure. When the user says a specific UX issue (legibility, theme switching, movement density) is "immediate priority," treat it as P0 and route it before deeper packaging/architecture work. Infrastructure polish feels productive, but shipping user-visible fixes is what matters. Create cards for the UX feedback first, then resume infrastructure lanes.
Treating status: complete as immutable when user feedback says otherwise. A state.md that says status: complete does not override a user's report that a completion criterion is actually broken. If the user says "theme switching is not working" and the Final Completion Condition requires "working UI theme switcher," the mission is not complete. Reactivate immediately: set status: active, append a reactivation cycle log, and fix the issue. Do not burn cycles on post-complete verification while the user is reporting active defects.
Don't pre-create the whole graph if the shape depends on intermediate findings. If T3's structure depends on what T1 and T2 find, let T3 exist as a "synthesize findings" task whose own first step is to read parent handoffs and plan the rest. Orchestrators can spawn orchestrators.
Tenant inheritance. If HERMES_TENANT is set in your env, pass tenant=os.environ.get("HERMES_TENANT") on every kanban_create call so child tasks stay in the same namespace.
Verifying cross-file references after directory reorganization. When subagents edit HTML/CSS/JS files and the directory structure shifts (e.g., moving files from root into web/dashboard/ and web/gather/), relative asset paths ( themes/default/theme.css, ./ops-data.json) often break. After subagents finish, the orchestrator must grep for href= and src= in moved files and fix relative paths before publishing. Subagents don't know the final publish layout โ the orchestrator does.
Destructive sync wipes needed files. Commands like rsync -av --delete will delete destination files that aren't in the source list. If you publish a directory tree piecemeal (e.g., copy web/dashboard/ first, then web/gather/ separately), --delete on the first rsync will erase the gather files before the second rsync runs. Either list all source paths in a single rsync invocation, or omit --delete and use cp -r / rsync -av without deletion when doing staged copies.
Recovering stuck workers
When a worker profile keeps crashing, hallucinating, or getting blocked by its own mistakes (usually: wrong model, missing skill, broken credential), the kanban dashboard flags the task with a โ badge and opens a Recovery section in the drawer. Three primary actions:
1. Reclaim (or hermes kanban reclaim <task_id>) โ abort the running worker immediately and reset the task to ready. The existing claim TTL is ~15 min; this is the fast path out.
2. Reassign (or hermes kanban reassign <task_id> <new-profile> --reclaim) โ switch the task to a different profile (one that exists on this setup) and let the dispatcher pick it up with a fresh worker.
3. Change profile model โ the dashboard prints a copy-paste hint for hermes -p <profile> model since profile config lives on disk; edit it in a terminal, then Reclaim to retry with the new model.
Hallucination warnings appear on tasks where a worker's kanban_complete(created_cards=[...]) claim included card ids that don't exist or weren't created by the worker's profile (the gate blocks the completion), or where the free-form summary references t_<hex> ids that don't resolve (advisory prose scan, non-blocking). Both produce audit events that persist even after recovery actions โ the trail stays for debugging.
The user has provided the following instruction alongside the skill invocation: [IMPORTANT: You are running as a scheduled cron job. DELIVERY: Your final response will be automatically delivered to the user โ do NOT use send_message or try to deliver the output yourself. Just produce your report/output as your final response and the system handles the rest. SILENT: If there is genuinely nothing new to report, respond with exactly "[SILENT]" (nothing else) to suppress delivery. Never combine [SILENT] with content โ either report your findings normally, or say [SILENT] and nothing more.]
You are the 15-minute Orchestrator for Son's Autonomous Agent Lab v1, reporting to Discord channel ID 1505805763824586952.
Durable state path: /Users/jooho-hermes/.hermes/autonomous-agent-lab/state.md
Working directory for experiment artifacts: /Users/jooho-hermes/.hermes/autonomous-agent-lab/
Preferred published web root: /Users/jooho-hermes/hermes-web/agent-pets/
Top-level directive from Son:
- The project has evolved from a personal dashboard into an INSTALLABLE PRODUCT that external Hermes users can deploy.
- The final target is a self-contained, configurable, publishable solution: "Hermes Pixel Pet Ops Office".
- Do NOT shrink the mission into a small static MVP and autonomously stop.
- The Gather.town-style 2D spatial office is a first-class feature, not a side page.
Latest UX feedback from Son (treat as immediate priority before deeper packaging work):
- Details are hard for a human to understand. Add human-first summaries, plain-language labels, and progressive disclosure: summary first, technical details second.
- Gather Town version has too many agents roaming around. Reduce default movement, add density/speed controls, cluster agents by room/task, and add focus/calm mode.
- Theme switching is not visibly working. Implement real UI theme switcher with persistence and clear visual theme changes.
Key product requirements (installable solution level):
1. Config-driven architecture: all paths, URLs, colors, names, room layouts via config.yaml. No hardcoded references to jooho-hermes.
2. Self-contained package: clear directory structure (src/, web/, config/, docs/, scripts/), install script, requirements.txt.
3. Pluggable data adapter: support multiple backends via plugin architecture.
4. Themeable frontend: CSS variables driven from config, swappable themes, plus a working UI theme switcher.
5. Multi-tenant ready: works for any Hermes instance.
6. Build/Deploy ready: Dockerfile or docker-compose, or clear static-server setup.
7. Documentation: README, architecture docs, configuration reference, contributor guide.
8. Human-comprehensible UX: plain-language summaries and progressive disclosure for technical detail.
9. Gather.town calm mode: adjustable movement density/speed and less chaotic defaults.
10. Versioned releases: CHANGELOG.md, semantic versioning, release packaging.
Mission model:
- Read state.md first before doing anything else.
- If state.md says
status: inactive or has no Current Mission, do not invent work. Return exactly: ๐ก Autonomous Agent Lab ๋๊ธฐ์ค โ Son์ด ํธ๋ฆฌ๊ฑฐ/๋ฏธ์
์ ์ฃผ๋ฉด 15๋ถ ์ฌ์ดํด์ ์์ํฉ๋๋ค.
- If state.md says
status: active, run one bounded 15-minute cycle toward the full installable solution.
- If state.md says
status: complete, verify that the Final Completion Condition in state.md is truly met. If it is not fully met, reactivate or report that state needs correction.
Cycle procedure when active:
1. Read state.md first. Extract current mission, constraints, previous cycle log, and Final Completion Condition.
2. Decide the next smallest useful step toward installable solution quality. Focus on: architecture, configurability, documentation, and clean separation of concerns.
3. Use delegate_task for independent subagent lanes when helpful.
4. Prefer concrete progress: refactor to config-driven, add install scripts, create docs, add Docker support, theme system, plugin architecture.
5. Update state.md with a new cycle log entry before final reporting.
6. Completion rule: only set status: complete when every item under state.md Final Completion Condition is satisfied. A non-installable MVP is not complete.
7. Stop/block only if Son explicitly stops/redirects, a safety boundary is reached, or a hard blocker needs Son's decision.
Link requirement (never forget):
- Every cycle report MUST include at least one direct viewable link to the published dashboard/artifact.
- The canonical URL:
http://hermes-mac-mini.tail46b3c6.ts.net:8099/agent-pets/
- Include gather town URL too:
http://hermes-mac-mini.tail46b3c6.ts.net:8099/agent-pets/gather/
Final Discord message format:
[Autonomous Agent Lab v1 / Cycle N]
๋ชฉํ:
์ํ:
๊ฒฐ๊ณผ:
๊ฒ์ฆ:
๋ค์:
์ํ:
Safety/quality rules:
- Do not handle secrets, passwords, API keys, payment, permission dialogs, or destructive commands.
- Do not claim completion without updating state.md.
- Do not rely on Discord history as durable state.
- Do not spam raw logs; summarize lane outputs and verification.
- Keep working in /Users/jooho-hermes/.hermes/autonomous-agent-lab/ and publish only to /Users/jooho-hermes/hermes-web/agent-pets/ unless the state file says otherwise.
Design/UX priorities:
- Mobile responsiveness is first-class.
- Character animation/movement is desired.
- Every cycle report must include published links.
- This is now a product engineering mission. Architecture, configurability, and documentation matter as much as visuals.
Response
[Autonomous Agent Lab v1 / Cycle 81]
๋ชฉํ:
- ์ธ๋ถ ์ฌ์ฉ์๊ฐ ์ค์น ํ ๋ฐ๋ก ๊ฒ์ฆํ ์ ์๋ live smoke-test ์คํฌ๋ฆฝํธ ์ถ๊ฐ
- ๋น๋ ๋ฒ์ b81๋ก ์ผ๊ด ๊ฐฑ์ ๋ฐ ์ ์ฒด ํ์ดํ๋ผ์ธ ์ฌ๊ฒ์ฆ
- Son์ ๋ธ๋ผ์ฐ์ ํ์ธ ๋๊ธฐ ์ค์๋ ์ ํ ํ์ง/๋ฐฐํฌ ๊ฒ์ฆ ๋๊ตฌ๋ฅผ ์ง์ ๋ณด๊ฐ
์ํ:
1. scripts/smoke-test.sh ์ ๊ท ์์ฑ
config.yaml์ server.public_url์ ์ฝ์ด config-driven์ผ๋ก ๋์
- dashboard / gather / dashboard.js / gather.js / ops-data.json / health.json 6๊ฐ ์๋ํฌ์ธํธ curl ๊ฒ์ฆ
- human-first summary (
human-summary), ํ
๋ง ์ค์์ฒ (switchTheme), Gather calm mode (hppo-gather-calm), schema_version, agents, health status ๋ฑ ํต์ฌ ๋ง์ปค ํ์ธ
grep -q + pipefail SIGPIPE ๋ฌธ์ ๋ฅผ ํํผํ๋ curl_grep ํฌํผ ์ ์ฉ
degraded ์ํ๋ ์ ์ ์ด์์ผ๋ก ์ธ์ (third-party ํ๊ฒฝ์์ ๋๋ฌด ์๊ฒฉํ์ง ์๊ฒ)
2. ๋น๋ b81 / ์บ์ v28 ์ผ๊ด ๊ฐฑ์
- dashboard & gather HTML:
data-build="81", b81, ?v=81, __HPPO_BUILD__ = 81
- Service Worker:
CACHE_NAME = 'pixel-pet-ops-v28'
3. scripts/test.sh์ Smoke Test ์น์
์ถ๊ฐ (2๊ฐ ์ฒดํฌ) โ ์ด 139๊ฐ ํ
์คํธ
4. ์ ์ฒด ํ์ดํ๋ผ์ธ ์คํ: adapter โ test(139/139) โ validate(21/21) โ publish โ smoke-test(16/16)
๊ฒฐ๊ณผ:
- Dashboard: http://hermes-mac-mini.tail46b3c6.ts.net:8099/agent-pets/
- Gather Town: http://hermes-mac-mini.tail46b3c6.ts.net:8099/agent-pets/gather/
- Smoke-test ์คํฌ๋ฆฝํธ ์ถ๊ฐ ์๋ฃ:
bash scripts/smoke-test.sh config.yaml ๋ก ์ฆ์ ๊ฒ์ฆ ๊ฐ๋ฅ
- ๋น๋ ๋ฐฐ์ง:
v1.4.4 ยท b81
ops-data.json / health.json ์ ์ ๋: < 60s
refresh.err.log: ์ฌ์ ํ ๋น์ด ์์ (์ด๋ํฐ ์ ์)
๊ฒ์ฆ:
- ํตํฉ ํ
์คํธ: 139 passed, 0 failed
- ์ค์น ๊ฒ์ฆ: 21 passed, 0 warned, 0 critical
- ์ค๋ชจํฌ ํ
์คํธ: 16 passed, 0 failed (dashboard 200, gather 200, JS/CSS ๋ง์ปค ๋ชจ๋ ํ์ธ)
- ํ๋์ฝ๋ฉ ์ฐธ์กฐ: source ์ ์ฒด 0๊ฑด
- ์ด๋ํฐ ์ถ๋ ฅ: schema 1.4, agents 32, cron_jobs 15, sessions 20, events 16
๋ค์:
- Son์ด ๋์๋ณด๋์ ์ ์ํด ๋ค์ 3๊ฐ์ง๋ฅผ ์ง์ ํ์ธํด ์ฃผ์๋ฉด ์๋ฃ ์ฒ๋ฆฌ ๊ฐ๋ฅํฉ๋๋ค:
1. ํ
๋ง ์ ํ (hero ํจ๋์์ ๐จ ํ
๋ง ์ ํ)
2. Gather Town calm mode (๊ธฐ๋ณธ 5๋ง๋ฆฌ, ๋๋ฆฐ ์ด๋)
3. Inspector human-first view + scroll-to-top ๋ฒํผ(๋ชจ๋ฐ์ผ)
- ์ smoke-test ์คํฌ๋ฆฝํธ๋ ํ ๋ฒ ์คํํด ๋ณด์ธ์:
bash scripts/smoke-test.sh config.yaml
- ๋ง์กฑ์ค๋ฌ์ฐ๋ฉด
status: complete๋ก ์ ํํ๊ฒ ์ต๋๋ค.
์ํ:
status: active ์ ์ง
- 11๊ฐ Final Completion Condition ๋ชจ๋ ์ถฉ์กฑ
- Docker live ๋น๋๋ง ํ๊ฒฝ ์ ์ฝ์ผ๋ก ๋ฏธ๊ฒ์ฆ (Dockerfile/docker-compose๋ ํฌํจ๋จ)
- Son์ ๋ธ๋ผ์ฐ์ ์ฌ์ด๋ ํ์ธ ๋๊ธฐ ์ค
|
| 2026-05-20 04-07-04 |
85,318 chars |
2026-05-20_04-07-04.md |
Cron Job: autonomous-agent-lab-v1-orchestrator
Job ID: 35127ff89556
Run Time: 2026-05-20 04:07:04
Schedule: every 15m
Prompt
[IMPORTANT: The user has invoked the "hermes-agent" skill, indicating they want you to follow its instructions. The full skill content is loaded below.]
---
name: hermes-agent
description: "Configure, extend, or contribute to Hermes Agent."
version: 2.1.0
author: Hermes Agent + Teknium
license: MIT
platforms: [linux, macos, windows]
metadata:
hermes:
tags: [hermes, setup, configuration, multi-agent, spawning, cli, gateway, development]
homepage: https://github.com/NousResearch/hermes-agent
related_skills: [claude-code, codex, opencode]
---
Hermes Agent
Hermes Agent is an open-source AI agent framework by Nous Research that runs in your terminal, messaging platforms, and IDEs. It belongs to the same category as Claude Code (Anthropic), Codex (OpenAI), and OpenClaw โ autonomous coding and task-execution agents that use tool calling to interact with your system. Hermes works with any LLM provider (OpenRouter, Anthropic, OpenAI, DeepSeek, local models, and 15+ others) and runs on Linux, macOS, and WSL.
What makes Hermes different:
- Self-improving through skills โ Hermes learns from experience by saving reusable procedures as skills. When it solves a complex problem, discovers a workflow, or gets corrected, it can persist that knowledge as a skill document that loads into future sessions. Skills accumulate over time, making the agent better at your specific tasks and environment.
- Persistent memory across sessions โ remembers who you are, your preferences, environment details, and lessons learned. Pluggable memory backends (built-in, Honcho, Mem0, and more) let you choose how memory works.
- Multi-platform gateway โ the same agent runs on Telegram, Discord, Slack, WhatsApp, Signal, Matrix, Email, and 10+ other platforms with full tool access, not just chat.
- Provider-agnostic โ swap models and providers mid-workflow without changing anything else. Credential pools rotate across multiple API keys automatically.
- Profiles โ run multiple independent Hermes instances with isolated configs, sessions, skills, and memory.
- Extensible โ plugins, MCP servers, custom tools, webhook triggers, cron scheduling, and the full Python ecosystem.
People use Hermes for software development, research, system administration, data analysis, content creation, home automation, and anything else that benefits from an AI agent with persistent context and full system access.
This skill helps you work with Hermes Agent effectively โ setting it up, configuring features, spawning additional agent instances, troubleshooting issues, finding the right commands and settings, and understanding how the system works when you need to extend or contribute to it.
Docs: https://hermes-agent.nousresearch.com/docs/
Quick Start
Install
curl -fsSL https://raw.githubusercontent.com/NousResearch/hermes-agent/main/scripts/install.sh | bash
Interactive chat (default)
hermes
Single query
hermes chat -q "What is the capital of France?"
Setup wizard
hermes setup
Change model/provider
hermes model
Check health
hermes doctor
---
CLI Reference
Global Flags
hermes [flags] [command]
--version, -V Show version
--resume, -r SESSION Resume session by ID or title
--continue, -c [NAME] Resume by name, or most recent session
--worktree, -w Isolated git worktree mode (parallel agents)
--skills, -s SKILL Preload skills (comma-separate or repeat)
--profile, -p NAME Use a named profile
--yolo Skip dangerous command approval
--pass-session-id Include session ID in system prompt
No subcommand defaults to chat.
Chat
hermes chat [flags]
-q, --query TEXT Single query, non-interactive
-m, --model MODEL Model (e.g. anthropic/claude-sonnet-4)
-t, --toolsets LIST Comma-separated toolsets
--provider PROVIDER Force provider (openrouter, anthropic, nous, etc.)
-v, --verbose Verbose output
-Q, --quiet Suppress banner, spinner, tool previews
--checkpoints Enable filesystem checkpoints (/rollback)
--source TAG Session source tag (default: cli)
Configuration
hermes setup [section] Interactive wizard (model|terminal|gateway|tools|agent)
hermes model Interactive model/provider picker
hermes config View current config
hermes config edit Open config.yaml in $EDITOR
hermes config set KEY VAL Set a config value
hermes config path Print config.yaml path
hermes config env-path Print .env path
hermes config check Check for missing/outdated config
hermes config migrate Update config with new options
hermes doctor [--fix] Check dependencies and config
Credential Pools
hermes auth add Interactive credential wizard (oauth, api-key)
hermes auth list [PROVIDER] List pooled credentials
hermes auth remove P INDEX Remove by provider + index
hermes auth reset PROVIDER Clear exhaustion status
hermes logout Clear stored auth
Tools & Skills
hermes tools Interactive tool enable/disable (curses UI)
hermes tools list Show all tools and status
hermes tools enable NAME Enable a toolset
hermes tools disable NAME Disable a toolset
hermes skills list List installed skills
hermes skills search QUERY Search the skills hub
hermes skills install ID Install a skill (ID can be a hub identifier OR a direct https://โฆ/SKILL.md URL; pass --name to override when frontmatter has no name)
hermes skills inspect ID Preview without installing
hermes skills config Enable/disable skills per platform
hermes skills check Check for updates
hermes skills update Update outdated skills
hermes skills uninstall N Remove a hub skill
hermes skills publish PATH Publish to registry
hermes skills browse Browse all available skills
hermes skills tap add REPO Add a GitHub repo as skill source
MCP Servers
hermes mcp serve Run Hermes as an MCP server
hermes mcp add NAME Add an MCP server (--url or --command)
hermes mcp remove NAME Remove an MCP server
hermes mcp list List configured servers
hermes mcp test NAME Test connection
hermes mcp configure NAME Toggle tool selection
Gateway (Messaging Platforms)
hermes gateway run Start gateway foreground
hermes gateway install Install as background service
hermes gateway start/stop Control the service
hermes gateway restart Restart the service
hermes gateway status Check status
hermes gateway setup Configure platforms
Supported platforms: Telegram, Discord, Slack, WhatsApp, Signal, Email, SMS, Matrix, Mattermost, Home Assistant, DingTalk, Feishu, WeCom, BlueBubbles (iMessage), Weixin (WeChat), API Server, Webhooks. Open WebUI connects via the API Server adapter.
Platform docs: https://hermes-agent.nousresearch.com/docs/user-guide/messaging/
Discord-specific walkthrough (token, intents, service install, access control): see references/discord-gateway-setup.md in this skill.
- Per-channel personas and skill bindings: see
references/gateway-channel-personas.md (works on Discord, Slack, Telegram, Mattermost, Matrix).
- For long-running Discord-first operations, purpose-specific channel routing, periodic summaries, weekly Dreaming/audit reports, and log-safety patterns: see
references/discord-operating-planes.md.
- For broad Hermes/LifeOS/SQAF ecosystem audits (cron inventory, live services, dashboards, provider/model warnings, and control-plane gaps), see
references/ecosystem-audit.md.
Sessions
hermes sessions list List recent sessions
hermes sessions browse Interactive picker
hermes sessions export OUT Export to JSONL
hermes sessions rename ID T Rename a session
hermes sessions delete ID Delete a session
hermes sessions prune Clean up old sessions (--older-than N days)
hermes sessions stats Session store statistics
For browser-based viewing of existing Hermes CLI/Discord/cron session transcripts, prefer a lightweight static export from ~/.hermes/state.db into a private web root instead of assuming Open WebUI can browse Hermes' native session store. See references/hermes-session-static-web-viewer.md for the SQLite schema, static HTML export workflow, redaction/truncation cautions, and the user's Mac mini deployment (/hermes-sessions/ under the Tailscale-only ~/hermes-web site).
For cron job execution history, the same static-export pattern applies to ~/.hermes/cron/jobs.json and ~/.hermes/cron/output/{job_id}/*.md. See references/cron-history-web-viewer.md for the cron data model, schedule-dict pitfall, and the user's deployed /cron-history/ dashboard.
Cron Jobs
hermes cron list List jobs (--all for disabled)
hermes cron create SCHED Create: '30m', 'every 2h', '0 9 *'
hermes cron edit ID Edit schedule, prompt, delivery
hermes cron pause/resume ID Control job state
hermes cron run ID Trigger on next tick
hermes cron remove ID Delete a job
hermes cron status Scheduler status
For bounded autonomous lab/orchestrator cron jobs that use file-based state, subagent lanes, artifact publishing, and status transitions (active โ complete/blocked/inactive), see references/autonomous-agent-lab-cron-cycle.md. A reusable verification script template lives at scripts/verify-completion-template.py.
For a worked example of evolving an autonomous lab into a config-driven, themeable, Docker-ready installable product, see references/autonomous-lab-product-architecture.md. For CI, integration testing, pluggable adapter architecture, bounded cycle orchestration, and post-productization patterns, see references/product-maturity-patterns.md.
For the final completion verification checklist โ the explicit audit pattern to run before marking status: complete on an installable-solution mission, see references/autonomous-lab-completion-verification.md.
For the reactivation protocol when a completed lab receives new P0 feedback or the user contradicts a completion claim, see references/autonomous-lab-reactivation-protocol.md.
For the config/CHANGELOG version drift pitfall that occurs when autonomous labs evolve over many cycles, and for the related source vs. published file drift problem where the live web root diverges from the project source, see references/autonomous-lab-version-drift.md.
For adding historical trend tracking (SQLite-backed agent status transitions + vanilla JS SVG sparklines) to an autonomous lab dashboard, see references/history-tracking-sparkline-pattern.md.
For preventing unbounded SQLite growth in long-running labs, see references/autonomous-lab-data-retention.md โ covers automatic per-refresh pruning and a standalone manual prune utility.
- For reusable dashboard UX patterns (onboarding tours, data freshness badges, keyboard shortcuts, progressive disclosure inspectors, cross-linking between views, inspector deep-linking), see
references/dashboard-ux-patterns.md.
For the daily operational briefing modal โ a one-screen human-first summary of agent counts, blocked work, recent events, health status, and upcoming cron schedules โ see references/daily-briefing-modal.md.
For the aggressive human-first inspector refinement โ when users report that details are hard to understand and the fix is to strip technical labels from the default view โ see references/progressive-disclosure-human-first.md.
For programmatic verification of CSS custom-property theme systems โ catching scoping bugs, confirming theme distinctness, and validating JS switching logic โ see references/theme-system-verification.md.
- For Son's Discord-first autonomous experiments where a channel hosts a repeated multi-agent loop, use the Autonomous Discord Agent Lab pattern: create file-based durable state, a paused cron orchestrator delivered to
discord:<channel_id>, then activate it from a user mission trigger. See references/autonomous-discord-agent-lab.md.
- For verifying that a release package (
tar.gz) is actually installable by third parties and contains no stale artifacts or hardcoded references, see references/release-package-verification.md and the reusable script at scripts/release-verify.sh.
Webhooks
hermes webhook subscribe N Create route at /webhooks/<name>
hermes webhook list List subscriptions
hermes webhook remove NAME Remove a subscription
hermes webhook test NAME Send a test POST
Profiles
hermes profile list List all profiles
hermes profile create NAME Create (--clone, --clone-all, --clone-from)
hermes profile use NAME Set sticky default
hermes profile delete NAME Delete a profile
hermes profile show NAME Show details
hermes profile alias NAME Manage wrapper scripts
hermes profile rename A B Rename a profile
hermes profile export NAME Export to tar.gz
hermes profile import FILE Import from archive
Credential Pools
hermes auth add Interactive credential wizard
hermes auth list [PROVIDER] List pooled credentials
hermes auth remove P INDEX Remove by provider + index
hermes auth reset PROVIDER Clear exhaustion status
Other
hermes insights [--days N] Usage analytics
hermes update Update to latest version
hermes pairing list/approve/revoke DM authorization
hermes plugins list/install/remove Plugin management
hermes honcho setup/status Honcho memory integration (requires honcho plugin)
hermes memory setup/status/off Memory provider config
hermes completion bash|zsh Shell completions
hermes acp ACP server (IDE integration)
hermes claw migrate Migrate from OpenClaw
hermes uninstall Uninstall Hermes
---
Slash Commands (In-Session)
Type these during an interactive chat session. New commands land fairly
often; if something below looks stale, run /help in-session for the
authoritative list or see the [live slash commands reference](https://hermes-agent.nousresearch.com/docs/reference/slash-commands).
The registry of record is hermes_cli/commands.py โ every consumer
(autocomplete, Telegram menu, Slack mapping, /help) derives from it.
Session Control
/new (/reset) Fresh session
/clear Clear screen + new session (CLI)
/retry Resend last message
/undo Remove last exchange
/title [name] Name the session
/compress Manually compress context
/stop Kill background processes
/rollback [N] Restore filesystem checkpoint
/snapshot [sub] Create or restore state snapshots of Hermes config/state (CLI)
/background <prompt> Run prompt in background
/queue <prompt> Queue for next turn
/steer <prompt> Inject a message after the next tool call without interrupting
/agents (/tasks) Show active agents and running tasks
/resume [name] Resume a named session
/goal [text|sub] Set a standing goal Hermes works on across turns until achieved
(subcommands: status, pause, resume, clear)
/redraw Force a full UI repaint (CLI)
Configuration
/config Show config (CLI)
/model [name] Show or change model
/personality [name] Set personality
/reasoning [level] Set reasoning (none|minimal|low|medium|high|xhigh|show|hide)
/verbose Cycle: off โ new โ all โ verbose
/voice [on|off|tts] Voice mode
/yolo Toggle approval bypass
/busy [sub] Control what Enter does while Hermes is working (CLI)
(subcommands: queue, steer, interrupt, status)
/indicator [style] Pick the TUI busy-indicator style (CLI)
(styles: kaomoji, emoji, unicode, ascii)
/footer [on|off] Toggle gateway runtime-metadata footer on final replies
/skin [name] Change theme (CLI)
/statusbar Toggle status bar (CLI)
Tools & Skills
/tools Manage tools (CLI)
/toolsets List toolsets (CLI)
/skills Search/install skills (CLI)
/skill <name> Load a skill into session
/reload-skills Re-scan ~/.hermes/skills/ for added/removed skills
/reload Reload .env variables into the running session (CLI)
/reload-mcp Reload MCP servers
/cron Manage cron jobs (CLI)
/curator [sub] Background skill maintenance (status, run, pin, archive, โฆ)
/kanban [sub] Multi-profile collaboration board (tasks, links, comments)
/plugins List plugins (CLI)
Gateway
/approve Approve a pending command (gateway)
/deny Deny a pending command (gateway)
/restart Restart gateway (gateway)
/sethome Set current chat as home channel (gateway)
/update Update Hermes to latest (gateway)
/topic [sub] Enable or inspect Telegram DM topic sessions (gateway)
/platforms (/gateway) Show platform connection status (gateway)
Utility
/branch (/fork) Branch the current session
/fast Toggle priority/fast processing
/browser Open CDP browser connection
/history Show conversation history (CLI)
/save Save conversation to file (CLI)
/copy [N] Copy the last assistant response to clipboard (CLI)
/paste Attach clipboard image (CLI)
/image Attach local image file (CLI)
Info
/help Show commands
/commands [page] Browse all commands (gateway)
/usage Token usage
/insights [days] Usage analytics
/gquota Show Google Gemini Code Assist quota usage (CLI)
/status Session info (gateway)
/profile Active profile info
/debug Upload debug report (system info + logs) and get shareable links
Exit
/quit (/exit, /q) Exit CLI
---
Key Paths & Config
~/.hermes/config.yaml Main configuration
~/.hermes/.env API keys and secrets
$HERMES_HOME/skills/ Installed skills
~/.hermes/sessions/ Session transcripts
~/.hermes/logs/ Gateway and error logs
~/.hermes/auth.json OAuth tokens and credential pools
~/.hermes/hermes-agent/ Source code (if git-installed)
Profiles use ~/.hermes/profiles/<name>/ with the same layout.
Config Sections
Edit with hermes config edit or hermes config set section.key value.
| Section | Key options |
|---------|-------------|
| model | default, provider, base_url, api_key, context_length |
| agent | max_turns (90), tool_use_enforcement |
| terminal | backend (local/docker/ssh/modal), cwd, timeout (180) |
| compression | enabled, threshold (0.50), target_ratio (0.20) |
| display | skin, tool_progress, show_reasoning, show_cost |
| stt | enabled, provider (local/groq/openai/mistral) |
| tts | provider (edge/elevenlabs/openai/minimax/mistral/neutts) |
| memory | memory_enabled, user_profile_enabled, provider |
| security | tirith_enabled, website_blocklist |
| delegation | model, provider, base_url, api_key, max_iterations (50), reasoning_effort |
| checkpoints | enabled, max_snapshots (50) |
| fallback_model | provider, model, base_url, key_env |
Fallback Providers
Hermes can automatically fail over to a backup provider:model when the primary is unavailable. This is turn-scoped โ each new user message starts with the primary restored; fallback only activates mid-turn when the primary fails.
Configuration ( ~/.hermes/config.yaml):
fallback_model:
provider: opencode-go
model: kimi-k2.6
Or use the interactive manager:
hermes fallback add # interactive picker
hermes fallback list # show fallback chain
hermes fallback remove # remove by index
Legacy note: fallback_model (singular) is the legacy single-fallback key. fallback_providers (list) supports multiple ordered fallbacks. When both exist, fallback_providers takes priority.
Trigger conditions (after exhausting retries where applicable):
- Rate limits (HTTP 429)
- Server errors (HTTP 500, 502, 503)
- Auth failures (HTTP 401, 403) โ immediately
- Not found (HTTP 404) โ immediately
- Invalid / empty responses repeatedly
Supported providers include all standard providers (OpenRouter, Anthropic, OpenCode Go/ Zen, Kimi, etc.) plus custom endpoints with base_url + key_env. Full provider docs: https://hermes-agent.nousresearch.com/docs/integrations/providers
Limitations:
- Subagent delegation does not inherit fallback config
- Cron jobs do not use fallback (use per-job provider/model overrides)
- Auxiliary tasks (vision, compression, etc.) use their own
auxiliary.* provider chain
For a deep-dive with worked examples and model lists, see references/fallback-providers.md.
Full config reference: https://hermes-agent.nousresearch.com/docs/user-guide/configuration
Providers
20+ providers supported. Set via hermes model or hermes setup.
| Provider | Auth | Key env var |
|----------|------|-------------|
| OpenRouter | API key | OPENROUTER_API_KEY |
| Anthropic | API key | ANTHROPIC_API_KEY |
| Nous Portal | OAuth | hermes auth |
| OpenAI Codex | OAuth | hermes auth |
| GitHub Copilot | Token | COPILOT_GITHUB_TOKEN |
| Google Gemini | API key | GOOGLE_API_KEY or GEMINI_API_KEY |
| DeepSeek | API key | DEEPSEEK_API_KEY |
| xAI / Grok | API key | XAI_API_KEY |
| Hugging Face | Token | HF_TOKEN |
| Z.AI / GLM | API key | GLM_API_KEY |
| MiniMax | API key | MINIMAX_API_KEY |
| MiniMax CN | API key | MINIMAX_CN_API_KEY |
| Kimi / Moonshot | API key | KIMI_API_KEY |
| Alibaba / DashScope | API key | DASHSCOPE_API_KEY |
| Xiaomi MiMo | API key | XIAOMI_API_KEY |
| Kilo Code | API key | KILOCODE_API_KEY |
| AI Gateway (Vercel) | API key | AI_GATEWAY_API_KEY |
| OpenCode Zen | API key | OPENCODE_ZEN_API_KEY |
| OpenCode Go | API key | OPENCODE_GO_API_KEY |
| Qwen OAuth | OAuth | hermes auth add qwen-oauth |
| Custom endpoint | Config | model.base_url + model.api_key in config.yaml |
| GitHub Copilot ACP | External | COPILOT_CLI_PATH or Copilot CLI |
Full provider docs: https://hermes-agent.nousresearch.com/docs/integrations/providers
Toolsets
Enable/disable via hermes tools (interactive) or hermes tools enable/disable NAME.
| Toolset | What it provides |
|---------|-----------------|
| web | Web search and content extraction |
| search | Web search only (subset of web) |
| browser | Browser automation (Browserbase, Camofox, or local Chromium) |
| terminal | Shell commands and process management |
| file | File read/write/search/patch |
| code_execution | Sandboxed Python execution |
| vision | Image analysis |
| image_gen | AI image generation |
| video | Video analysis and generation |
| tts | Text-to-speech |
| skills | Skill browsing and management |
| memory | Persistent cross-session memory |
| session_search | Search past conversations |
| delegation | Subagent task delegation |
| cronjob | Scheduled task management |
| clarify | Ask user clarifying questions |
| messaging | Cross-platform message sending |
| todo | In-session task planning and tracking |
| kanban | Multi-agent work-queue tools (gated to workers) |
| debugging | Extra introspection/debug tools (off by default) |
| safe | Minimal, low-risk toolset for locked-down sessions |
| spotify | Spotify playback and playlist control |
| homeassistant | Smart home control (off by default) |
| discord | Discord integration tools |
| discord_admin | Discord admin/moderation tools |
| feishu_doc | Feishu (Lark) document tools |
| feishu_drive | Feishu (Lark) drive tools |
| yuanbao | Yuanbao integration tools |
| rl | Reinforcement learning tools (off by default) |
| moa | Mixture of Agents (off by default) |
Full enumeration lives in toolsets.py as the TOOLSETS dict; _HERMES_CORE_TOOLS is the default bundle most platforms inherit from.
Tool changes take effect on /reset (new session). They do NOT apply mid-conversation to preserve prompt caching.
---
Security & Privacy Toggles
Common "why is Hermes doing X to my output / tool calls / commands?" toggles โ and the exact commands to change them. Most of these need a fresh session (/reset in chat, or start a new hermes invocation) because they're read once at startup.
Secret redaction in tool output
Secret redaction is off by default โ tool output (terminal stdout, read_file, web content, subagent summaries, etc.) passes through unmodified. If the user wants Hermes to auto-mask strings that look like API keys, tokens, and secrets before they enter the conversation context and logs:
hermes config set security.redact_secrets true # enable globally
Restart required. security.redact_secrets is snapshotted at import time โ toggling it mid-session (e.g. via export HERMES_REDACT_SECRETS=true from a tool call) will NOT take effect for the running process. Tell the user to run hermes config set security.redact_secrets true in a terminal, then start a new session. This is deliberate โ it prevents an LLM from flipping the toggle on itself mid-task.
Disable again with:
hermes config set security.redact_secrets false
PII redaction in gateway messages
Separate from secret redaction. When enabled, the gateway hashes user IDs and strips phone numbers from the session context before it reaches the model:
hermes config set privacy.redact_pii true # enable
hermes config set privacy.redact_pii false # disable (default)
Command approval prompts
By default (approvals.mode: manual), Hermes prompts the user before running shell commands flagged as destructive (rm -rf, git reset --hard, etc.). The modes are:
manual โ always prompt (default)
smart โ use an auxiliary LLM to auto-approve low-risk commands, prompt on high-risk
off โ skip all approval prompts (equivalent to --yolo)
hermes config set approvals.mode smart # recommended middle ground
hermes config set approvals.mode off # bypass everything (not recommended)
Per-invocation bypass without changing config:
hermes --yolo โฆ
export HERMES_YOLO_MODE=1
Note: YOLO / approvals.mode: off does NOT turn off secret redaction. They are independent.
Shell hooks allowlist
Some shell-hook integrations require explicit allowlisting before they fire. Managed via ~/.hermes/shell-hooks-allowlist.json โ prompted interactively the first time a hook wants to run.
Disabling the web/browser/image-gen tools
To keep the model away from network or media tools entirely, open hermes tools and toggle per-platform. Takes effect on next session (/reset). See the Tools & Skills section above.
---
Voice & Transcription
STT (Voice โ Text)
Voice messages from messaging platforms are auto-transcribed.
Provider priority (auto-detected):
1. Local faster-whisper โ free, no API key: pip install faster-whisper
2. Groq Whisper โ free tier: set GROQ_API_KEY
3. OpenAI Whisper โ paid: set VOICE_TOOLS_OPENAI_KEY
4. Mistral Voxtral โ set MISTRAL_API_KEY
Config:
stt:
enabled: true
provider: local # local, groq, openai, mistral
local:
model: base # tiny, base, small, medium, large-v3
TTS (Text โ Voice)
| Provider | Env var | Free? |
|----------|---------|-------|
| Edge TTS | None | Yes (default) |
| ElevenLabs | ELEVENLABS_API_KEY | Free tier |
| OpenAI | VOICE_TOOLS_OPENAI_KEY | Paid |
| MiniMax | MINIMAX_API_KEY | Paid |
| Mistral (Voxtral) | MISTRAL_API_KEY | Paid |
| NeuTTS (local) | None (pip install neutts[all] + espeak-ng) | Free |
Voice commands: /voice on (voice-to-voice), /voice tts (always voice), /voice off.
---
Spawning Additional Hermes Instances
Run additional Hermes processes as fully independent subprocesses โ separate sessions, tools, and environments.
When to Use This vs delegate_task
| | delegate_task | Spawning hermes process |
|-|-----------------|--------------------------|
| Isolation | Separate conversation, shared process | Fully independent process |
| Duration | Minutes (bounded by parent loop) | Hours/days |
| Tool access | Subset of parent's tools | Full tool access |
| Interactive | No | Yes (PTY mode) |
| Use case | Quick parallel subtasks | Long autonomous missions |
One-Shot Mode
terminal(command="hermes chat -q 'Research GRPO papers and write summary to ~/research/grpo.md'", timeout=300)
Background for long tasks:
terminal(command="hermes chat -q 'Set up CI/CD for ~/myapp'", background=true)
Interactive PTY Mode (via tmux)
Hermes uses prompt_toolkit, which requires a real terminal. Use tmux for interactive spawning:
Start
terminal(command="tmux new-session -d -s agent1 -x 120 -y 40 'hermes'", timeout=10)
Wait for startup, then send a message
terminal(command="sleep 8 && tmux send-keys -t agent1 'Build a FastAPI auth service' Enter", timeout=15)
Read output
terminal(command="sleep 20 && tmux capture-pane -t agent1 -p", timeout=5)
Send follow-up
terminal(command="tmux send-keys -t agent1 'Add rate limiting middleware' Enter", timeout=5)
Exit
terminal(command="tmux send-keys -t agent1 '/exit' Enter && sleep 2 && tmux kill-session -t agent1", timeout=10)
Multi-Agent Coordination
Agent A: backend
terminal(command="tmux new-session -d -s backend -x 120 -y 40 'hermes -w'", timeout=10)
terminal(command="sleep 8 && tmux send-keys -t backend 'Build REST API for user management' Enter", timeout=15)
Agent B: frontend
terminal(command="tmux new-session -d -s frontend -x 120 -y 40 'hermes -w'", timeout=10)
terminal(command="sleep 8 && tmux send-keys -t frontend 'Build React dashboard for user management' Enter", timeout=15)
Check progress, relay context between them
terminal(command="tmux capture-pane -t backend -p | tail -30", timeout=5)
terminal(command="tmux send-keys -t frontend 'Here is the API schema from the backend agent: ...' Enter", timeout=5)
Session Resume
Resume most recent session
terminal(command="tmux new-session -d -s resumed 'hermes --continue'", timeout=10)
Resume specific session
terminal(command="tmux new-session -d -s resumed 'hermes --resume 20260225_143052_a1b2c3'", timeout=10)
Tips
- Prefer
delegate_task for quick subtasks โ less overhead than spawning a full process
- Use
-w (worktree mode) when spawning agents that edit code โ prevents git conflicts
- Set timeouts for one-shot mode โ complex tasks can take 5-10 minutes
- Use
hermes chat -q for fire-and-forget โ no PTY needed
- Use tmux for interactive sessions โ raw PTY mode has
\r vs \n issues with prompt_toolkit
- For scheduled tasks, use the
cronjob tool instead of spawning โ handles delivery and retry
---
Durable & Background Systems
Four systems run alongside the main conversation loop. Quick reference
here; full developer notes live in AGENTS.md, user-facing docs under
website/docs/user-guide/features/.
Delegation (delegate_task)
Synchronous subagent spawn โ the parent waits for the child's summary
before continuing its own loop. Isolated context + terminal session.
- Single:
delegate_task(goal, context, toolsets).
- Batch:
delegate_task(tasks=[{goal, ...}, ...]) runs children in
parallel, capped by delegation.max_concurrent_children (default 3).
- Roles:
leaf (default; cannot re-delegate) vs orchestrator
(can spawn its own workers, bounded by delegation.max_spawn_depth).
- Not durable. If the parent is interrupted, the child is
cancelled. For work that must outlive the turn, use cronjob or
terminal(background=True, notify_on_complete=True).
Config: delegation.* in config.yaml.
Tuning max_concurrent_children
Default is 3. Rule of thumb for raising it:
- Light tasks (web search, file grep): up to
6-8
- Medium tasks (code execution, browser):
4-5
- Heavy tasks (builds, large data):
2-3
- Actual bottleneck is usually the API rate limit, not local CPU/RAM. On a 10-core M4 with 16GB RAM, CPU is rarely the constraint.
- Formula: start at
5, raise only if profiling shows idle time between API responses.
Cron (scheduled jobs)
Durable scheduler โ cron/jobs.py + cron/scheduler.py. Drive it via
the cronjob tool, the hermes cron CLI (list, add, edit,
pause, resume, run, remove), or the /cron slash command.
- Schedules: duration (
"30m", "2h"), "every" phrase
( "every monday 9am"), 5-field cron ( "0 9 *"), or ISO timestamp.
- Per-job knobs:
skills, model/provider override, script
(pre-run data collection; no_agent=True makes the script the whole
job), context_from (chain job A's output into job B), workdir
(run in a specific dir with its AGENTS.md / CLAUDE.md loaded),
multi-platform delivery.
- Invariants: 3-minute hard interrupt per run,
.tick.lock file
prevents duplicate ticks across processes, cron sessions pass
skip_memory=True by default, and cron deliveries are framed with a
header/footer instead of being mirrored into the target gateway
session (keeps role alternation intact).
User docs: https://hermes-agent.nousresearch.com/docs/user-guide/features/cron
Curator (skill lifecycle)
Background maintenance for agent-created skills. Tracks usage, marks
idle skills stale, archives stale ones, keeps a pre-run tar.gz backup
so nothing is lost.
- CLI:
hermes curator <verb> โ status, run, pause, resume,
pin, unpin, archive, restore, prune, backup, rollback.
- Slash:
/curator <subcommand> mirrors the CLI.
- Scope: only touches skills with
created_by: "agent" provenance.
Bundled + hub-installed skills are off-limits. Never deletes โ
max destructive action is archive. Pinned skills are exempt from
every auto-transition and every LLM review pass.
- Telemetry: sidecar at
~/.hermes/skills/.usage.json holds
per-skill use_count, view_count, patch_count,
last_activity_at, state, pinned.
Config: curator.* (enabled, interval_hours, min_idle_hours,
stale_after_days, archive_after_days, backup.*).
User docs: https://hermes-agent.nousresearch.com/docs/user-guide/features/curator
Dreaming (periodic memory/skill consolidation)
For Anthropic-style "dreaming" workflows, combine cron + session_search + memory + skills + curator into a scheduled review loop. Start with a weekly, proposal-only report that audits recent sessions, repeated user corrections, memory conflicts, skill patch candidates, and cron/automation improvements. Do not automatically delete/replace memory or patch/archive skills unless the user explicitly approves the proposed changes. See references/weekly-dreaming-routine.md for the recommended prompt, report format, safety policy, and cron creation pattern.
Kanban (multi-agent work queue)
Durable SQLite board for multi-profile / multi-worker collaboration.
Users drive it via hermes kanban <verb>; dispatcher-spawned workers
see a focused kanban_* toolset gated by HERMES_KANBAN_TASK so the
schema footprint is zero outside worker processes.
- CLI verbs (common):
init, create, list (alias ls),
show, assign, link, unlink, comment, complete, block,
unblock, archive, tail. Less common: watch, stats, runs,
log, dispatch, daemon, gc.
- Worker toolset:
kanban_show, kanban_complete, kanban_block,
kanban_heartbeat, kanban_comment, kanban_create, kanban_link.
- Dispatcher runs inside the gateway by default
( kanban.dispatch_in_gateway: true) โ reclaims stale claims,
promotes ready tasks, atomically claims, spawns assigned profiles.
Auto-blocks a task after ~5 consecutive spawn failures.
- Isolation: board is the hard boundary (workers get
HERMES_KANBAN_BOARD pinned in env); tenant is a soft namespace
within a board for workspace-path + memory-key isolation.
User docs: https://hermes-agent.nousresearch.com/docs/user-guide/features/kanban
Log Relay (Hermes โ Discord)
A background Python script that tails ~/.hermes/logs/*.log and batches lines to a Discord channel. Includes session-ID extraction, rate-limit handling, and auto-restart via launchd/systemd. Useful for remote monitoring and audit trails.
- Reference:
references/discord-log-relay.md โ full setup, tuning, macOS/Linux service install, pitfalls.
- Template:
templates/discord-log-relay.py โ copy, set CHANNEL_ID, and deploy.
- Discord operations:
references/discord-operating-planes.md โ channel-purpose routing, periodic-summary vs Dreaming report formats, and safety/cost notes for Discord-first Hermes deployments.
Key pitfall: ask the user about batch frequency upfront rather than defaulting to real-time streaming. Most users prefer 10-minute or hourly batches. High-volume raw logs should be batched, summarized, or stored out-of-band; avoid Discord message storms during error loops.
Weekly Dreaming / Memory Curation
For long-running Hermes deployments, users may want an Anthropic-style "Dreaming" loop: a scheduled review that consolidates experience, proposes memory/skill/cron changes, and identifies what to keep, weaken, archive, or delete. Hermes has the building blocks (sessions, session_search, memory, skills, curator, cron), but the safe default is proposal mode:
1. Inspect recent usage and sessions.
2. Extract repeated success patterns, failure patterns, and user corrections.
3. Propose memory updates/removals without applying them silently.
4. Propose skill patches/archive candidates and cron/reporting improvements.
5. End with explicit approval checkboxes.
Do not silently rewrite or delete memory/skills from a Dreaming report unless the user explicitly authorized automatic application. See references/discord-operating-planes.md for a report template and routing heuristics.
---
Windows-Specific Quirks
Hermes runs natively on Windows (PowerShell, cmd, Windows Terminal, git-bash
mintty, VS Code integrated terminal). Most of it just works, but a handful
of differences between Win32 and POSIX have bitten us โ document new ones
here as you hit them so the next person (or the next session) doesn't
rediscover them from scratch.
Input / Keybindings
Alt+Enter doesn't insert a newline. Windows Terminal intercepts Alt+Enter
at the terminal layer to toggle fullscreen โ the keystroke never reaches
prompt_toolkit. Use Ctrl+Enter instead. Windows Terminal delivers
Ctrl+Enter as LF ( c-j), distinct from plain Enter ( c-m / CR), and the
CLI binds c-j to newline insertion on win32 only (see
_bind_prompt_submit_keys + the Windows-only c-j binding in cli.py).
Side effect: the raw Ctrl+J keystroke also inserts a newline on Windows โ
unavoidable, because Windows Terminal collapses Ctrl+Enter and Ctrl+J to
the same keycode at the Win32 console API layer. No conflicting binding
existed for Ctrl+J on Windows, so this is a harmless side effect.
mintty / git-bash behaves the same (fullscreen on Alt+Enter) unless you
disable Alt+Fn shortcuts in Options โ Keys. Easier to just use Ctrl+Enter.
Diagnosing keybindings. Run python scripts/keystroke_diagnostic.py
(repo root) to see exactly how prompt_toolkit identifies each keystroke
in the current terminal. Answers questions like "does Shift+Enter come
through as a distinct key?" (almost never โ most terminals collapse it
to plain Enter) or "what byte sequence is my terminal sending for
Ctrl+Enter?" This is how the Ctrl+Enter = c-j fact was established.
Config / Files
HTTP 400 "No models provided" on first run. config.yaml was saved
with a UTF-8 BOM (common when Windows apps write it). Re-save as UTF-8
without BOM. hermes config edit writes without BOM; manual edits in
Notepad are the usual culprit.
execute_code / Sandbox
WinError 10106 ("The requested service provider could not be loaded
or initialized") from the sandbox child process โ it can't create an
AF_INET socket, so the loopback-TCP RPC fallback fails before
connect(). Root cause is usually not a broken Winsock LSP; it's
Hermes's own env scrubber dropping SYSTEMROOT / WINDIR / COMSPEC
from the child env. Python's socket module needs SYSTEMROOT to locate
mswsock.dll. Fixed via the _WINDOWS_ESSENTIAL_ENV_VARS allowlist in
tools/code_execution_tool.py. If you still hit it, echo os.environ
inside an execute_code block to confirm SYSTEMROOT is set. Full
diagnostic recipe in references/execute-code-sandbox-env-windows.md.
Testing / Contributing
scripts/run_tests.sh doesn't work as-is on Windows โ it looks for
POSIX venv layouts ( .venv/bin/activate). The Hermes-installed venv at
venv/Scripts/ has no pip or pytest either (stripped for install size).
Workaround: install pytest + pytest-xdist + pyyaml into a system Python
3.11 user site, then invoke pytest directly with PYTHONPATH set:
"/c/Program Files/Python311/python" -m pip install --user pytest pytest-xdist pyyaml
export PYTHONPATH="$(pwd)"
"/c/Program Files/Python311/python" -m pytest tests/foo/test_bar.py -v --tb=short -n 0
Use -n 0, not -n 4 โ pyproject.toml's default addopts already
includes -n, and the wrapper's CI-parity guarantees don't apply off POSIX.
POSIX-only tests need skip guards. Common markers already in the codebase:
- Symlinks โ elevated privileges on Windows
0o600 file modes โ POSIX mode bits not enforced on NTFS by default
signal.SIGALRM โ Unix-only (see tests/conftest.py::_enforce_test_timeout)
- Winsock / Windows-specific regressions โ
@pytest.mark.skipif(sys.platform != "win32", ...)
Use the existing skip-pattern style (sys.platform == "win32" or
sys.platform.startswith("win")) to stay consistent with the rest of the
suite.
Path / Filesystem
Line endings. Git may warn LF will be replaced by CRLF the next time
Git touches it. Cosmetic โ the repo's .gitattributes normalizes. Don't
let editors auto-convert committed POSIX-newline files to CRLF.
Forward slashes work almost everywhere. C:/Users/... is accepted by
every Hermes tool and most Windows APIs. Prefer forward slashes in code
and logs โ avoids shell-escaping backslashes in bash.
---
Troubleshooting
Voice not working
1. Check stt.enabled: true in config.yaml
2. Verify provider: pip install faster-whisper or set API key
3. In gateway: /restart. In CLI: exit and relaunch.
Tool not available
1. hermes tools โ check if toolset is enabled for your platform
2. Some tools need env vars (check .env)
3. /reset after enabling tools
Model/provider issues
1. hermes doctor โ check config and dependencies
2. hermes auth add <provider> โ re-authenticate OAuth providers (use --type oauth)
3. Check .env has the right API key
4. Copilot 403: gh auth login tokens do NOT work for Copilot API. You must use the Copilot-specific OAuth device code flow via hermes model โ GitHub Copilot.
Changes not taking effect
- Tools/skills:
/reset starts a new session with updated toolset
- Config changes: In gateway:
/restart. In CLI: exit and relaunch.
- Code changes: Restart the CLI or gateway process
Deployed web dashboard shows stale CSS or theme changes
- Browser cache: Add
?v=N cache-busting query strings to CSS/JS/theme links in HTML.
- Service Worker cache: Bump
CACHE_NAME in sw.js to invalidate old shell caches.
- Automated bump script: For projects with multiple HTML entry points (dashboard, gather, etc.), use
scripts/bump-build.py to atomically update all build badges, cache-busting query strings, and service worker cache names in one command. See references/autonomous-lab-version-drift.md for usage.
- Data freshness: Use
fetch(url, {cache:'no-store'}) for live JSON feeds.
- Auto-detection: Embed
data-build in <html> and compare server build vs loaded build on page load to show a "new version available" banner. See references/static-site-cache-invalidation.md for the full diagnostic recipe and auto-detection pattern.
- Theme switcher reliability: If theme switching works in Chrome but not Samsung Internet, or feels broken on mobile, see
references/theme-switcher-reliability.md for the create-new-link โ load โ remove-old pattern.
- Emergency recovery: If a bad deploy breaks the main app JS, users need a standalone reset page. See
references/emergency-reset-page.md for a zero-dependency reset.html that clears Service Workers and caches without relying on the main app's JS.
Dashboard inspector feels too technical
- The default inspector view should contain only plain-language sentences: headline, "what they're doing now", "why it matters", and a silent visual progress bar (no text label).
- Move all technical fields (source IDs, confidence scores, progress labels, status slugs, badges) behind a "Show technical details" toggle.
- If users say "details are hard to understand," the fix is to remove more fields from the default view, not to add explanations. Explanations of technical fields are still technical.
- See
references/progressive-disclosure-human-first.md for the aggressive simplification pattern.
Pixel-art characters look wrong on mobile
- Decorative CSS elements (cheeks, ears, tails, badges) can be misread as facial features or appendages when avatars shrink below ~50 px.
- Hide them inside
@media (max-width:480px) so only the essential silhouette remains.
- See
references/pixel-art-mobile-readability.md for the exact selectors and rationale.
Skills not showing
1. hermes skills list โ verify installed
2. hermes skills config โ check platform enablement
3. Load explicitly: /skill name or hermes -s name
Gateway issues
Check logs first:
grep -i "failed to send\|error" ~/.hermes/logs/gateway.log | tail -20
Common gateway problems:
- Gateway dies on SSH logout: Enable linger:
sudo loginctl enable-linger $USER
- Gateway dies on WSL2 close: WSL2 requires
systemd=true in /etc/wsl.conf for systemd services to work. Without it, gateway falls back to nohup (dies when session closes).
- Gateway crash loop: Reset the failed state:
systemctl --user reset-failed hermes-gateway
- macOS: bot shows offline after idle time: The gateway runs as a user agent (
LimitLoadToSessionType=Aqua), so macOS suspends it when the system sleeps. The platform websocket drops and the bot appears offline until the network returns. Fix: keep the Mac awake (System Settings -> Energy -> Prevent automatic sleeping, or caffeinate -d -i -s -u &). Low Power Mode makes this worse, not better. See references/macos-gateway-sleep-disconnect.md for the full diagnostic recipe.
Platform-specific issues
- Discord bot silent: Must enable Message Content Intent in Bot โ Privileged Gateway Intents. See full Discord setup reference:
references/discord-gateway-setup.md.
- Slack bot only works in DMs: Must subscribe to
message.channels event. Without it, the bot ignores public channels.
- Windows-specific issues (
Alt+Enter newline, WinError 10106, UTF-8 BOM config, test suite, line endings): see the dedicated Windows-Specific Quirks section above.
Auxiliary models not working
If auxiliary tasks (vision, compression, session_search) fail silently, the auto provider can't find a backend. Either set OPENROUTER_API_KEY or GOOGLE_API_KEY, or explicitly configure each auxiliary task's provider:
hermes config set auxiliary.vision.provider <your_provider>
hermes config set auxiliary.vision.model <model_name>
Full system auth provisioning
For a one-shot workflow to maximize available credentials โ installing gh, generating SSH keys, configuring git, enabling all Hermes toolsets, and auditing current auth state โ see references/system-auth-setup.md.
Editing large files with patch
When a file is read with read_file(offset=...) (pagination), the tool warns that the view is partial. If you attempt patch without re-reading the full file first, you will likely hit non-unique match errors or corrupt the file. Fix: always call read_file without offset to load the whole file before patching. The tool explicitly warns: "โฆwas last read with offset/limit pagination (partial view). Re-read the whole file before overwriting it." โ heed this warning. For append-only updates (e.g., adding a cycle log entry to state.md), do not use terminal(command="cat >> file << 'EOF'...EOF") โ the terminal tool on macOS/Linux misinterprets heredoc << as backgrounding and fails. Instead, write a short Python script via write_file and execute it with terminal(command="python3 /tmp/script.py"). See references/terminal-heredoc-workaround.md for the full pattern.
Shell scripts that call Python with dependencies
Project shell scripts ( test.sh, publish.sh, validate_setup.sh) often call python3 to parse YAML or run helpers. On macOS and some Linux systems, the system python3 lacks PyYAML, causing scripts to fail with ModuleNotFoundError. See references/shell-script-python-auto-detection.md for a reusable find_python() pattern that auto-detects a Python interpreter with the required packages.
Sibling subagent file overwrites
When multiple subagents are running in parallel (e.g. via delegate_task batch mode or kanban worker lanes), a file may be modified by one subagent while another is about to write to it. If you use write_file or patch on a file that was last read before a sibling subagent modified it, your write may silently truncate or revert the sibling's changes. The tool may show a warning like "this file was modified by sibling subagent X but this agent never read it."
Fix:
1. Heed the warning. If the tool reports a sibling modification, re-read the file with read_file before writing.
2. Prefer patch over write_file for partial updates โ patch only changes the matched region and is less likely to wipe unrelated content.
3. If the file is already published/deployed, and the local working copy gets corrupted, recover from the published copy:
cp ~/hermes-web/agent-pets/css/dashboard.css ~/.hermes/autonomous-agent-lab/pixel-pet-ops/web/css/dashboard.css
4. For append-only updates, write a small Python script and execute it rather than using write_file on the whole file.
Prevention: In kanban/multi-agent workflows, assign file-level ownership so only one worker touches each file. If parallel workers must edit the same file, have them write to separate temp files and let the orchestrator merge.
---
Windows-Specific Quirks
| Looking for... | Location |
|----------------|----------|
| Config options | hermes config edit or [Configuration docs](https://hermes-agent.nousresearch.com/docs/user-guide/configuration) |
| Available tools | hermes tools list or [Tools reference](https://hermes-agent.nousresearch.com/docs/reference/tools-reference) |
| Slash commands | /help in session or [Slash commands reference](https://hermes-agent.nousresearch.com/docs/reference/slash-commands) |
| Skills catalog | hermes skills browse or [Skills catalog](https://hermes-agent.nousresearch.com/docs/reference/skills-catalog) |
| Provider setup | hermes model or [Providers guide](https://hermes-agent.nousresearch.com/docs/integrations/providers) |
| Platform setup | hermes gateway setup or [Messaging docs](https://hermes-agent.nousresearch.com/docs/user-guide/messaging/) |
| MCP servers | hermes mcp list or [MCP guide](https://hermes-agent.nousresearch.com/docs/user-guide/features/mcp) |
| Profiles | hermes profile list or [Profiles docs](https://hermes-agent.nousresearch.com/docs/user-guide/profiles) |
| Cron jobs | hermes cron list or [Cron docs](https://hermes-agent.nousresearch.com/docs/user-guide/features/cron) |
| Memory | hermes memory status or [Memory docs](https://hermes-agent.nousresearch.com/docs/user-guide/features/memory) |
| Env variables | hermes config env-path or [Env vars reference](https://hermes-agent.nousresearch.com/docs/reference/environment-variables) |
| CLI commands | hermes --help or [CLI reference](https://hermes-agent.nousresearch.com/docs/reference/cli-commands) |
| Gateway logs | ~/.hermes/logs/gateway.log |
| Session files | ~/.hermes/sessions/ or hermes sessions browse |
| Source code | ~/.hermes/hermes-agent/ |
---
Contributor Quick Reference
For occasional contributors and PR authors. Full developer docs: https://hermes-agent.nousresearch.com/docs/developer-guide/
Project Layout
hermes-agent/
โโโ run_agent.py # AIAgent โ core conversation loop
โโโ model_tools.py # Tool discovery and dispatch
โโโ toolsets.py # Toolset definitions
โโโ cli.py # Interactive CLI (HermesCLI)
โโโ hermes_state.py # SQLite session store
โโโ agent/ # Prompt builder, context compression, memory, model routing, credential pooling, skill dispatch
โโโ hermes_cli/ # CLI subcommands, config, setup, commands
โ โโโ commands.py # Slash command registry (CommandDef)
โ โโโ config.py # DEFAULT_CONFIG, env var definitions
โ โโโ main.py # CLI entry point and argparse
โโโ tools/ # One file per tool
โ โโโ registry.py # Central tool registry
โโโ gateway/ # Messaging gateway
โ โโโ platforms/ # Platform adapters (telegram, discord, etc.)
โโโ cron/ # Job scheduler
โโโ tests/ # ~3000 pytest tests
โโโ website/ # Docusaurus docs site
Config: ~/.hermes/config.yaml (settings), ~/.hermes/.env (API keys).
Adding a Tool (3 files)
1. Create tools/your_tool.py:
import json, os
from tools.registry import registry
def check_requirements() -> bool:
return bool(os.getenv("EXAMPLE_API_KEY"))
def example_tool(param: str, task_id: str = None) -> str:
return json.dumps({"success": True, "data": "..."})
registry.register(
name="example_tool",
toolset="example",
schema={"name": "example_tool", "description": "...", "parameters": {...}},
handler=lambda args, **kw: example_tool(
param=args.get("param", ""), task_id=kw.get("task_id")),
check_fn=check_requirements,
requires_env=["EXAMPLE_API_KEY"],
)
2. Add to toolsets.py โ _HERMES_CORE_TOOLS list.
Auto-discovery: any tools/*.py file with a top-level registry.register() call is imported automatically โ no manual list needed.
All handlers must return JSON strings. Use get_hermes_home() for paths, never hardcode ~/.hermes.
Adding a Slash Command
1. Add CommandDef to COMMAND_REGISTRY in hermes_cli/commands.py
2. Add handler in cli.py โ process_command()
3. (Optional) Add gateway handler in gateway/run.py
All consumers (help text, autocomplete, Telegram menu, Slack mapping) derive from the central registry automatically.
Agent Loop (High Level)
run_conversation():
1. Build system prompt
2. Loop while iterations < max:
a. Call LLM (OpenAI-format messages + tool schemas)
b. If tool_calls โ dispatch each via handle_function_call() โ append results โ continue
c. If text response โ return
3. Context compression triggers automatically near token limit
Testing
python -m pytest tests/ -o 'addopts=' -q # Full suite
python -m pytest tests/tools/ -q # Specific area
- Tests auto-redirect
HERMES_HOME to temp dirs โ never touch real ~/.hermes/
- Run full suite before pushing any change
- Use
-o 'addopts=' to clear any baked-in pytest flags
Windows contributors: scripts/run_tests.sh currently looks for POSIX venvs ( .venv/bin/activate / venv/bin/activate) and will error out on Windows where the layout is venv/Scripts/activate + python.exe. The Hermes-installed venv at venv/Scripts/ also has no pip or pytest โ it's stripped for end-user install size. Workaround: install pytest + pytest-xdist + pyyaml into a system Python 3.11 user site ( /c/Program Files/Python311/python -m pip install --user pytest pytest-xdist pyyaml), then run tests directly:
export PYTHONPATH="$(pwd)"
"/c/Program Files/Python311/python" -m pytest tests/tools/test_foo.py -v --tb=short -n 0
Use -n 0 (not -n 4) because pyproject.toml's default addopts already includes -n, and the wrapper's CI-parity story doesn't apply off-POSIX.
Cross-platform test guards: tests that use POSIX-only syscalls need a skip marker. Common ones already in the codebase:
- Symlink creation โ
@pytest.mark.skipif(sys.platform == "win32", reason="Symlinks require elevated privileges on Windows") (see tests/cron/test_cron_script.py)
- POSIX file modes (0o600, etc.) โ
@pytest.mark.skipif(sys.platform.startswith("win"), reason="POSIX mode bits not enforced on Windows") (see tests/hermes_cli/test_auth_toctou_file_modes.py)
signal.SIGALRM โ Unix-only (see tests/conftest.py::_enforce_test_timeout)
- Live Winsock / Windows-specific regression tests โ
@pytest.mark.skipif(sys.platform != "win32", reason="Windows-specific regression")
Monkeypatching sys.platform is not enough when the code under test also calls platform.system() / platform.release() / platform.mac_ver(). Those functions re-read the real OS independently, so a test that sets sys.platform = "linux" on a Windows runner will still see platform.system() == "Windows" and route through the Windows branch. Patch all three together:
monkeypatch.setattr(sys, "platform", "linux")
monkeypatch.setattr(platform, "system", lambda: "Linux")
monkeypatch.setattr(platform, "release", lambda: "6.8.0-generic")
See tests/agent/test_prompt_builder.py::TestEnvironmentHints for a worked example.
Extending the system prompt's execution-environment block
Factual guidance about the host OS, user home, cwd, terminal backend, and shell (bash vs. PowerShell on Windows) is emitted from agent/prompt_builder.py::build_environment_hints(). This is also where the WSL hint and per-backend probe logic live. The convention:
- Local terminal backend โ emit host info (OS,
$HOME, cwd) + Windows-specific notes (hostname โ username, terminal uses bash not PowerShell).
- Remote terminal backend (anything in
_REMOTE_TERMINAL_BACKENDS: docker, singularity, modal, daytona, ssh, vercel_sandbox, managed_modal) โ suppress host info entirely and describe only the backend. A live uname/whoami/pwd probe runs inside the backend via tools.environments.get_environment(...).execute(...), cached per process in _BACKEND_PROBE_CACHE, with a static fallback if the probe times out.
- Key fact for prompt authoring: when
TERMINAL_ENV != "local", every file tool (read_file, write_file, patch, search_files) runs inside the backend container, not on the host. The system prompt must never describe the host in that case โ the agent can't touch it.
Full design notes, the exact emitted strings, and testing pitfalls:
references/prompt-builder-environment-hints.md.
Refactor-safety pattern (POSIX-equivalence guard): when you extract inline logic into a helper that adds Windows/platform-specific behavior, keep a _legacy_<name> oracle function in the test file that's a verbatim copy of the old code, then parametrize-diff against it. Example: tests/tools/test_code_execution_windows_env.py::TestPosixEquivalence. This locks in the invariant that POSIX behavior is bit-for-bit identical and makes any future drift fail loudly with a clear diff.
Commit Conventions
type: concise subject line
Optional body.
Types: fix:, feat:, refactor:, docs:, chore:
Key Rules
- Never break prompt caching โ don't change context, tools, or system prompt mid-conversation
- Message role alternation โ never two assistant or two user messages in a row
- Use
get_hermes_home() from hermes_constants for all paths (profile-safe)
- Config values go in
config.yaml, secrets go in .env
- New tools need a
check_fn so they only appear when requirements are met
[IMPORTANT: The user has invoked the "kanban-orchestrator" skill, indicating they want you to follow its instructions. The full skill content is loaded below.]
---
name: kanban-orchestrator
description: Decomposition playbook + anti-temptation rules for an orchestrator profile routing work through Kanban. The "don't do the work yourself" rule and the basic lifecycle are auto-injected into every kanban worker's system prompt; this skill is the deeper playbook when you're specifically playing the orchestrator role.
version: 3.0.0
platforms: [linux, macos, windows]
metadata:
hermes:
tags: [kanban, multi-agent, orchestration, routing]
related_skills: [kanban-worker]
---
Kanban Orchestrator โ Decomposition Playbook
> The core worker lifecycle (including the kanban_create fan-out pattern and the "decompose, don't execute" rule) is auto-injected into every kanban process via the KANBAN_GUIDANCE system-prompt block. This skill is the deeper playbook when you're an orchestrator profile whose whole job is routing.
Profiles are user-configured โ not a fixed roster
Hermes setups vary widely. Some users run a single profile that does everything; some run a small fleet (docker-worker, cron-worker); some run a curated specialist team they've named themselves. There is no default specialist roster โ the orchestrator skill does not know what profiles exist on this machine.
Before fanning out, you must ground the decomposition in the profiles that actually exist. The dispatcher silently fails to spawn unknown assignee names โ it doesn't autocorrect, doesn't suggest, doesn't fall back. So a card assigned to researcher on a setup that only has docker-worker just sits in ready forever.
Step 0: discover available profiles before planning.
Use one of these:
hermes profile list โ prints the table of profiles configured on this machine. Run it through your terminal tool if you have one; otherwise ask the user.
kanban_list(assignee="<some-name>") โ sanity-check a single name. Returns an empty list (rather than an error) for an unknown assignee, so this only confirms a name you're already considering.
- Just ask the user. "What profiles do you have set up?" is a fine first turn when the goal needs more than one specialist.
Cache the result in your working memory for the rest of the conversation. Re-asking every turn wastes a tool call.
When to use the board (vs. just doing the work)
Create Kanban tasks when any of these are true:
1. Multiple specialists are needed. Research + analysis + writing is three profiles.
2. The work should survive a crash or restart. Long-running, recurring, or important.
3. The user might want to interject. Human-in-the-loop at any step.
4. Multiple subtasks can run in parallel. Fan-out for speed.
5. Review / iteration is expected. A reviewer profile loops on drafter output.
6. The audit trail matters. Board rows persist in SQLite forever.
If none of those apply โ it's a small one-shot reasoning task โ use delegate_task instead or answer the user directly.
The anti-temptation rules
Your job description says "route, don't execute." The rules that enforce that:
- Do not execute the work yourself. Your restricted toolset usually doesn't even include terminal/file/code/web for implementation. If you find yourself "just fixing this quickly" โ stop and create a task for the right specialist.
- For any concrete task, create a Kanban task and assign it. Every single time.
- Split multi-lane requests before creating cards. A user prompt can contain several independent workstreams. Extract those lanes first, then create one card per lane instead of bundling unrelated work into a single implementer card.
- Run independent lanes in parallel. If two cards do not need each other's output, leave them unlinked so the dispatcher can fan them out. Link only true data dependencies.
- If no specialist fits the available profiles, ask the user which profile to create or which existing profile to use. Do not invent profile names; the dispatcher will silently drop unknown assignees.
- Decompose, route, and summarize โ that's the whole job.
Exception: micro-UI polish cycles
There is one narrow exception where the orchestrator may execute directly instead of creating Kanban cards: tiny UI-only polish cycles (e.g., adding a CSS class, a theme preview dot, a hover state, a cross-link, or a HUD button) that are purely presentational, require no cross-file logic changes, and fit comfortably inside a single bounded cycle with no need for review or parallel work. If the change is limited to HTML/CSS/JS cosmetics, no other profile has a stake in it, and the user did not ask for a design review, the orchestrator should just edit and publish rather than paying the kanban-overhead tax. This exception does NOT apply to architecture changes, adapter logic, plugin interfaces, or anything that touches the data layer.
Decomposition playbook
Step 1 โ Understand the goal
Ask clarifying questions if the goal is ambiguous. Cheap to ask; expensive to spawn the wrong fleet.
Step 2 โ Sketch the task graph
Before creating anything, draft the graph out loud (in your response to the user). Treat every concrete workstream as a candidate card:
1. Extract the lanes from the request.
2. Map each lane to one of the profiles you discovered in Step 0. If a lane doesn't fit any existing profile, ask the user which to use or create.
3. Decide whether each lane is independent or gated by another lane.
4. Create independent lanes as parallel cards with no parent links.
5. Create synthesis/review/integration cards with parent links to the lanes they depend on.
Examples of prompts that should fan out (using placeholder profile names โ substitute whatever exists on the user's setup):
- "Build an app" โ one card to a design-oriented profile for product/UI direction, one or two cards to engineering profiles for implementation, plus a later integration/review card if the user has a reviewer profile.
- "Fix blockers and check model variants" โ one implementation card for the blocker fixes plus one discovery/research card for config/source verification. A final reviewer card can depend on both.
- "Research docs and implement" โ a docs-research card can run in parallel with a codebase-discovery card; implementation waits only if it truly needs those findings.
- "Analyze this screenshot and find the related code" โ one card to a vision-capable profile for the visual analysis while another searches the codebase.
Words like "also," "finally," or "and" do not automatically imply a dependency. They often mean "make sure this is covered before reporting back." Only link tasks when one card cannot start until another card's output exists.
Show the graph to the user before creating cards. Let them correct it โ including which actual profile name should own each lane.
Step 3 โ Create tasks and link
Use the profile names from Step 0. The example below uses placeholders <profile-A>, <profile-B>, <profile-C> โ replace them with what the user actually has.
t1 = kanban_create(
title="research: Postgres cost vs current",
assignee="<profile-A>", # whichever profile handles research on this setup
body="Compare estimated infrastructure costs, migration costs, and ongoing ops costs over a 3-year window. Sources: AWS/GCP pricing, team time estimates, current Postgres bills from peers.",
tenant=os.environ.get("HERMES_TENANT"),
)["task_id"]
t2 = kanban_create(
title="research: Postgres performance vs current",
assignee="<profile-A>", # same profile, run in parallel
body="Compare query latency, throughput, and scaling characteristics at our expected data volume (~500GB, 10k QPS peak). Sources: benchmark papers, public case studies, pgbench results if easy.",
)["task_id"]
t3 = kanban_create(
title="synthesize migration recommendation",
assignee="<profile-B>", # whichever profile does synthesis/analysis
body="Read the findings from T1 (cost) and T2 (performance). Produce a 1-page recommendation with explicit trade-offs and a go/no-go call.",
parents=[t1, t2],
)["task_id"]
t4 = kanban_create(
title="draft decision memo",
assignee="<profile-C>", # whichever profile drafts user-facing prose
body="Turn the analyst's recommendation into a 2-page memo for the CTO. Match the tone of previous decision memos in the team's knowledge base.",
parents=[t3],
)["task_id"]
parents=[...] gates promotion โ children stay in todo until every parent reaches done, then auto-promote to ready. No manual coordination needed; the dispatcher and dependency engine handle it.
Step 4 โ Complete your own task
If you were spawned as a task yourself (e.g. a planner profile was assigned T0: "investigate Postgres migration"), mark it done with a summary of what you created:
kanban_complete(
summary="decomposed into T1-T4: 2 research lanes in parallel, 1 synthesis on their outputs, 1 prose draft on the recommendation",
metadata={
"task_graph": {
"T1": {"assignee": "<profile-A>", "parents": []},
"T2": {"assignee": "<profile-A>", "parents": []},
"T3": {"assignee": "<profile-B>", "parents": ["T1", "T2"]},
"T4": {"assignee": "<profile-C>", "parents": ["T3"]},
},
},
)
Step 5 โ Report back to the user
Tell them what you created in plain prose, naming the actual profiles you used:
> I've queued 4 tasks:
> - T1 (<profile-A>): cost comparison
> - T2 (<profile-A>): performance comparison, in parallel with T1
> - T3 (<profile-B>): synthesizes T1 + T2 into a recommendation
> - T4 (<profile-C>): turns T3 into a CTO memo
>
> The dispatcher will pick up T1 and T2 now. T3 starts when both finish. You'll get a gateway ping when T4 completes. Use the dashboard or hermes kanban tail <id> to follow along.
Common patterns
Fan-out + fan-in (research โ synthesize): N research-style cards with no parents, one synthesis card with all of them as parents.
Parallel implementation + validation: one implementer card makes the change while one explorer/researcher card verifies config, docs, or source mapping. A reviewer card can depend on both. Do not make the implementer own unrelated verification just because the user mentioned both in one sentence.
Pipeline with gates: planner โ implementer โ reviewer. Each stage's parents=[previous_task]. Reviewer blocks or completes; if reviewer blocks, the operator unblocks with feedback and respawns.
Same-profile queue: N tasks, all assigned to the same profile, no dependencies between them. Dispatcher serializes โ that profile processes them in priority order, accumulating experience in its own memory.
Parallel UI/frontend lanes: When the goal touches multiple independent HTML/CSS/JS files (e.g., a dashboard page and a 2D gather view), fan out to separate subagents per file. Each lane edits its own file, then the orchestrator integrates, fixes cross-file references (theme paths, shared JSON endpoints), and publishes. This avoids merge conflicts in single-file HTML dashboards and keeps each subagent's context focused. See references/parallel-ui-lanes-and-publishing.md for the post-subagent integration checklist and rsync safety notes.
Human-in-the-loop: Any task can kanban_block() to wait for input. Dispatcher respawns after /unblock. The comment thread carries the full context.
Pitfalls
Inventing profile names that don't exist. The dispatcher silently fails to spawn unknown assignees โ the card just sits in ready forever. Always assign to a profile from your Step 0 discovery; ask the user if you're unsure.
Bundling independent lanes into one card. If the user asks for two independent outcomes, create two cards. Example: "fix blockers and check model variants" is not one fixer task; create a fixer/engineer card for the fixes and an explorer/researcher card for the variant check, then optionally gate review on both.
Over-linking because of wording. "Finally check X" may still be parallel with implementation if X is static config, docs, or source discovery. Link it after implementation only when the check depends on the implementation result.
Forgetting dependency links. If the task graph says research -> implement -> review, do not create all tasks as independent ready cards. Use parent links so implement/review cannot run before their inputs exist.
Reassignment vs. new task. If a reviewer blocks with "needs changes," create a NEW task linked from the reviewer's task โ don't re-run the same task with a stern look. The new task is assigned to the original implementer profile.
Argument order for links. kanban_link(parent_id=..., child_id=...) โ parent first. Mixing them up demotes the wrong task to todo.
Ignoring explicit user feedback to keep building infrastructure. When the user says a specific UX issue (legibility, theme switching, movement density) is "immediate priority," treat it as P0 and route it before deeper packaging/architecture work. Infrastructure polish feels productive, but shipping user-visible fixes is what matters. Create cards for the UX feedback first, then resume infrastructure lanes.
Treating status: complete as immutable when user feedback says otherwise. A state.md that says status: complete does not override a user's report that a completion criterion is actually broken. If the user says "theme switching is not working" and the Final Completion Condition requires "working UI theme switcher," the mission is not complete. Reactivate immediately: set status: active, append a reactivation cycle log, and fix the issue. Do not burn cycles on post-complete verification while the user is reporting active defects.
Don't pre-create the whole graph if the shape depends on intermediate findings. If T3's structure depends on what T1 and T2 find, let T3 exist as a "synthesize findings" task whose own first step is to read parent handoffs and plan the rest. Orchestrators can spawn orchestrators.
Tenant inheritance. If HERMES_TENANT is set in your env, pass tenant=os.environ.get("HERMES_TENANT") on every kanban_create call so child tasks stay in the same namespace.
Verifying cross-file references after directory reorganization. When subagents edit HTML/CSS/JS files and the directory structure shifts (e.g., moving files from root into web/dashboard/ and web/gather/), relative asset paths ( themes/default/theme.css, ./ops-data.json) often break. After subagents finish, the orchestrator must grep for href= and src= in moved files and fix relative paths before publishing. Subagents don't know the final publish layout โ the orchestrator does.
Destructive sync wipes needed files. Commands like rsync -av --delete will delete destination files that aren't in the source list. If you publish a directory tree piecemeal (e.g., copy web/dashboard/ first, then web/gather/ separately), --delete on the first rsync will erase the gather files before the second rsync runs. Either list all source paths in a single rsync invocation, or omit --delete and use cp -r / rsync -av without deletion when doing staged copies.
Recovering stuck workers
When a worker profile keeps crashing, hallucinating, or getting blocked by its own mistakes (usually: wrong model, missing skill, broken credential), the kanban dashboard flags the task with a โ badge and opens a Recovery section in the drawer. Three primary actions:
1. Reclaim (or hermes kanban reclaim <task_id>) โ abort the running worker immediately and reset the task to ready. The existing claim TTL is ~15 min; this is the fast path out.
2. Reassign (or hermes kanban reassign <task_id> <new-profile> --reclaim) โ switch the task to a different profile (one that exists on this setup) and let the dispatcher pick it up with a fresh worker.
3. Change profile model โ the dashboard prints a copy-paste hint for hermes -p <profile> model since profile config lives on disk; edit it in a terminal, then Reclaim to retry with the new model.
Hallucination warnings appear on tasks where a worker's kanban_complete(created_cards=[...]) claim included card ids that don't exist or weren't created by the worker's profile (the gate blocks the completion), or where the free-form summary references t_<hex> ids that don't resolve (advisory prose scan, non-blocking). Both produce audit events that persist even after recovery actions โ the trail stays for debugging.
The user has provided the following instruction alongside the skill invocation: [IMPORTANT: You are running as a scheduled cron job. DELIVERY: Your final response will be automatically delivered to the user โ do NOT use send_message or try to deliver the output yourself. Just produce your report/output as your final response and the system handles the rest. SILENT: If there is genuinely nothing new to report, respond with exactly "[SILENT]" (nothing else) to suppress delivery. Never combine [SILENT] with content โ either report your findings normally, or say [SILENT] and nothing more.]
You are the 15-minute Orchestrator for Son's Autonomous Agent Lab v1, reporting to Discord channel ID 1505805763824586952.
Durable state path: /Users/jooho-hermes/.hermes/autonomous-agent-lab/state.md
Working directory for experiment artifacts: /Users/jooho-hermes/.hermes/autonomous-agent-lab/
Preferred published web root: /Users/jooho-hermes/hermes-web/agent-pets/
Top-level directive from Son:
- The project has evolved from a personal dashboard into an INSTALLABLE PRODUCT that external Hermes users can deploy.
- The final target is a self-contained, configurable, publishable solution: "Hermes Pixel Pet Ops Office".
- Do NOT shrink the mission into a small static MVP and autonomously stop.
- The Gather.town-style 2D spatial office is a first-class feature, not a side page.
Latest UX feedback from Son (treat as immediate priority before deeper packaging work):
- Details are hard for a human to understand. Add human-first summaries, plain-language labels, and progressive disclosure: summary first, technical details second.
- Gather Town version has too many agents roaming around. Reduce default movement, add density/speed controls, cluster agents by room/task, and add focus/calm mode.
- Theme switching is not visibly working. Implement real UI theme switcher with persistence and clear visual theme changes.
Key product requirements (installable solution level):
1. Config-driven architecture: all paths, URLs, colors, names, room layouts via config.yaml. No hardcoded references to jooho-hermes.
2. Self-contained package: clear directory structure (src/, web/, config/, docs/, scripts/), install script, requirements.txt.
3. Pluggable data adapter: support multiple backends via plugin architecture.
4. Themeable frontend: CSS variables driven from config, swappable themes, plus a working UI theme switcher.
5. Multi-tenant ready: works for any Hermes instance.
6. Build/Deploy ready: Dockerfile or docker-compose, or clear static-server setup.
7. Documentation: README, architecture docs, configuration reference, contributor guide.
8. Human-comprehensible UX: plain-language summaries and progressive disclosure for technical detail.
9. Gather.town calm mode: adjustable movement density/speed and less chaotic defaults.
10. Versioned releases: CHANGELOG.md, semantic versioning, release packaging.
Mission model:
- Read state.md first before doing anything else.
- If state.md says
status: inactive or has no Current Mission, do not invent work. Return exactly: ๐ก Autonomous Agent Lab ๋๊ธฐ์ค โ Son์ด ํธ๋ฆฌ๊ฑฐ/๋ฏธ์
์ ์ฃผ๋ฉด 15๋ถ ์ฌ์ดํด์ ์์ํฉ๋๋ค.
- If state.md says
status: active, run one bounded 15-minute cycle toward the full installable solution.
- If state.md says
status: complete, verify that the Final Completion Condition in state.md is truly met. If it is not fully met, reactivate or report that state needs correction.
Cycle procedure when active:
1. Read state.md first. Extract current mission, constraints, previous cycle log, and Final Completion Condition.
2. Decide the next smallest useful step toward installable solution quality. Focus on: architecture, configurability, documentation, and clean separation of concerns.
3. Use delegate_task for independent subagent lanes when helpful.
4. Prefer concrete progress: refactor to config-driven, add install scripts, create docs, add Docker support, theme system, plugin architecture.
5. Update state.md with a new cycle log entry before final reporting.
6. Completion rule: only set status: complete when every item under state.md Final Completion Condition is satisfied. A non-installable MVP is not complete.
7. Stop/block only if Son explicitly stops/redirects, a safety boundary is reached, or a hard blocker needs Son's decision.
Link requirement (never forget):
- Every cycle report MUST include at least one direct viewable link to the published dashboard/artifact.
- The canonical URL:
http://hermes-mac-mini.tail46b3c6.ts.net:8099/agent-pets/
- Include gather town URL too:
http://hermes-mac-mini.tail46b3c6.ts.net:8099/agent-pets/gather/
Final Discord message format:
[Autonomous Agent Lab v1 / Cycle N]
๋ชฉํ:
์ํ:
๊ฒฐ๊ณผ:
๊ฒ์ฆ:
๋ค์:
์ํ:
Safety/quality rules:
- Do not handle secrets, passwords, API keys, payment, permission dialogs, or destructive commands.
- Do not claim completion without updating state.md.
- Do not rely on Discord history as durable state.
- Do not spam raw logs; summarize lane outputs and verification.
- Keep working in /Users/jooho-hermes/.hermes/autonomous-agent-lab/ and publish only to /Users/jooho-hermes/hermes-web/agent-pets/ unless the state file says otherwise.
Design/UX priorities:
- Mobile responsiveness is first-class.
- Character animation/movement is desired.
- Every cycle report must include published links.
- This is now a product engineering mission. Architecture, configurability, and documentation matter as much as visuals.
Response
[Autonomous Agent Lab v1 / Cycle 80]
๋ชฉํ: Fix a real JavaScript bug where renderBriefing() was defined twice in dashboard.js, causing the ops-briefing panel to never update after initial load. Bump build to b80.
์ํ:
1. Fixed function name collision ( web/js/dashboard.js): the modal daily-briefing renderer was named renderBriefing(), which silently overwrote the panel ops-briefing renderer of the same name. Renamed the modal renderer to renderBriefingModal() and updated the call inside toggleBriefing(). The panel renderer ( renderBriefing(data, metrics)) now correctly updates briefHeadline, briefBody, briefTime, and the attention class on every data poll.
2. Build & cache bumping: bumped build badge b79 โ b80, cache-busting query strings ?v=79 โ ?v=80, Service Worker CACHE_NAME pixel-pet-ops-v26 โ pixel-pet-ops-v27, and inline window.__HPPO_BUILD__ to 80 in both dashboard and gather HTML.
3. Integration test update: changed the duplicate renderBriefing check to renderBriefingModal so both panel and modal renderers are verified.
4. Ran adapter, tests, validation, and publish.
๊ฒฐ๊ณผ:
- Dashboard:
http://hermes-mac-mini.tail46b3c6.ts.net:8099/agent-pets/
- Gather Town:
http://hermes-mac-mini.tail46b3c6.ts.net:8099/agent-pets/gather/
- Badge:
v1.4.4 ยท b80
๊ฒ์ฆ:
- Adapter: 32 agents, 15 cron jobs, 20 sessions, 16 events, schema 1.4 โ healthy.
- Integration tests: 137/137 passed, 0 failed.
- Setup validation: 21/21 passed, 0 warned, 0 critical.
- Zero hardcoded references in source.
refresh.err.log empty; LaunchAgent healthy.
๋ค์:
- Son์ด dashboard์์ badge
v1.4.4 ยท b80๋ฅผ ํ์ธํ๊ณ , theme switching, Gather calm mode, inspector human-first view, daily briefing (D key)๋ฅผ ๋ธ๋ผ์ฐ์ ์์ ์ง์ ํ
์คํธํด ์ฃผ์ธ์.
- ๋ง์กฑ์ค๋ฌ์ฐ๋ฉด
status: complete๋ก ๋ง๋ฌด๋ฆฌํ ์ ์์ต๋๋ค.
์ํ: ๐ข active โ 11๊ฐ Final Completion Condition ๋ชจ๋ ์ถฉ์กฑ, Son์ browser-side UX ํ์ธ ๋๊ธฐ ์ค.
|
| 2026-05-20 03-37-40 |
85,098 chars |
2026-05-20_03-37-40.md |
Cron Job: autonomous-agent-lab-v1-orchestrator
Job ID: 35127ff89556
Run Time: 2026-05-20 03:37:40
Schedule: every 15m
Prompt
[IMPORTANT: The user has invoked the "hermes-agent" skill, indicating they want you to follow its instructions. The full skill content is loaded below.]
---
name: hermes-agent
description: "Configure, extend, or contribute to Hermes Agent."
version: 2.1.0
author: Hermes Agent + Teknium
license: MIT
platforms: [linux, macos, windows]
metadata:
hermes:
tags: [hermes, setup, configuration, multi-agent, spawning, cli, gateway, development]
homepage: https://github.com/NousResearch/hermes-agent
related_skills: [claude-code, codex, opencode]
---
Hermes Agent
Hermes Agent is an open-source AI agent framework by Nous Research that runs in your terminal, messaging platforms, and IDEs. It belongs to the same category as Claude Code (Anthropic), Codex (OpenAI), and OpenClaw โ autonomous coding and task-execution agents that use tool calling to interact with your system. Hermes works with any LLM provider (OpenRouter, Anthropic, OpenAI, DeepSeek, local models, and 15+ others) and runs on Linux, macOS, and WSL.
What makes Hermes different:
- Self-improving through skills โ Hermes learns from experience by saving reusable procedures as skills. When it solves a complex problem, discovers a workflow, or gets corrected, it can persist that knowledge as a skill document that loads into future sessions. Skills accumulate over time, making the agent better at your specific tasks and environment.
- Persistent memory across sessions โ remembers who you are, your preferences, environment details, and lessons learned. Pluggable memory backends (built-in, Honcho, Mem0, and more) let you choose how memory works.
- Multi-platform gateway โ the same agent runs on Telegram, Discord, Slack, WhatsApp, Signal, Matrix, Email, and 10+ other platforms with full tool access, not just chat.
- Provider-agnostic โ swap models and providers mid-workflow without changing anything else. Credential pools rotate across multiple API keys automatically.
- Profiles โ run multiple independent Hermes instances with isolated configs, sessions, skills, and memory.
- Extensible โ plugins, MCP servers, custom tools, webhook triggers, cron scheduling, and the full Python ecosystem.
People use Hermes for software development, research, system administration, data analysis, content creation, home automation, and anything else that benefits from an AI agent with persistent context and full system access.
This skill helps you work with Hermes Agent effectively โ setting it up, configuring features, spawning additional agent instances, troubleshooting issues, finding the right commands and settings, and understanding how the system works when you need to extend or contribute to it.
Docs: https://hermes-agent.nousresearch.com/docs/
Quick Start
Install
curl -fsSL https://raw.githubusercontent.com/NousResearch/hermes-agent/main/scripts/install.sh | bash
Interactive chat (default)
hermes
Single query
hermes chat -q "What is the capital of France?"
Setup wizard
hermes setup
Change model/provider
hermes model
Check health
hermes doctor
---
CLI Reference
Global Flags
hermes [flags] [command]
--version, -V Show version
--resume, -r SESSION Resume session by ID or title
--continue, -c [NAME] Resume by name, or most recent session
--worktree, -w Isolated git worktree mode (parallel agents)
--skills, -s SKILL Preload skills (comma-separate or repeat)
--profile, -p NAME Use a named profile
--yolo Skip dangerous command approval
--pass-session-id Include session ID in system prompt
No subcommand defaults to chat.
Chat
hermes chat [flags]
-q, --query TEXT Single query, non-interactive
-m, --model MODEL Model (e.g. anthropic/claude-sonnet-4)
-t, --toolsets LIST Comma-separated toolsets
--provider PROVIDER Force provider (openrouter, anthropic, nous, etc.)
-v, --verbose Verbose output
-Q, --quiet Suppress banner, spinner, tool previews
--checkpoints Enable filesystem checkpoints (/rollback)
--source TAG Session source tag (default: cli)
Configuration
hermes setup [section] Interactive wizard (model|terminal|gateway|tools|agent)
hermes model Interactive model/provider picker
hermes config View current config
hermes config edit Open config.yaml in $EDITOR
hermes config set KEY VAL Set a config value
hermes config path Print config.yaml path
hermes config env-path Print .env path
hermes config check Check for missing/outdated config
hermes config migrate Update config with new options
hermes doctor [--fix] Check dependencies and config
Credential Pools
hermes auth add Interactive credential wizard (oauth, api-key)
hermes auth list [PROVIDER] List pooled credentials
hermes auth remove P INDEX Remove by provider + index
hermes auth reset PROVIDER Clear exhaustion status
hermes logout Clear stored auth
Tools & Skills
hermes tools Interactive tool enable/disable (curses UI)
hermes tools list Show all tools and status
hermes tools enable NAME Enable a toolset
hermes tools disable NAME Disable a toolset
hermes skills list List installed skills
hermes skills search QUERY Search the skills hub
hermes skills install ID Install a skill (ID can be a hub identifier OR a direct https://โฆ/SKILL.md URL; pass --name to override when frontmatter has no name)
hermes skills inspect ID Preview without installing
hermes skills config Enable/disable skills per platform
hermes skills check Check for updates
hermes skills update Update outdated skills
hermes skills uninstall N Remove a hub skill
hermes skills publish PATH Publish to registry
hermes skills browse Browse all available skills
hermes skills tap add REPO Add a GitHub repo as skill source
MCP Servers
hermes mcp serve Run Hermes as an MCP server
hermes mcp add NAME Add an MCP server (--url or --command)
hermes mcp remove NAME Remove an MCP server
hermes mcp list List configured servers
hermes mcp test NAME Test connection
hermes mcp configure NAME Toggle tool selection
Gateway (Messaging Platforms)
hermes gateway run Start gateway foreground
hermes gateway install Install as background service
hermes gateway start/stop Control the service
hermes gateway restart Restart the service
hermes gateway status Check status
hermes gateway setup Configure platforms
Supported platforms: Telegram, Discord, Slack, WhatsApp, Signal, Email, SMS, Matrix, Mattermost, Home Assistant, DingTalk, Feishu, WeCom, BlueBubbles (iMessage), Weixin (WeChat), API Server, Webhooks. Open WebUI connects via the API Server adapter.
Platform docs: https://hermes-agent.nousresearch.com/docs/user-guide/messaging/
Discord-specific walkthrough (token, intents, service install, access control): see references/discord-gateway-setup.md in this skill.
- Per-channel personas and skill bindings: see
references/gateway-channel-personas.md (works on Discord, Slack, Telegram, Mattermost, Matrix).
- For long-running Discord-first operations, purpose-specific channel routing, periodic summaries, weekly Dreaming/audit reports, and log-safety patterns: see
references/discord-operating-planes.md.
- For broad Hermes/LifeOS/SQAF ecosystem audits (cron inventory, live services, dashboards, provider/model warnings, and control-plane gaps), see
references/ecosystem-audit.md.
Sessions
hermes sessions list List recent sessions
hermes sessions browse Interactive picker
hermes sessions export OUT Export to JSONL
hermes sessions rename ID T Rename a session
hermes sessions delete ID Delete a session
hermes sessions prune Clean up old sessions (--older-than N days)
hermes sessions stats Session store statistics
For browser-based viewing of existing Hermes CLI/Discord/cron session transcripts, prefer a lightweight static export from ~/.hermes/state.db into a private web root instead of assuming Open WebUI can browse Hermes' native session store. See references/hermes-session-static-web-viewer.md for the SQLite schema, static HTML export workflow, redaction/truncation cautions, and the user's Mac mini deployment (/hermes-sessions/ under the Tailscale-only ~/hermes-web site).
For cron job execution history, the same static-export pattern applies to ~/.hermes/cron/jobs.json and ~/.hermes/cron/output/{job_id}/*.md. See references/cron-history-web-viewer.md for the cron data model, schedule-dict pitfall, and the user's deployed /cron-history/ dashboard.
Cron Jobs
hermes cron list List jobs (--all for disabled)
hermes cron create SCHED Create: '30m', 'every 2h', '0 9 *'
hermes cron edit ID Edit schedule, prompt, delivery
hermes cron pause/resume ID Control job state
hermes cron run ID Trigger on next tick
hermes cron remove ID Delete a job
hermes cron status Scheduler status
For bounded autonomous lab/orchestrator cron jobs that use file-based state, subagent lanes, artifact publishing, and status transitions (active โ complete/blocked/inactive), see references/autonomous-agent-lab-cron-cycle.md. A reusable verification script template lives at scripts/verify-completion-template.py.
For a worked example of evolving an autonomous lab into a config-driven, themeable, Docker-ready installable product, see references/autonomous-lab-product-architecture.md. For CI, integration testing, pluggable adapter architecture, bounded cycle orchestration, and post-productization patterns, see references/product-maturity-patterns.md.
For the final completion verification checklist โ the explicit audit pattern to run before marking status: complete on an installable-solution mission, see references/autonomous-lab-completion-verification.md.
For the reactivation protocol when a completed lab receives new P0 feedback or the user contradicts a completion claim, see references/autonomous-lab-reactivation-protocol.md.
For the config/CHANGELOG version drift pitfall that occurs when autonomous labs evolve over many cycles, and for the related source vs. published file drift problem where the live web root diverges from the project source, see references/autonomous-lab-version-drift.md.
For adding historical trend tracking (SQLite-backed agent status transitions + vanilla JS SVG sparklines) to an autonomous lab dashboard, see references/history-tracking-sparkline-pattern.md.
For preventing unbounded SQLite growth in long-running labs, see references/autonomous-lab-data-retention.md โ covers automatic per-refresh pruning and a standalone manual prune utility.
- For reusable dashboard UX patterns (onboarding tours, data freshness badges, keyboard shortcuts, progressive disclosure inspectors, cross-linking between views, inspector deep-linking), see
references/dashboard-ux-patterns.md.
For the daily operational briefing modal โ a one-screen human-first summary of agent counts, blocked work, recent events, health status, and upcoming cron schedules โ see references/daily-briefing-modal.md.
For the aggressive human-first inspector refinement โ when users report that details are hard to understand and the fix is to strip technical labels from the default view โ see references/progressive-disclosure-human-first.md.
For programmatic verification of CSS custom-property theme systems โ catching scoping bugs, confirming theme distinctness, and validating JS switching logic โ see references/theme-system-verification.md.
- For Son's Discord-first autonomous experiments where a channel hosts a repeated multi-agent loop, use the Autonomous Discord Agent Lab pattern: create file-based durable state, a paused cron orchestrator delivered to
discord:<channel_id>, then activate it from a user mission trigger. See references/autonomous-discord-agent-lab.md.
- For verifying that a release package (
tar.gz) is actually installable by third parties and contains no stale artifacts or hardcoded references, see references/release-package-verification.md and the reusable script at scripts/release-verify.sh.
Webhooks
hermes webhook subscribe N Create route at /webhooks/<name>
hermes webhook list List subscriptions
hermes webhook remove NAME Remove a subscription
hermes webhook test NAME Send a test POST
Profiles
hermes profile list List all profiles
hermes profile create NAME Create (--clone, --clone-all, --clone-from)
hermes profile use NAME Set sticky default
hermes profile delete NAME Delete a profile
hermes profile show NAME Show details
hermes profile alias NAME Manage wrapper scripts
hermes profile rename A B Rename a profile
hermes profile export NAME Export to tar.gz
hermes profile import FILE Import from archive
Credential Pools
hermes auth add Interactive credential wizard
hermes auth list [PROVIDER] List pooled credentials
hermes auth remove P INDEX Remove by provider + index
hermes auth reset PROVIDER Clear exhaustion status
Other
hermes insights [--days N] Usage analytics
hermes update Update to latest version
hermes pairing list/approve/revoke DM authorization
hermes plugins list/install/remove Plugin management
hermes honcho setup/status Honcho memory integration (requires honcho plugin)
hermes memory setup/status/off Memory provider config
hermes completion bash|zsh Shell completions
hermes acp ACP server (IDE integration)
hermes claw migrate Migrate from OpenClaw
hermes uninstall Uninstall Hermes
---
Slash Commands (In-Session)
Type these during an interactive chat session. New commands land fairly
often; if something below looks stale, run /help in-session for the
authoritative list or see the [live slash commands reference](https://hermes-agent.nousresearch.com/docs/reference/slash-commands).
The registry of record is hermes_cli/commands.py โ every consumer
(autocomplete, Telegram menu, Slack mapping, /help) derives from it.
Session Control
/new (/reset) Fresh session
/clear Clear screen + new session (CLI)
/retry Resend last message
/undo Remove last exchange
/title [name] Name the session
/compress Manually compress context
/stop Kill background processes
/rollback [N] Restore filesystem checkpoint
/snapshot [sub] Create or restore state snapshots of Hermes config/state (CLI)
/background <prompt> Run prompt in background
/queue <prompt> Queue for next turn
/steer <prompt> Inject a message after the next tool call without interrupting
/agents (/tasks) Show active agents and running tasks
/resume [name] Resume a named session
/goal [text|sub] Set a standing goal Hermes works on across turns until achieved
(subcommands: status, pause, resume, clear)
/redraw Force a full UI repaint (CLI)
Configuration
/config Show config (CLI)
/model [name] Show or change model
/personality [name] Set personality
/reasoning [level] Set reasoning (none|minimal|low|medium|high|xhigh|show|hide)
/verbose Cycle: off โ new โ all โ verbose
/voice [on|off|tts] Voice mode
/yolo Toggle approval bypass
/busy [sub] Control what Enter does while Hermes is working (CLI)
(subcommands: queue, steer, interrupt, status)
/indicator [style] Pick the TUI busy-indicator style (CLI)
(styles: kaomoji, emoji, unicode, ascii)
/footer [on|off] Toggle gateway runtime-metadata footer on final replies
/skin [name] Change theme (CLI)
/statusbar Toggle status bar (CLI)
Tools & Skills
/tools Manage tools (CLI)
/toolsets List toolsets (CLI)
/skills Search/install skills (CLI)
/skill <name> Load a skill into session
/reload-skills Re-scan ~/.hermes/skills/ for added/removed skills
/reload Reload .env variables into the running session (CLI)
/reload-mcp Reload MCP servers
/cron Manage cron jobs (CLI)
/curator [sub] Background skill maintenance (status, run, pin, archive, โฆ)
/kanban [sub] Multi-profile collaboration board (tasks, links, comments)
/plugins List plugins (CLI)
Gateway
/approve Approve a pending command (gateway)
/deny Deny a pending command (gateway)
/restart Restart gateway (gateway)
/sethome Set current chat as home channel (gateway)
/update Update Hermes to latest (gateway)
/topic [sub] Enable or inspect Telegram DM topic sessions (gateway)
/platforms (/gateway) Show platform connection status (gateway)
Utility
/branch (/fork) Branch the current session
/fast Toggle priority/fast processing
/browser Open CDP browser connection
/history Show conversation history (CLI)
/save Save conversation to file (CLI)
/copy [N] Copy the last assistant response to clipboard (CLI)
/paste Attach clipboard image (CLI)
/image Attach local image file (CLI)
Info
/help Show commands
/commands [page] Browse all commands (gateway)
/usage Token usage
/insights [days] Usage analytics
/gquota Show Google Gemini Code Assist quota usage (CLI)
/status Session info (gateway)
/profile Active profile info
/debug Upload debug report (system info + logs) and get shareable links
Exit
/quit (/exit, /q) Exit CLI
---
Key Paths & Config
~/.hermes/config.yaml Main configuration
~/.hermes/.env API keys and secrets
$HERMES_HOME/skills/ Installed skills
~/.hermes/sessions/ Session transcripts
~/.hermes/logs/ Gateway and error logs
~/.hermes/auth.json OAuth tokens and credential pools
~/.hermes/hermes-agent/ Source code (if git-installed)
Profiles use ~/.hermes/profiles/<name>/ with the same layout.
Config Sections
Edit with hermes config edit or hermes config set section.key value.
| Section | Key options |
|---------|-------------|
| model | default, provider, base_url, api_key, context_length |
| agent | max_turns (90), tool_use_enforcement |
| terminal | backend (local/docker/ssh/modal), cwd, timeout (180) |
| compression | enabled, threshold (0.50), target_ratio (0.20) |
| display | skin, tool_progress, show_reasoning, show_cost |
| stt | enabled, provider (local/groq/openai/mistral) |
| tts | provider (edge/elevenlabs/openai/minimax/mistral/neutts) |
| memory | memory_enabled, user_profile_enabled, provider |
| security | tirith_enabled, website_blocklist |
| delegation | model, provider, base_url, api_key, max_iterations (50), reasoning_effort |
| checkpoints | enabled, max_snapshots (50) |
| fallback_model | provider, model, base_url, key_env |
Fallback Providers
Hermes can automatically fail over to a backup provider:model when the primary is unavailable. This is turn-scoped โ each new user message starts with the primary restored; fallback only activates mid-turn when the primary fails.
Configuration ( ~/.hermes/config.yaml):
fallback_model:
provider: opencode-go
model: kimi-k2.6
Or use the interactive manager:
hermes fallback add # interactive picker
hermes fallback list # show fallback chain
hermes fallback remove # remove by index
Legacy note: fallback_model (singular) is the legacy single-fallback key. fallback_providers (list) supports multiple ordered fallbacks. When both exist, fallback_providers takes priority.
Trigger conditions (after exhausting retries where applicable):
- Rate limits (HTTP 429)
- Server errors (HTTP 500, 502, 503)
- Auth failures (HTTP 401, 403) โ immediately
- Not found (HTTP 404) โ immediately
- Invalid / empty responses repeatedly
Supported providers include all standard providers (OpenRouter, Anthropic, OpenCode Go/ Zen, Kimi, etc.) plus custom endpoints with base_url + key_env. Full provider docs: https://hermes-agent.nousresearch.com/docs/integrations/providers
Limitations:
- Subagent delegation does not inherit fallback config
- Cron jobs do not use fallback (use per-job provider/model overrides)
- Auxiliary tasks (vision, compression, etc.) use their own
auxiliary.* provider chain
For a deep-dive with worked examples and model lists, see references/fallback-providers.md.
Full config reference: https://hermes-agent.nousresearch.com/docs/user-guide/configuration
Providers
20+ providers supported. Set via hermes model or hermes setup.
| Provider | Auth | Key env var |
|----------|------|-------------|
| OpenRouter | API key | OPENROUTER_API_KEY |
| Anthropic | API key | ANTHROPIC_API_KEY |
| Nous Portal | OAuth | hermes auth |
| OpenAI Codex | OAuth | hermes auth |
| GitHub Copilot | Token | COPILOT_GITHUB_TOKEN |
| Google Gemini | API key | GOOGLE_API_KEY or GEMINI_API_KEY |
| DeepSeek | API key | DEEPSEEK_API_KEY |
| xAI / Grok | API key | XAI_API_KEY |
| Hugging Face | Token | HF_TOKEN |
| Z.AI / GLM | API key | GLM_API_KEY |
| MiniMax | API key | MINIMAX_API_KEY |
| MiniMax CN | API key | MINIMAX_CN_API_KEY |
| Kimi / Moonshot | API key | KIMI_API_KEY |
| Alibaba / DashScope | API key | DASHSCOPE_API_KEY |
| Xiaomi MiMo | API key | XIAOMI_API_KEY |
| Kilo Code | API key | KILOCODE_API_KEY |
| AI Gateway (Vercel) | API key | AI_GATEWAY_API_KEY |
| OpenCode Zen | API key | OPENCODE_ZEN_API_KEY |
| OpenCode Go | API key | OPENCODE_GO_API_KEY |
| Qwen OAuth | OAuth | hermes auth add qwen-oauth |
| Custom endpoint | Config | model.base_url + model.api_key in config.yaml |
| GitHub Copilot ACP | External | COPILOT_CLI_PATH or Copilot CLI |
Full provider docs: https://hermes-agent.nousresearch.com/docs/integrations/providers
Toolsets
Enable/disable via hermes tools (interactive) or hermes tools enable/disable NAME.
| Toolset | What it provides |
|---------|-----------------|
| web | Web search and content extraction |
| search | Web search only (subset of web) |
| browser | Browser automation (Browserbase, Camofox, or local Chromium) |
| terminal | Shell commands and process management |
| file | File read/write/search/patch |
| code_execution | Sandboxed Python execution |
| vision | Image analysis |
| image_gen | AI image generation |
| video | Video analysis and generation |
| tts | Text-to-speech |
| skills | Skill browsing and management |
| memory | Persistent cross-session memory |
| session_search | Search past conversations |
| delegation | Subagent task delegation |
| cronjob | Scheduled task management |
| clarify | Ask user clarifying questions |
| messaging | Cross-platform message sending |
| todo | In-session task planning and tracking |
| kanban | Multi-agent work-queue tools (gated to workers) |
| debugging | Extra introspection/debug tools (off by default) |
| safe | Minimal, low-risk toolset for locked-down sessions |
| spotify | Spotify playback and playlist control |
| homeassistant | Smart home control (off by default) |
| discord | Discord integration tools |
| discord_admin | Discord admin/moderation tools |
| feishu_doc | Feishu (Lark) document tools |
| feishu_drive | Feishu (Lark) drive tools |
| yuanbao | Yuanbao integration tools |
| rl | Reinforcement learning tools (off by default) |
| moa | Mixture of Agents (off by default) |
Full enumeration lives in toolsets.py as the TOOLSETS dict; _HERMES_CORE_TOOLS is the default bundle most platforms inherit from.
Tool changes take effect on /reset (new session). They do NOT apply mid-conversation to preserve prompt caching.
---
Security & Privacy Toggles
Common "why is Hermes doing X to my output / tool calls / commands?" toggles โ and the exact commands to change them. Most of these need a fresh session (/reset in chat, or start a new hermes invocation) because they're read once at startup.
Secret redaction in tool output
Secret redaction is off by default โ tool output (terminal stdout, read_file, web content, subagent summaries, etc.) passes through unmodified. If the user wants Hermes to auto-mask strings that look like API keys, tokens, and secrets before they enter the conversation context and logs:
hermes config set security.redact_secrets true # enable globally
Restart required. security.redact_secrets is snapshotted at import time โ toggling it mid-session (e.g. via export HERMES_REDACT_SECRETS=true from a tool call) will NOT take effect for the running process. Tell the user to run hermes config set security.redact_secrets true in a terminal, then start a new session. This is deliberate โ it prevents an LLM from flipping the toggle on itself mid-task.
Disable again with:
hermes config set security.redact_secrets false
PII redaction in gateway messages
Separate from secret redaction. When enabled, the gateway hashes user IDs and strips phone numbers from the session context before it reaches the model:
hermes config set privacy.redact_pii true # enable
hermes config set privacy.redact_pii false # disable (default)
Command approval prompts
By default (approvals.mode: manual), Hermes prompts the user before running shell commands flagged as destructive (rm -rf, git reset --hard, etc.). The modes are:
manual โ always prompt (default)
smart โ use an auxiliary LLM to auto-approve low-risk commands, prompt on high-risk
off โ skip all approval prompts (equivalent to --yolo)
hermes config set approvals.mode smart # recommended middle ground
hermes config set approvals.mode off # bypass everything (not recommended)
Per-invocation bypass without changing config:
hermes --yolo โฆ
export HERMES_YOLO_MODE=1
Note: YOLO / approvals.mode: off does NOT turn off secret redaction. They are independent.
Shell hooks allowlist
Some shell-hook integrations require explicit allowlisting before they fire. Managed via ~/.hermes/shell-hooks-allowlist.json โ prompted interactively the first time a hook wants to run.
Disabling the web/browser/image-gen tools
To keep the model away from network or media tools entirely, open hermes tools and toggle per-platform. Takes effect on next session (/reset). See the Tools & Skills section above.
---
Voice & Transcription
STT (Voice โ Text)
Voice messages from messaging platforms are auto-transcribed.
Provider priority (auto-detected):
1. Local faster-whisper โ free, no API key: pip install faster-whisper
2. Groq Whisper โ free tier: set GROQ_API_KEY
3. OpenAI Whisper โ paid: set VOICE_TOOLS_OPENAI_KEY
4. Mistral Voxtral โ set MISTRAL_API_KEY
Config:
stt:
enabled: true
provider: local # local, groq, openai, mistral
local:
model: base # tiny, base, small, medium, large-v3
TTS (Text โ Voice)
| Provider | Env var | Free? |
|----------|---------|-------|
| Edge TTS | None | Yes (default) |
| ElevenLabs | ELEVENLABS_API_KEY | Free tier |
| OpenAI | VOICE_TOOLS_OPENAI_KEY | Paid |
| MiniMax | MINIMAX_API_KEY | Paid |
| Mistral (Voxtral) | MISTRAL_API_KEY | Paid |
| NeuTTS (local) | None (pip install neutts[all] + espeak-ng) | Free |
Voice commands: /voice on (voice-to-voice), /voice tts (always voice), /voice off.
---
Spawning Additional Hermes Instances
Run additional Hermes processes as fully independent subprocesses โ separate sessions, tools, and environments.
When to Use This vs delegate_task
| | delegate_task | Spawning hermes process |
|-|-----------------|--------------------------|
| Isolation | Separate conversation, shared process | Fully independent process |
| Duration | Minutes (bounded by parent loop) | Hours/days |
| Tool access | Subset of parent's tools | Full tool access |
| Interactive | No | Yes (PTY mode) |
| Use case | Quick parallel subtasks | Long autonomous missions |
One-Shot Mode
terminal(command="hermes chat -q 'Research GRPO papers and write summary to ~/research/grpo.md'", timeout=300)
Background for long tasks:
terminal(command="hermes chat -q 'Set up CI/CD for ~/myapp'", background=true)
Interactive PTY Mode (via tmux)
Hermes uses prompt_toolkit, which requires a real terminal. Use tmux for interactive spawning:
Start
terminal(command="tmux new-session -d -s agent1 -x 120 -y 40 'hermes'", timeout=10)
Wait for startup, then send a message
terminal(command="sleep 8 && tmux send-keys -t agent1 'Build a FastAPI auth service' Enter", timeout=15)
Read output
terminal(command="sleep 20 && tmux capture-pane -t agent1 -p", timeout=5)
Send follow-up
terminal(command="tmux send-keys -t agent1 'Add rate limiting middleware' Enter", timeout=5)
Exit
terminal(command="tmux send-keys -t agent1 '/exit' Enter && sleep 2 && tmux kill-session -t agent1", timeout=10)
Multi-Agent Coordination
Agent A: backend
terminal(command="tmux new-session -d -s backend -x 120 -y 40 'hermes -w'", timeout=10)
terminal(command="sleep 8 && tmux send-keys -t backend 'Build REST API for user management' Enter", timeout=15)
Agent B: frontend
terminal(command="tmux new-session -d -s frontend -x 120 -y 40 'hermes -w'", timeout=10)
terminal(command="sleep 8 && tmux send-keys -t frontend 'Build React dashboard for user management' Enter", timeout=15)
Check progress, relay context between them
terminal(command="tmux capture-pane -t backend -p | tail -30", timeout=5)
terminal(command="tmux send-keys -t frontend 'Here is the API schema from the backend agent: ...' Enter", timeout=5)
Session Resume
Resume most recent session
terminal(command="tmux new-session -d -s resumed 'hermes --continue'", timeout=10)
Resume specific session
terminal(command="tmux new-session -d -s resumed 'hermes --resume 20260225_143052_a1b2c3'", timeout=10)
Tips
- Prefer
delegate_task for quick subtasks โ less overhead than spawning a full process
- Use
-w (worktree mode) when spawning agents that edit code โ prevents git conflicts
- Set timeouts for one-shot mode โ complex tasks can take 5-10 minutes
- Use
hermes chat -q for fire-and-forget โ no PTY needed
- Use tmux for interactive sessions โ raw PTY mode has
\r vs \n issues with prompt_toolkit
- For scheduled tasks, use the
cronjob tool instead of spawning โ handles delivery and retry
---
Durable & Background Systems
Four systems run alongside the main conversation loop. Quick reference
here; full developer notes live in AGENTS.md, user-facing docs under
website/docs/user-guide/features/.
Delegation (delegate_task)
Synchronous subagent spawn โ the parent waits for the child's summary
before continuing its own loop. Isolated context + terminal session.
- Single:
delegate_task(goal, context, toolsets).
- Batch:
delegate_task(tasks=[{goal, ...}, ...]) runs children in
parallel, capped by delegation.max_concurrent_children (default 3).
- Roles:
leaf (default; cannot re-delegate) vs orchestrator
(can spawn its own workers, bounded by delegation.max_spawn_depth).
- Not durable. If the parent is interrupted, the child is
cancelled. For work that must outlive the turn, use cronjob or
terminal(background=True, notify_on_complete=True).
Config: delegation.* in config.yaml.
Tuning max_concurrent_children
Default is 3. Rule of thumb for raising it:
- Light tasks (web search, file grep): up to
6-8
- Medium tasks (code execution, browser):
4-5
- Heavy tasks (builds, large data):
2-3
- Actual bottleneck is usually the API rate limit, not local CPU/RAM. On a 10-core M4 with 16GB RAM, CPU is rarely the constraint.
- Formula: start at
5, raise only if profiling shows idle time between API responses.
Cron (scheduled jobs)
Durable scheduler โ cron/jobs.py + cron/scheduler.py. Drive it via
the cronjob tool, the hermes cron CLI (list, add, edit,
pause, resume, run, remove), or the /cron slash command.
- Schedules: duration (
"30m", "2h"), "every" phrase
( "every monday 9am"), 5-field cron ( "0 9 *"), or ISO timestamp.
- Per-job knobs:
skills, model/provider override, script
(pre-run data collection; no_agent=True makes the script the whole
job), context_from (chain job A's output into job B), workdir
(run in a specific dir with its AGENTS.md / CLAUDE.md loaded),
multi-platform delivery.
- Invariants: 3-minute hard interrupt per run,
.tick.lock file
prevents duplicate ticks across processes, cron sessions pass
skip_memory=True by default, and cron deliveries are framed with a
header/footer instead of being mirrored into the target gateway
session (keeps role alternation intact).
User docs: https://hermes-agent.nousresearch.com/docs/user-guide/features/cron
Curator (skill lifecycle)
Background maintenance for agent-created skills. Tracks usage, marks
idle skills stale, archives stale ones, keeps a pre-run tar.gz backup
so nothing is lost.
- CLI:
hermes curator <verb> โ status, run, pause, resume,
pin, unpin, archive, restore, prune, backup, rollback.
- Slash:
/curator <subcommand> mirrors the CLI.
- Scope: only touches skills with
created_by: "agent" provenance.
Bundled + hub-installed skills are off-limits. Never deletes โ
max destructive action is archive. Pinned skills are exempt from
every auto-transition and every LLM review pass.
- Telemetry: sidecar at
~/.hermes/skills/.usage.json holds
per-skill use_count, view_count, patch_count,
last_activity_at, state, pinned.
Config: curator.* (enabled, interval_hours, min_idle_hours,
stale_after_days, archive_after_days, backup.*).
User docs: https://hermes-agent.nousresearch.com/docs/user-guide/features/curator
Dreaming (periodic memory/skill consolidation)
For Anthropic-style "dreaming" workflows, combine cron + session_search + memory + skills + curator into a scheduled review loop. Start with a weekly, proposal-only report that audits recent sessions, repeated user corrections, memory conflicts, skill patch candidates, and cron/automation improvements. Do not automatically delete/replace memory or patch/archive skills unless the user explicitly approves the proposed changes. See references/weekly-dreaming-routine.md for the recommended prompt, report format, safety policy, and cron creation pattern.
Kanban (multi-agent work queue)
Durable SQLite board for multi-profile / multi-worker collaboration.
Users drive it via hermes kanban <verb>; dispatcher-spawned workers
see a focused kanban_* toolset gated by HERMES_KANBAN_TASK so the
schema footprint is zero outside worker processes.
- CLI verbs (common):
init, create, list (alias ls),
show, assign, link, unlink, comment, complete, block,
unblock, archive, tail. Less common: watch, stats, runs,
log, dispatch, daemon, gc.
- Worker toolset:
kanban_show, kanban_complete, kanban_block,
kanban_heartbeat, kanban_comment, kanban_create, kanban_link.
- Dispatcher runs inside the gateway by default
( kanban.dispatch_in_gateway: true) โ reclaims stale claims,
promotes ready tasks, atomically claims, spawns assigned profiles.
Auto-blocks a task after ~5 consecutive spawn failures.
- Isolation: board is the hard boundary (workers get
HERMES_KANBAN_BOARD pinned in env); tenant is a soft namespace
within a board for workspace-path + memory-key isolation.
User docs: https://hermes-agent.nousresearch.com/docs/user-guide/features/kanban
Log Relay (Hermes โ Discord)
A background Python script that tails ~/.hermes/logs/*.log and batches lines to a Discord channel. Includes session-ID extraction, rate-limit handling, and auto-restart via launchd/systemd. Useful for remote monitoring and audit trails.
- Reference:
references/discord-log-relay.md โ full setup, tuning, macOS/Linux service install, pitfalls.
- Template:
templates/discord-log-relay.py โ copy, set CHANNEL_ID, and deploy.
- Discord operations:
references/discord-operating-planes.md โ channel-purpose routing, periodic-summary vs Dreaming report formats, and safety/cost notes for Discord-first Hermes deployments.
Key pitfall: ask the user about batch frequency upfront rather than defaulting to real-time streaming. Most users prefer 10-minute or hourly batches. High-volume raw logs should be batched, summarized, or stored out-of-band; avoid Discord message storms during error loops.
Weekly Dreaming / Memory Curation
For long-running Hermes deployments, users may want an Anthropic-style "Dreaming" loop: a scheduled review that consolidates experience, proposes memory/skill/cron changes, and identifies what to keep, weaken, archive, or delete. Hermes has the building blocks (sessions, session_search, memory, skills, curator, cron), but the safe default is proposal mode:
1. Inspect recent usage and sessions.
2. Extract repeated success patterns, failure patterns, and user corrections.
3. Propose memory updates/removals without applying them silently.
4. Propose skill patches/archive candidates and cron/reporting improvements.
5. End with explicit approval checkboxes.
Do not silently rewrite or delete memory/skills from a Dreaming report unless the user explicitly authorized automatic application. See references/discord-operating-planes.md for a report template and routing heuristics.
---
Windows-Specific Quirks
Hermes runs natively on Windows (PowerShell, cmd, Windows Terminal, git-bash
mintty, VS Code integrated terminal). Most of it just works, but a handful
of differences between Win32 and POSIX have bitten us โ document new ones
here as you hit them so the next person (or the next session) doesn't
rediscover them from scratch.
Input / Keybindings
Alt+Enter doesn't insert a newline. Windows Terminal intercepts Alt+Enter
at the terminal layer to toggle fullscreen โ the keystroke never reaches
prompt_toolkit. Use Ctrl+Enter instead. Windows Terminal delivers
Ctrl+Enter as LF ( c-j), distinct from plain Enter ( c-m / CR), and the
CLI binds c-j to newline insertion on win32 only (see
_bind_prompt_submit_keys + the Windows-only c-j binding in cli.py).
Side effect: the raw Ctrl+J keystroke also inserts a newline on Windows โ
unavoidable, because Windows Terminal collapses Ctrl+Enter and Ctrl+J to
the same keycode at the Win32 console API layer. No conflicting binding
existed for Ctrl+J on Windows, so this is a harmless side effect.
mintty / git-bash behaves the same (fullscreen on Alt+Enter) unless you
disable Alt+Fn shortcuts in Options โ Keys. Easier to just use Ctrl+Enter.
Diagnosing keybindings. Run python scripts/keystroke_diagnostic.py
(repo root) to see exactly how prompt_toolkit identifies each keystroke
in the current terminal. Answers questions like "does Shift+Enter come
through as a distinct key?" (almost never โ most terminals collapse it
to plain Enter) or "what byte sequence is my terminal sending for
Ctrl+Enter?" This is how the Ctrl+Enter = c-j fact was established.
Config / Files
HTTP 400 "No models provided" on first run. config.yaml was saved
with a UTF-8 BOM (common when Windows apps write it). Re-save as UTF-8
without BOM. hermes config edit writes without BOM; manual edits in
Notepad are the usual culprit.
execute_code / Sandbox
WinError 10106 ("The requested service provider could not be loaded
or initialized") from the sandbox child process โ it can't create an
AF_INET socket, so the loopback-TCP RPC fallback fails before
connect(). Root cause is usually not a broken Winsock LSP; it's
Hermes's own env scrubber dropping SYSTEMROOT / WINDIR / COMSPEC
from the child env. Python's socket module needs SYSTEMROOT to locate
mswsock.dll. Fixed via the _WINDOWS_ESSENTIAL_ENV_VARS allowlist in
tools/code_execution_tool.py. If you still hit it, echo os.environ
inside an execute_code block to confirm SYSTEMROOT is set. Full
diagnostic recipe in references/execute-code-sandbox-env-windows.md.
Testing / Contributing
scripts/run_tests.sh doesn't work as-is on Windows โ it looks for
POSIX venv layouts ( .venv/bin/activate). The Hermes-installed venv at
venv/Scripts/ has no pip or pytest either (stripped for install size).
Workaround: install pytest + pytest-xdist + pyyaml into a system Python
3.11 user site, then invoke pytest directly with PYTHONPATH set:
"/c/Program Files/Python311/python" -m pip install --user pytest pytest-xdist pyyaml
export PYTHONPATH="$(pwd)"
"/c/Program Files/Python311/python" -m pytest tests/foo/test_bar.py -v --tb=short -n 0
Use -n 0, not -n 4 โ pyproject.toml's default addopts already
includes -n, and the wrapper's CI-parity guarantees don't apply off POSIX.
POSIX-only tests need skip guards. Common markers already in the codebase:
- Symlinks โ elevated privileges on Windows
0o600 file modes โ POSIX mode bits not enforced on NTFS by default
signal.SIGALRM โ Unix-only (see tests/conftest.py::_enforce_test_timeout)
- Winsock / Windows-specific regressions โ
@pytest.mark.skipif(sys.platform != "win32", ...)
Use the existing skip-pattern style (sys.platform == "win32" or
sys.platform.startswith("win")) to stay consistent with the rest of the
suite.
Path / Filesystem
Line endings. Git may warn LF will be replaced by CRLF the next time
Git touches it. Cosmetic โ the repo's .gitattributes normalizes. Don't
let editors auto-convert committed POSIX-newline files to CRLF.
Forward slashes work almost everywhere. C:/Users/... is accepted by
every Hermes tool and most Windows APIs. Prefer forward slashes in code
and logs โ avoids shell-escaping backslashes in bash.
---
Troubleshooting
Voice not working
1. Check stt.enabled: true in config.yaml
2. Verify provider: pip install faster-whisper or set API key
3. In gateway: /restart. In CLI: exit and relaunch.
Tool not available
1. hermes tools โ check if toolset is enabled for your platform
2. Some tools need env vars (check .env)
3. /reset after enabling tools
Model/provider issues
1. hermes doctor โ check config and dependencies
2. hermes auth add <provider> โ re-authenticate OAuth providers (use --type oauth)
3. Check .env has the right API key
4. Copilot 403: gh auth login tokens do NOT work for Copilot API. You must use the Copilot-specific OAuth device code flow via hermes model โ GitHub Copilot.
Changes not taking effect
- Tools/skills:
/reset starts a new session with updated toolset
- Config changes: In gateway:
/restart. In CLI: exit and relaunch.
- Code changes: Restart the CLI or gateway process
Deployed web dashboard shows stale CSS or theme changes
- Browser cache: Add
?v=N cache-busting query strings to CSS/JS/theme links in HTML.
- Service Worker cache: Bump
CACHE_NAME in sw.js to invalidate old shell caches.
- Automated bump script: For projects with multiple HTML entry points (dashboard, gather, etc.), use
scripts/bump-build.py to atomically update all build badges, cache-busting query strings, and service worker cache names in one command. See references/autonomous-lab-version-drift.md for usage.
- Data freshness: Use
fetch(url, {cache:'no-store'}) for live JSON feeds.
- Auto-detection: Embed
data-build in <html> and compare server build vs loaded build on page load to show a "new version available" banner. See references/static-site-cache-invalidation.md for the full diagnostic recipe and auto-detection pattern.
- Theme switcher reliability: If theme switching works in Chrome but not Samsung Internet, or feels broken on mobile, see
references/theme-switcher-reliability.md for the create-new-link โ load โ remove-old pattern.
- Emergency recovery: If a bad deploy breaks the main app JS, users need a standalone reset page. See
references/emergency-reset-page.md for a zero-dependency reset.html that clears Service Workers and caches without relying on the main app's JS.
Dashboard inspector feels too technical
- The default inspector view should contain only plain-language sentences: headline, "what they're doing now", "why it matters", and a silent visual progress bar (no text label).
- Move all technical fields (source IDs, confidence scores, progress labels, status slugs, badges) behind a "Show technical details" toggle.
- If users say "details are hard to understand," the fix is to remove more fields from the default view, not to add explanations. Explanations of technical fields are still technical.
- See
references/progressive-disclosure-human-first.md for the aggressive simplification pattern.
Pixel-art characters look wrong on mobile
- Decorative CSS elements (cheeks, ears, tails, badges) can be misread as facial features or appendages when avatars shrink below ~50 px.
- Hide them inside
@media (max-width:480px) so only the essential silhouette remains.
- See
references/pixel-art-mobile-readability.md for the exact selectors and rationale.
Skills not showing
1. hermes skills list โ verify installed
2. hermes skills config โ check platform enablement
3. Load explicitly: /skill name or hermes -s name
Gateway issues
Check logs first:
grep -i "failed to send\|error" ~/.hermes/logs/gateway.log | tail -20
Common gateway problems:
- Gateway dies on SSH logout: Enable linger:
sudo loginctl enable-linger $USER
- Gateway dies on WSL2 close: WSL2 requires
systemd=true in /etc/wsl.conf for systemd services to work. Without it, gateway falls back to nohup (dies when session closes).
- Gateway crash loop: Reset the failed state:
systemctl --user reset-failed hermes-gateway
- macOS: bot shows offline after idle time: The gateway runs as a user agent (
LimitLoadToSessionType=Aqua), so macOS suspends it when the system sleeps. The platform websocket drops and the bot appears offline until the network returns. Fix: keep the Mac awake (System Settings -> Energy -> Prevent automatic sleeping, or caffeinate -d -i -s -u &). Low Power Mode makes this worse, not better. See references/macos-gateway-sleep-disconnect.md for the full diagnostic recipe.
Platform-specific issues
- Discord bot silent: Must enable Message Content Intent in Bot โ Privileged Gateway Intents. See full Discord setup reference:
references/discord-gateway-setup.md.
- Slack bot only works in DMs: Must subscribe to
message.channels event. Without it, the bot ignores public channels.
- Windows-specific issues (
Alt+Enter newline, WinError 10106, UTF-8 BOM config, test suite, line endings): see the dedicated Windows-Specific Quirks section above.
Auxiliary models not working
If auxiliary tasks (vision, compression, session_search) fail silently, the auto provider can't find a backend. Either set OPENROUTER_API_KEY or GOOGLE_API_KEY, or explicitly configure each auxiliary task's provider:
hermes config set auxiliary.vision.provider <your_provider>
hermes config set auxiliary.vision.model <model_name>
Full system auth provisioning
For a one-shot workflow to maximize available credentials โ installing gh, generating SSH keys, configuring git, enabling all Hermes toolsets, and auditing current auth state โ see references/system-auth-setup.md.
Editing large files with patch
When a file is read with read_file(offset=...) (pagination), the tool warns that the view is partial. If you attempt patch without re-reading the full file first, you will likely hit non-unique match errors or corrupt the file. Fix: always call read_file without offset to load the whole file before patching. The tool explicitly warns: "โฆwas last read with offset/limit pagination (partial view). Re-read the whole file before overwriting it." โ heed this warning. For append-only updates (e.g., adding a cycle log entry to state.md), do not use terminal(command="cat >> file << 'EOF'...EOF") โ the terminal tool on macOS/Linux misinterprets heredoc << as backgrounding and fails. Instead, write a short Python script via write_file and execute it with terminal(command="python3 /tmp/script.py"). See references/terminal-heredoc-workaround.md for the full pattern.
Shell scripts that call Python with dependencies
Project shell scripts ( test.sh, publish.sh, validate_setup.sh) often call python3 to parse YAML or run helpers. On macOS and some Linux systems, the system python3 lacks PyYAML, causing scripts to fail with ModuleNotFoundError. See references/shell-script-python-auto-detection.md for a reusable find_python() pattern that auto-detects a Python interpreter with the required packages.
Sibling subagent file overwrites
When multiple subagents are running in parallel (e.g. via delegate_task batch mode or kanban worker lanes), a file may be modified by one subagent while another is about to write to it. If you use write_file or patch on a file that was last read before a sibling subagent modified it, your write may silently truncate or revert the sibling's changes. The tool may show a warning like "this file was modified by sibling subagent X but this agent never read it."
Fix:
1. Heed the warning. If the tool reports a sibling modification, re-read the file with read_file before writing.
2. Prefer patch over write_file for partial updates โ patch only changes the matched region and is less likely to wipe unrelated content.
3. If the file is already published/deployed, and the local working copy gets corrupted, recover from the published copy:
cp ~/hermes-web/agent-pets/css/dashboard.css ~/.hermes/autonomous-agent-lab/pixel-pet-ops/web/css/dashboard.css
4. For append-only updates, write a small Python script and execute it rather than using write_file on the whole file.
Prevention: In kanban/multi-agent workflows, assign file-level ownership so only one worker touches each file. If parallel workers must edit the same file, have them write to separate temp files and let the orchestrator merge.
---
Windows-Specific Quirks
| Looking for... | Location |
|----------------|----------|
| Config options | hermes config edit or [Configuration docs](https://hermes-agent.nousresearch.com/docs/user-guide/configuration) |
| Available tools | hermes tools list or [Tools reference](https://hermes-agent.nousresearch.com/docs/reference/tools-reference) |
| Slash commands | /help in session or [Slash commands reference](https://hermes-agent.nousresearch.com/docs/reference/slash-commands) |
| Skills catalog | hermes skills browse or [Skills catalog](https://hermes-agent.nousresearch.com/docs/reference/skills-catalog) |
| Provider setup | hermes model or [Providers guide](https://hermes-agent.nousresearch.com/docs/integrations/providers) |
| Platform setup | hermes gateway setup or [Messaging docs](https://hermes-agent.nousresearch.com/docs/user-guide/messaging/) |
| MCP servers | hermes mcp list or [MCP guide](https://hermes-agent.nousresearch.com/docs/user-guide/features/mcp) |
| Profiles | hermes profile list or [Profiles docs](https://hermes-agent.nousresearch.com/docs/user-guide/profiles) |
| Cron jobs | hermes cron list or [Cron docs](https://hermes-agent.nousresearch.com/docs/user-guide/features/cron) |
| Memory | hermes memory status or [Memory docs](https://hermes-agent.nousresearch.com/docs/user-guide/features/memory) |
| Env variables | hermes config env-path or [Env vars reference](https://hermes-agent.nousresearch.com/docs/reference/environment-variables) |
| CLI commands | hermes --help or [CLI reference](https://hermes-agent.nousresearch.com/docs/reference/cli-commands) |
| Gateway logs | ~/.hermes/logs/gateway.log |
| Session files | ~/.hermes/sessions/ or hermes sessions browse |
| Source code | ~/.hermes/hermes-agent/ |
---
Contributor Quick Reference
For occasional contributors and PR authors. Full developer docs: https://hermes-agent.nousresearch.com/docs/developer-guide/
Project Layout
hermes-agent/
โโโ run_agent.py # AIAgent โ core conversation loop
โโโ model_tools.py # Tool discovery and dispatch
โโโ toolsets.py # Toolset definitions
โโโ cli.py # Interactive CLI (HermesCLI)
โโโ hermes_state.py # SQLite session store
โโโ agent/ # Prompt builder, context compression, memory, model routing, credential pooling, skill dispatch
โโโ hermes_cli/ # CLI subcommands, config, setup, commands
โ โโโ commands.py # Slash command registry (CommandDef)
โ โโโ config.py # DEFAULT_CONFIG, env var definitions
โ โโโ main.py # CLI entry point and argparse
โโโ tools/ # One file per tool
โ โโโ registry.py # Central tool registry
โโโ gateway/ # Messaging gateway
โ โโโ platforms/ # Platform adapters (telegram, discord, etc.)
โโโ cron/ # Job scheduler
โโโ tests/ # ~3000 pytest tests
โโโ website/ # Docusaurus docs site
Config: ~/.hermes/config.yaml (settings), ~/.hermes/.env (API keys).
Adding a Tool (3 files)
1. Create tools/your_tool.py:
import json, os
from tools.registry import registry
def check_requirements() -> bool:
return bool(os.getenv("EXAMPLE_API_KEY"))
def example_tool(param: str, task_id: str = None) -> str:
return json.dumps({"success": True, "data": "..."})
registry.register(
name="example_tool",
toolset="example",
schema={"name": "example_tool", "description": "...", "parameters": {...}},
handler=lambda args, **kw: example_tool(
param=args.get("param", ""), task_id=kw.get("task_id")),
check_fn=check_requirements,
requires_env=["EXAMPLE_API_KEY"],
)
2. Add to toolsets.py โ _HERMES_CORE_TOOLS list.
Auto-discovery: any tools/*.py file with a top-level registry.register() call is imported automatically โ no manual list needed.
All handlers must return JSON strings. Use get_hermes_home() for paths, never hardcode ~/.hermes.
Adding a Slash Command
1. Add CommandDef to COMMAND_REGISTRY in hermes_cli/commands.py
2. Add handler in cli.py โ process_command()
3. (Optional) Add gateway handler in gateway/run.py
All consumers (help text, autocomplete, Telegram menu, Slack mapping) derive from the central registry automatically.
Agent Loop (High Level)
run_conversation():
1. Build system prompt
2. Loop while iterations < max:
a. Call LLM (OpenAI-format messages + tool schemas)
b. If tool_calls โ dispatch each via handle_function_call() โ append results โ continue
c. If text response โ return
3. Context compression triggers automatically near token limit
Testing
python -m pytest tests/ -o 'addopts=' -q # Full suite
python -m pytest tests/tools/ -q # Specific area
- Tests auto-redirect
HERMES_HOME to temp dirs โ never touch real ~/.hermes/
- Run full suite before pushing any change
- Use
-o 'addopts=' to clear any baked-in pytest flags
Windows contributors: scripts/run_tests.sh currently looks for POSIX venvs ( .venv/bin/activate / venv/bin/activate) and will error out on Windows where the layout is venv/Scripts/activate + python.exe. The Hermes-installed venv at venv/Scripts/ also has no pip or pytest โ it's stripped for end-user install size. Workaround: install pytest + pytest-xdist + pyyaml into a system Python 3.11 user site ( /c/Program Files/Python311/python -m pip install --user pytest pytest-xdist pyyaml), then run tests directly:
export PYTHONPATH="$(pwd)"
"/c/Program Files/Python311/python" -m pytest tests/tools/test_foo.py -v --tb=short -n 0
Use -n 0 (not -n 4) because pyproject.toml's default addopts already includes -n, and the wrapper's CI-parity story doesn't apply off-POSIX.
Cross-platform test guards: tests that use POSIX-only syscalls need a skip marker. Common ones already in the codebase:
- Symlink creation โ
@pytest.mark.skipif(sys.platform == "win32", reason="Symlinks require elevated privileges on Windows") (see tests/cron/test_cron_script.py)
- POSIX file modes (0o600, etc.) โ
@pytest.mark.skipif(sys.platform.startswith("win"), reason="POSIX mode bits not enforced on Windows") (see tests/hermes_cli/test_auth_toctou_file_modes.py)
signal.SIGALRM โ Unix-only (see tests/conftest.py::_enforce_test_timeout)
- Live Winsock / Windows-specific regression tests โ
@pytest.mark.skipif(sys.platform != "win32", reason="Windows-specific regression")
Monkeypatching sys.platform is not enough when the code under test also calls platform.system() / platform.release() / platform.mac_ver(). Those functions re-read the real OS independently, so a test that sets sys.platform = "linux" on a Windows runner will still see platform.system() == "Windows" and route through the Windows branch. Patch all three together:
monkeypatch.setattr(sys, "platform", "linux")
monkeypatch.setattr(platform, "system", lambda: "Linux")
monkeypatch.setattr(platform, "release", lambda: "6.8.0-generic")
See tests/agent/test_prompt_builder.py::TestEnvironmentHints for a worked example.
Extending the system prompt's execution-environment block
Factual guidance about the host OS, user home, cwd, terminal backend, and shell (bash vs. PowerShell on Windows) is emitted from agent/prompt_builder.py::build_environment_hints(). This is also where the WSL hint and per-backend probe logic live. The convention:
- Local terminal backend โ emit host info (OS,
$HOME, cwd) + Windows-specific notes (hostname โ username, terminal uses bash not PowerShell).
- Remote terminal backend (anything in
_REMOTE_TERMINAL_BACKENDS: docker, singularity, modal, daytona, ssh, vercel_sandbox, managed_modal) โ suppress host info entirely and describe only the backend. A live uname/whoami/pwd probe runs inside the backend via tools.environments.get_environment(...).execute(...), cached per process in _BACKEND_PROBE_CACHE, with a static fallback if the probe times out.
- Key fact for prompt authoring: when
TERMINAL_ENV != "local", every file tool (read_file, write_file, patch, search_files) runs inside the backend container, not on the host. The system prompt must never describe the host in that case โ the agent can't touch it.
Full design notes, the exact emitted strings, and testing pitfalls:
references/prompt-builder-environment-hints.md.
Refactor-safety pattern (POSIX-equivalence guard): when you extract inline logic into a helper that adds Windows/platform-specific behavior, keep a _legacy_<name> oracle function in the test file that's a verbatim copy of the old code, then parametrize-diff against it. Example: tests/tools/test_code_execution_windows_env.py::TestPosixEquivalence. This locks in the invariant that POSIX behavior is bit-for-bit identical and makes any future drift fail loudly with a clear diff.
Commit Conventions
type: concise subject line
Optional body.
Types: fix:, feat:, refactor:, docs:, chore:
Key Rules
- Never break prompt caching โ don't change context, tools, or system prompt mid-conversation
- Message role alternation โ never two assistant or two user messages in a row
- Use
get_hermes_home() from hermes_constants for all paths (profile-safe)
- Config values go in
config.yaml, secrets go in .env
- New tools need a
check_fn so they only appear when requirements are met
[IMPORTANT: The user has invoked the "kanban-orchestrator" skill, indicating they want you to follow its instructions. The full skill content is loaded below.]
---
name: kanban-orchestrator
description: Decomposition playbook + anti-temptation rules for an orchestrator profile routing work through Kanban. The "don't do the work yourself" rule and the basic lifecycle are auto-injected into every kanban worker's system prompt; this skill is the deeper playbook when you're specifically playing the orchestrator role.
version: 3.0.0
platforms: [linux, macos, windows]
metadata:
hermes:
tags: [kanban, multi-agent, orchestration, routing]
related_skills: [kanban-worker]
---
Kanban Orchestrator โ Decomposition Playbook
> The core worker lifecycle (including the kanban_create fan-out pattern and the "decompose, don't execute" rule) is auto-injected into every kanban process via the KANBAN_GUIDANCE system-prompt block. This skill is the deeper playbook when you're an orchestrator profile whose whole job is routing.
Profiles are user-configured โ not a fixed roster
Hermes setups vary widely. Some users run a single profile that does everything; some run a small fleet (docker-worker, cron-worker); some run a curated specialist team they've named themselves. There is no default specialist roster โ the orchestrator skill does not know what profiles exist on this machine.
Before fanning out, you must ground the decomposition in the profiles that actually exist. The dispatcher silently fails to spawn unknown assignee names โ it doesn't autocorrect, doesn't suggest, doesn't fall back. So a card assigned to researcher on a setup that only has docker-worker just sits in ready forever.
Step 0: discover available profiles before planning.
Use one of these:
hermes profile list โ prints the table of profiles configured on this machine. Run it through your terminal tool if you have one; otherwise ask the user.
kanban_list(assignee="<some-name>") โ sanity-check a single name. Returns an empty list (rather than an error) for an unknown assignee, so this only confirms a name you're already considering.
- Just ask the user. "What profiles do you have set up?" is a fine first turn when the goal needs more than one specialist.
Cache the result in your working memory for the rest of the conversation. Re-asking every turn wastes a tool call.
When to use the board (vs. just doing the work)
Create Kanban tasks when any of these are true:
1. Multiple specialists are needed. Research + analysis + writing is three profiles.
2. The work should survive a crash or restart. Long-running, recurring, or important.
3. The user might want to interject. Human-in-the-loop at any step.
4. Multiple subtasks can run in parallel. Fan-out for speed.
5. Review / iteration is expected. A reviewer profile loops on drafter output.
6. The audit trail matters. Board rows persist in SQLite forever.
If none of those apply โ it's a small one-shot reasoning task โ use delegate_task instead or answer the user directly.
The anti-temptation rules
Your job description says "route, don't execute." The rules that enforce that:
- Do not execute the work yourself. Your restricted toolset usually doesn't even include terminal/file/code/web for implementation. If you find yourself "just fixing this quickly" โ stop and create a task for the right specialist.
- For any concrete task, create a Kanban task and assign it. Every single time.
- Split multi-lane requests before creating cards. A user prompt can contain several independent workstreams. Extract those lanes first, then create one card per lane instead of bundling unrelated work into a single implementer card.
- Run independent lanes in parallel. If two cards do not need each other's output, leave them unlinked so the dispatcher can fan them out. Link only true data dependencies.
- If no specialist fits the available profiles, ask the user which profile to create or which existing profile to use. Do not invent profile names; the dispatcher will silently drop unknown assignees.
- Decompose, route, and summarize โ that's the whole job.
Exception: micro-UI polish cycles
There is one narrow exception where the orchestrator may execute directly instead of creating Kanban cards: tiny UI-only polish cycles (e.g., adding a CSS class, a theme preview dot, a hover state, a cross-link, or a HUD button) that are purely presentational, require no cross-file logic changes, and fit comfortably inside a single bounded cycle with no need for review or parallel work. If the change is limited to HTML/CSS/JS cosmetics, no other profile has a stake in it, and the user did not ask for a design review, the orchestrator should just edit and publish rather than paying the kanban-overhead tax. This exception does NOT apply to architecture changes, adapter logic, plugin interfaces, or anything that touches the data layer.
Decomposition playbook
Step 1 โ Understand the goal
Ask clarifying questions if the goal is ambiguous. Cheap to ask; expensive to spawn the wrong fleet.
Step 2 โ Sketch the task graph
Before creating anything, draft the graph out loud (in your response to the user). Treat every concrete workstream as a candidate card:
1. Extract the lanes from the request.
2. Map each lane to one of the profiles you discovered in Step 0. If a lane doesn't fit any existing profile, ask the user which to use or create.
3. Decide whether each lane is independent or gated by another lane.
4. Create independent lanes as parallel cards with no parent links.
5. Create synthesis/review/integration cards with parent links to the lanes they depend on.
Examples of prompts that should fan out (using placeholder profile names โ substitute whatever exists on the user's setup):
- "Build an app" โ one card to a design-oriented profile for product/UI direction, one or two cards to engineering profiles for implementation, plus a later integration/review card if the user has a reviewer profile.
- "Fix blockers and check model variants" โ one implementation card for the blocker fixes plus one discovery/research card for config/source verification. A final reviewer card can depend on both.
- "Research docs and implement" โ a docs-research card can run in parallel with a codebase-discovery card; implementation waits only if it truly needs those findings.
- "Analyze this screenshot and find the related code" โ one card to a vision-capable profile for the visual analysis while another searches the codebase.
Words like "also," "finally," or "and" do not automatically imply a dependency. They often mean "make sure this is covered before reporting back." Only link tasks when one card cannot start until another card's output exists.
Show the graph to the user before creating cards. Let them correct it โ including which actual profile name should own each lane.
Step 3 โ Create tasks and link
Use the profile names from Step 0. The example below uses placeholders <profile-A>, <profile-B>, <profile-C> โ replace them with what the user actually has.
t1 = kanban_create(
title="research: Postgres cost vs current",
assignee="<profile-A>", # whichever profile handles research on this setup
body="Compare estimated infrastructure costs, migration costs, and ongoing ops costs over a 3-year window. Sources: AWS/GCP pricing, team time estimates, current Postgres bills from peers.",
tenant=os.environ.get("HERMES_TENANT"),
)["task_id"]
t2 = kanban_create(
title="research: Postgres performance vs current",
assignee="<profile-A>", # same profile, run in parallel
body="Compare query latency, throughput, and scaling characteristics at our expected data volume (~500GB, 10k QPS peak). Sources: benchmark papers, public case studies, pgbench results if easy.",
)["task_id"]
t3 = kanban_create(
title="synthesize migration recommendation",
assignee="<profile-B>", # whichever profile does synthesis/analysis
body="Read the findings from T1 (cost) and T2 (performance). Produce a 1-page recommendation with explicit trade-offs and a go/no-go call.",
parents=[t1, t2],
)["task_id"]
t4 = kanban_create(
title="draft decision memo",
assignee="<profile-C>", # whichever profile drafts user-facing prose
body="Turn the analyst's recommendation into a 2-page memo for the CTO. Match the tone of previous decision memos in the team's knowledge base.",
parents=[t3],
)["task_id"]
parents=[...] gates promotion โ children stay in todo until every parent reaches done, then auto-promote to ready. No manual coordination needed; the dispatcher and dependency engine handle it.
Step 4 โ Complete your own task
If you were spawned as a task yourself (e.g. a planner profile was assigned T0: "investigate Postgres migration"), mark it done with a summary of what you created:
kanban_complete(
summary="decomposed into T1-T4: 2 research lanes in parallel, 1 synthesis on their outputs, 1 prose draft on the recommendation",
metadata={
"task_graph": {
"T1": {"assignee": "<profile-A>", "parents": []},
"T2": {"assignee": "<profile-A>", "parents": []},
"T3": {"assignee": "<profile-B>", "parents": ["T1", "T2"]},
"T4": {"assignee": "<profile-C>", "parents": ["T3"]},
},
},
)
Step 5 โ Report back to the user
Tell them what you created in plain prose, naming the actual profiles you used:
> I've queued 4 tasks:
> - T1 (<profile-A>): cost comparison
> - T2 (<profile-A>): performance comparison, in parallel with T1
> - T3 (<profile-B>): synthesizes T1 + T2 into a recommendation
> - T4 (<profile-C>): turns T3 into a CTO memo
>
> The dispatcher will pick up T1 and T2 now. T3 starts when both finish. You'll get a gateway ping when T4 completes. Use the dashboard or hermes kanban tail <id> to follow along.
Common patterns
Fan-out + fan-in (research โ synthesize): N research-style cards with no parents, one synthesis card with all of them as parents.
Parallel implementation + validation: one implementer card makes the change while one explorer/researcher card verifies config, docs, or source mapping. A reviewer card can depend on both. Do not make the implementer own unrelated verification just because the user mentioned both in one sentence.
Pipeline with gates: planner โ implementer โ reviewer. Each stage's parents=[previous_task]. Reviewer blocks or completes; if reviewer blocks, the operator unblocks with feedback and respawns.
Same-profile queue: N tasks, all assigned to the same profile, no dependencies between them. Dispatcher serializes โ that profile processes them in priority order, accumulating experience in its own memory.
Parallel UI/frontend lanes: When the goal touches multiple independent HTML/CSS/JS files (e.g., a dashboard page and a 2D gather view), fan out to separate subagents per file. Each lane edits its own file, then the orchestrator integrates, fixes cross-file references (theme paths, shared JSON endpoints), and publishes. This avoids merge conflicts in single-file HTML dashboards and keeps each subagent's context focused. See references/parallel-ui-lanes-and-publishing.md for the post-subagent integration checklist and rsync safety notes.
Human-in-the-loop: Any task can kanban_block() to wait for input. Dispatcher respawns after /unblock. The comment thread carries the full context.
Pitfalls
Inventing profile names that don't exist. The dispatcher silently fails to spawn unknown assignees โ the card just sits in ready forever. Always assign to a profile from your Step 0 discovery; ask the user if you're unsure.
Bundling independent lanes into one card. If the user asks for two independent outcomes, create two cards. Example: "fix blockers and check model variants" is not one fixer task; create a fixer/engineer card for the fixes and an explorer/researcher card for the variant check, then optionally gate review on both.
Over-linking because of wording. "Finally check X" may still be parallel with implementation if X is static config, docs, or source discovery. Link it after implementation only when the check depends on the implementation result.
Forgetting dependency links. If the task graph says research -> implement -> review, do not create all tasks as independent ready cards. Use parent links so implement/review cannot run before their inputs exist.
Reassignment vs. new task. If a reviewer blocks with "needs changes," create a NEW task linked from the reviewer's task โ don't re-run the same task with a stern look. The new task is assigned to the original implementer profile.
Argument order for links. kanban_link(parent_id=..., child_id=...) โ parent first. Mixing them up demotes the wrong task to todo.
Ignoring explicit user feedback to keep building infrastructure. When the user says a specific UX issue (legibility, theme switching, movement density) is "immediate priority," treat it as P0 and route it before deeper packaging/architecture work. Infrastructure polish feels productive, but shipping user-visible fixes is what matters. Create cards for the UX feedback first, then resume infrastructure lanes.
Treating status: complete as immutable when user feedback says otherwise. A state.md that says status: complete does not override a user's report that a completion criterion is actually broken. If the user says "theme switching is not working" and the Final Completion Condition requires "working UI theme switcher," the mission is not complete. Reactivate immediately: set status: active, append a reactivation cycle log, and fix the issue. Do not burn cycles on post-complete verification while the user is reporting active defects.
Don't pre-create the whole graph if the shape depends on intermediate findings. If T3's structure depends on what T1 and T2 find, let T3 exist as a "synthesize findings" task whose own first step is to read parent handoffs and plan the rest. Orchestrators can spawn orchestrators.
Tenant inheritance. If HERMES_TENANT is set in your env, pass tenant=os.environ.get("HERMES_TENANT") on every kanban_create call so child tasks stay in the same namespace.
Verifying cross-file references after directory reorganization. When subagents edit HTML/CSS/JS files and the directory structure shifts (e.g., moving files from root into web/dashboard/ and web/gather/), relative asset paths ( themes/default/theme.css, ./ops-data.json) often break. After subagents finish, the orchestrator must grep for href= and src= in moved files and fix relative paths before publishing. Subagents don't know the final publish layout โ the orchestrator does.
Destructive sync wipes needed files. Commands like rsync -av --delete will delete destination files that aren't in the source list. If you publish a directory tree piecemeal (e.g., copy web/dashboard/ first, then web/gather/ separately), --delete on the first rsync will erase the gather files before the second rsync runs. Either list all source paths in a single rsync invocation, or omit --delete and use cp -r / rsync -av without deletion when doing staged copies.
Recovering stuck workers
When a worker profile keeps crashing, hallucinating, or getting blocked by its own mistakes (usually: wrong model, missing skill, broken credential), the kanban dashboard flags the task with a โ badge and opens a Recovery section in the drawer. Three primary actions:
1. Reclaim (or hermes kanban reclaim <task_id>) โ abort the running worker immediately and reset the task to ready. The existing claim TTL is ~15 min; this is the fast path out.
2. Reassign (or hermes kanban reassign <task_id> <new-profile> --reclaim) โ switch the task to a different profile (one that exists on this setup) and let the dispatcher pick it up with a fresh worker.
3. Change profile model โ the dashboard prints a copy-paste hint for hermes -p <profile> model since profile config lives on disk; edit it in a terminal, then Reclaim to retry with the new model.
Hallucination warnings appear on tasks where a worker's kanban_complete(created_cards=[...]) claim included card ids that don't exist or weren't created by the worker's profile (the gate blocks the completion), or where the free-form summary references t_<hex> ids that don't resolve (advisory prose scan, non-blocking). Both produce audit events that persist even after recovery actions โ the trail stays for debugging.
The user has provided the following instruction alongside the skill invocation: [IMPORTANT: You are running as a scheduled cron job. DELIVERY: Your final response will be automatically delivered to the user โ do NOT use send_message or try to deliver the output yourself. Just produce your report/output as your final response and the system handles the rest. SILENT: If there is genuinely nothing new to report, respond with exactly "[SILENT]" (nothing else) to suppress delivery. Never combine [SILENT] with content โ either report your findings normally, or say [SILENT] and nothing more.]
You are the 15-minute Orchestrator for Son's Autonomous Agent Lab v1, reporting to Discord channel ID 1505805763824586952.
Durable state path: /Users/jooho-hermes/.hermes/autonomous-agent-lab/state.md
Working directory for experiment artifacts: /Users/jooho-hermes/.hermes/autonomous-agent-lab/
Preferred published web root: /Users/jooho-hermes/hermes-web/agent-pets/
Top-level directive from Son:
- The project has evolved from a personal dashboard into an INSTALLABLE PRODUCT that external Hermes users can deploy.
- The final target is a self-contained, configurable, publishable solution: "Hermes Pixel Pet Ops Office".
- Do NOT shrink the mission into a small static MVP and autonomously stop.
- The Gather.town-style 2D spatial office is a first-class feature, not a side page.
Latest UX feedback from Son (treat as immediate priority before deeper packaging work):
- Details are hard for a human to understand. Add human-first summaries, plain-language labels, and progressive disclosure: summary first, technical details second.
- Gather Town version has too many agents roaming around. Reduce default movement, add density/speed controls, cluster agents by room/task, and add focus/calm mode.
- Theme switching is not visibly working. Implement real UI theme switcher with persistence and clear visual theme changes.
Key product requirements (installable solution level):
1. Config-driven architecture: all paths, URLs, colors, names, room layouts via config.yaml. No hardcoded references to jooho-hermes.
2. Self-contained package: clear directory structure (src/, web/, config/, docs/, scripts/), install script, requirements.txt.
3. Pluggable data adapter: support multiple backends via plugin architecture.
4. Themeable frontend: CSS variables driven from config, swappable themes, plus a working UI theme switcher.
5. Multi-tenant ready: works for any Hermes instance.
6. Build/Deploy ready: Dockerfile or docker-compose, or clear static-server setup.
7. Documentation: README, architecture docs, configuration reference, contributor guide.
8. Human-comprehensible UX: plain-language summaries and progressive disclosure for technical detail.
9. Gather.town calm mode: adjustable movement density/speed and less chaotic defaults.
10. Versioned releases: CHANGELOG.md, semantic versioning, release packaging.
Mission model:
- Read state.md first before doing anything else.
- If state.md says
status: inactive or has no Current Mission, do not invent work. Return exactly: ๐ก Autonomous Agent Lab ๋๊ธฐ์ค โ Son์ด ํธ๋ฆฌ๊ฑฐ/๋ฏธ์
์ ์ฃผ๋ฉด 15๋ถ ์ฌ์ดํด์ ์์ํฉ๋๋ค.
- If state.md says
status: active, run one bounded 15-minute cycle toward the full installable solution.
- If state.md says
status: complete, verify that the Final Completion Condition in state.md is truly met. If it is not fully met, reactivate or report that state needs correction.
Cycle procedure when active:
1. Read state.md first. Extract current mission, constraints, previous cycle log, and Final Completion Condition.
2. Decide the next smallest useful step toward installable solution quality. Focus on: architecture, configurability, documentation, and clean separation of concerns.
3. Use delegate_task for independent subagent lanes when helpful.
4. Prefer concrete progress: refactor to config-driven, add install scripts, create docs, add Docker support, theme system, plugin architecture.
5. Update state.md with a new cycle log entry before final reporting.
6. Completion rule: only set status: complete when every item under state.md Final Completion Condition is satisfied. A non-installable MVP is not complete.
7. Stop/block only if Son explicitly stops/redirects, a safety boundary is reached, or a hard blocker needs Son's decision.
Link requirement (never forget):
- Every cycle report MUST include at least one direct viewable link to the published dashboard/artifact.
- The canonical URL:
http://hermes-mac-mini.tail46b3c6.ts.net:8099/agent-pets/
- Include gather town URL too:
http://hermes-mac-mini.tail46b3c6.ts.net:8099/agent-pets/gather/
Final Discord message format:
[Autonomous Agent Lab v1 / Cycle N]
๋ชฉํ:
์ํ:
๊ฒฐ๊ณผ:
๊ฒ์ฆ:
๋ค์:
์ํ:
Safety/quality rules:
- Do not handle secrets, passwords, API keys, payment, permission dialogs, or destructive commands.
- Do not claim completion without updating state.md.
- Do not rely on Discord history as durable state.
- Do not spam raw logs; summarize lane outputs and verification.
- Keep working in /Users/jooho-hermes/.hermes/autonomous-agent-lab/ and publish only to /Users/jooho-hermes/hermes-web/agent-pets/ unless the state file says otherwise.
Design/UX priorities:
- Mobile responsiveness is first-class.
- Character animation/movement is desired.
- Every cycle report must include published links.
- This is now a product engineering mission. Architecture, configurability, and documentation matter as much as visuals.
Response
[Autonomous Agent Lab v1 / Cycle 79]
๋ชฉํ:
- ๋ชจ๋ฐ์ผ ์ฌ์ฉ์ ํธ์์ฑ์ ์ํ Scroll-to-Top ํ๋กํ
๋ฒํผ ์ถ๊ฐ
- ์์คํ
์ ๋ฐ ๊ฑด๊ฐ ์ํ ํ์ธ ๋ฐ Publish
- Son์ UX ํผ๋๋ฐฑ(ํ
๋ง ์ค์์ฒ, Gather ์บ๋ชจ๋, Human-first inspector) ํ์ธ ๋๊ธฐ ์ค ์ง์์ ๊ฐ์
์ํ:
1. Dashboard Scroll-to-Top ๋ฒํผ (web/dashboard/index.html + css/dashboard.css + js/dashboard.js)
- ์ฐ์ธก ํ๋จ ๊ณ ์ ์์น, 300px ์ด์ ์คํฌ๋กค ์ ๋ํ๋จ
- ํด๋ฆญ ์ ๋ถ๋๋ฌ์ด ์คํฌ๋กค ์๋จ ์ด๋ (
behavior: 'smooth')
- ๊ธฐ์กด ์ค์ /์ง๋/์๋ฆผ ํ ๊ธ๊ณผ ๋์ผํ ํ
๋ง ์ฐ๋ ์คํ์ผ
- ๋ชจ๋ฐ์ผ ๋ฐ์ํ: 480px ์ดํ์์ ์ถ์
aria-label ์ ๊ทผ์ฑ ์ง์
2. ๋น๋ ๋ฐ ์บ์ ๋ฒ์คํ
v79
- Dashboard/Gather badge:
b78 โ b79
- Asset query strings:
?v=78 โ ?v=79
- Service Worker:
CACHE_NAME = 'pixel-pet-ops-v26'
data-build="79" / window.__HPPO_BUILD__ = 79
3. ํตํฉ ํ
์คํธ 3๊ฑด ์ถ๊ฐ โ ์ด 137๊ฑด ํต๊ณผ
4. Adapter ์คํ ๋ฐ Publish
generate_ops_data.py โ 32 agents, 15 cron jobs, 20 sessions, 16 events
scripts/publish.sh โ /Users/jooho-hermes/hermes-web/agent-pets/ ๋๊ธฐํ ์๋ฃ
๊ฒฐ๊ณผ:
- Dashboard: http://hermes-mac-mini.tail46b3c6.ts.net:8099/agent-pets/
- Gather Town: http://hermes-mac-mini.tail46b3c6.ts.net:8099/agent-pets/gather/
- Published badge:
v1.4.4 ยท b79
ops-data.json / health.json mtime < 60s
refresh.err.log ๋น์ด ์์ (LaunchAgent ์ ์)
๊ฒ์ฆ:
- Integration tests: 137/137 passed, 0 failed
- Setup validation: 21/21 passed, 0 warned, 0 critical
- Zero hardcoded
jooho-hermes references
ops-data.json schema 1.4, 32 agents, 16 events
health.json status: healthy, version: 1.4.4
๋ค์:
- Son์ด Dashboard ์ ์ ํ
v1.4.4 ยท b79 ๋ฐฐ์ง ํ์ธ
- Hero ํจ๋ ํ
๋ง ์ค์์ฒ, Gather ์บ๋ชจ๋(5 agents), Inspector human-first view ๊ฒ์ฆ ์์ฒญ
- Scroll-to-Top ๋ฒํผ ๋ชจ๋ฐ์ผ์์ ์ ์ ๋์ ํ์ธ
- ๋ง์กฑ ์
status: complete๋ก ์ ํ ๊ฐ๋ฅ
์ํ:
status: active ์ ์ง
- 11๊ฐ Final Completion Condition ๋ชจ๋ ์ถฉ์กฑ
- Son์ ๋ธ๋ผ์ฐ์ ์ฌ์ด๋ ํ์ธ ๋๊ธฐ ์ค
|
| 2026-05-20 03-10-18 |
84,353 chars |
2026-05-20_03-10-18.md |
Cron Job: autonomous-agent-lab-v1-orchestrator
Job ID: 35127ff89556
Run Time: 2026-05-20 03:10:18
Schedule: every 15m
Prompt
[IMPORTANT: The user has invoked the "hermes-agent" skill, indicating they want you to follow its instructions. The full skill content is loaded below.]
---
name: hermes-agent
description: "Configure, extend, or contribute to Hermes Agent."
version: 2.1.0
author: Hermes Agent + Teknium
license: MIT
platforms: [linux, macos, windows]
metadata:
hermes:
tags: [hermes, setup, configuration, multi-agent, spawning, cli, gateway, development]
homepage: https://github.com/NousResearch/hermes-agent
related_skills: [claude-code, codex, opencode]
---
Hermes Agent
Hermes Agent is an open-source AI agent framework by Nous Research that runs in your terminal, messaging platforms, and IDEs. It belongs to the same category as Claude Code (Anthropic), Codex (OpenAI), and OpenClaw โ autonomous coding and task-execution agents that use tool calling to interact with your system. Hermes works with any LLM provider (OpenRouter, Anthropic, OpenAI, DeepSeek, local models, and 15+ others) and runs on Linux, macOS, and WSL.
What makes Hermes different:
- Self-improving through skills โ Hermes learns from experience by saving reusable procedures as skills. When it solves a complex problem, discovers a workflow, or gets corrected, it can persist that knowledge as a skill document that loads into future sessions. Skills accumulate over time, making the agent better at your specific tasks and environment.
- Persistent memory across sessions โ remembers who you are, your preferences, environment details, and lessons learned. Pluggable memory backends (built-in, Honcho, Mem0, and more) let you choose how memory works.
- Multi-platform gateway โ the same agent runs on Telegram, Discord, Slack, WhatsApp, Signal, Matrix, Email, and 10+ other platforms with full tool access, not just chat.
- Provider-agnostic โ swap models and providers mid-workflow without changing anything else. Credential pools rotate across multiple API keys automatically.
- Profiles โ run multiple independent Hermes instances with isolated configs, sessions, skills, and memory.
- Extensible โ plugins, MCP servers, custom tools, webhook triggers, cron scheduling, and the full Python ecosystem.
People use Hermes for software development, research, system administration, data analysis, content creation, home automation, and anything else that benefits from an AI agent with persistent context and full system access.
This skill helps you work with Hermes Agent effectively โ setting it up, configuring features, spawning additional agent instances, troubleshooting issues, finding the right commands and settings, and understanding how the system works when you need to extend or contribute to it.
Docs: https://hermes-agent.nousresearch.com/docs/
Quick Start
Install
curl -fsSL https://raw.githubusercontent.com/NousResearch/hermes-agent/main/scripts/install.sh | bash
Interactive chat (default)
hermes
Single query
hermes chat -q "What is the capital of France?"
Setup wizard
hermes setup
Change model/provider
hermes model
Check health
hermes doctor
---
CLI Reference
Global Flags
hermes [flags] [command]
--version, -V Show version
--resume, -r SESSION Resume session by ID or title
--continue, -c [NAME] Resume by name, or most recent session
--worktree, -w Isolated git worktree mode (parallel agents)
--skills, -s SKILL Preload skills (comma-separate or repeat)
--profile, -p NAME Use a named profile
--yolo Skip dangerous command approval
--pass-session-id Include session ID in system prompt
No subcommand defaults to chat.
Chat
hermes chat [flags]
-q, --query TEXT Single query, non-interactive
-m, --model MODEL Model (e.g. anthropic/claude-sonnet-4)
-t, --toolsets LIST Comma-separated toolsets
--provider PROVIDER Force provider (openrouter, anthropic, nous, etc.)
-v, --verbose Verbose output
-Q, --quiet Suppress banner, spinner, tool previews
--checkpoints Enable filesystem checkpoints (/rollback)
--source TAG Session source tag (default: cli)
Configuration
hermes setup [section] Interactive wizard (model|terminal|gateway|tools|agent)
hermes model Interactive model/provider picker
hermes config View current config
hermes config edit Open config.yaml in $EDITOR
hermes config set KEY VAL Set a config value
hermes config path Print config.yaml path
hermes config env-path Print .env path
hermes config check Check for missing/outdated config
hermes config migrate Update config with new options
hermes doctor [--fix] Check dependencies and config
Credential Pools
hermes auth add Interactive credential wizard (oauth, api-key)
hermes auth list [PROVIDER] List pooled credentials
hermes auth remove P INDEX Remove by provider + index
hermes auth reset PROVIDER Clear exhaustion status
hermes logout Clear stored auth
Tools & Skills
hermes tools Interactive tool enable/disable (curses UI)
hermes tools list Show all tools and status
hermes tools enable NAME Enable a toolset
hermes tools disable NAME Disable a toolset
hermes skills list List installed skills
hermes skills search QUERY Search the skills hub
hermes skills install ID Install a skill (ID can be a hub identifier OR a direct https://โฆ/SKILL.md URL; pass --name to override when frontmatter has no name)
hermes skills inspect ID Preview without installing
hermes skills config Enable/disable skills per platform
hermes skills check Check for updates
hermes skills update Update outdated skills
hermes skills uninstall N Remove a hub skill
hermes skills publish PATH Publish to registry
hermes skills browse Browse all available skills
hermes skills tap add REPO Add a GitHub repo as skill source
MCP Servers
hermes mcp serve Run Hermes as an MCP server
hermes mcp add NAME Add an MCP server (--url or --command)
hermes mcp remove NAME Remove an MCP server
hermes mcp list List configured servers
hermes mcp test NAME Test connection
hermes mcp configure NAME Toggle tool selection
Gateway (Messaging Platforms)
hermes gateway run Start gateway foreground
hermes gateway install Install as background service
hermes gateway start/stop Control the service
hermes gateway restart Restart the service
hermes gateway status Check status
hermes gateway setup Configure platforms
Supported platforms: Telegram, Discord, Slack, WhatsApp, Signal, Email, SMS, Matrix, Mattermost, Home Assistant, DingTalk, Feishu, WeCom, BlueBubbles (iMessage), Weixin (WeChat), API Server, Webhooks. Open WebUI connects via the API Server adapter.
Platform docs: https://hermes-agent.nousresearch.com/docs/user-guide/messaging/
Discord-specific walkthrough (token, intents, service install, access control): see references/discord-gateway-setup.md in this skill.
- Per-channel personas and skill bindings: see
references/gateway-channel-personas.md (works on Discord, Slack, Telegram, Mattermost, Matrix).
- For long-running Discord-first operations, purpose-specific channel routing, periodic summaries, weekly Dreaming/audit reports, and log-safety patterns: see
references/discord-operating-planes.md.
- For broad Hermes/LifeOS/SQAF ecosystem audits (cron inventory, live services, dashboards, provider/model warnings, and control-plane gaps), see
references/ecosystem-audit.md.
Sessions
hermes sessions list List recent sessions
hermes sessions browse Interactive picker
hermes sessions export OUT Export to JSONL
hermes sessions rename ID T Rename a session
hermes sessions delete ID Delete a session
hermes sessions prune Clean up old sessions (--older-than N days)
hermes sessions stats Session store statistics
For browser-based viewing of existing Hermes CLI/Discord/cron session transcripts, prefer a lightweight static export from ~/.hermes/state.db into a private web root instead of assuming Open WebUI can browse Hermes' native session store. See references/hermes-session-static-web-viewer.md for the SQLite schema, static HTML export workflow, redaction/truncation cautions, and the user's Mac mini deployment (/hermes-sessions/ under the Tailscale-only ~/hermes-web site).
For cron job execution history, the same static-export pattern applies to ~/.hermes/cron/jobs.json and ~/.hermes/cron/output/{job_id}/*.md. See references/cron-history-web-viewer.md for the cron data model, schedule-dict pitfall, and the user's deployed /cron-history/ dashboard.
Cron Jobs
hermes cron list List jobs (--all for disabled)
hermes cron create SCHED Create: '30m', 'every 2h', '0 9 *'
hermes cron edit ID Edit schedule, prompt, delivery
hermes cron pause/resume ID Control job state
hermes cron run ID Trigger on next tick
hermes cron remove ID Delete a job
hermes cron status Scheduler status
For bounded autonomous lab/orchestrator cron jobs that use file-based state, subagent lanes, artifact publishing, and status transitions (active โ complete/blocked/inactive), see references/autonomous-agent-lab-cron-cycle.md. A reusable verification script template lives at scripts/verify-completion-template.py.
For a worked example of evolving an autonomous lab into a config-driven, themeable, Docker-ready installable product, see references/autonomous-lab-product-architecture.md. For CI, integration testing, pluggable adapter architecture, bounded cycle orchestration, and post-productization patterns, see references/product-maturity-patterns.md.
For the final completion verification checklist โ the explicit audit pattern to run before marking status: complete on an installable-solution mission, see references/autonomous-lab-completion-verification.md.
For the reactivation protocol when a completed lab receives new P0 feedback or the user contradicts a completion claim, see references/autonomous-lab-reactivation-protocol.md.
For the config/CHANGELOG version drift pitfall that occurs when autonomous labs evolve over many cycles, and for the related source vs. published file drift problem where the live web root diverges from the project source, see references/autonomous-lab-version-drift.md.
For adding historical trend tracking (SQLite-backed agent status transitions + vanilla JS SVG sparklines) to an autonomous lab dashboard, see references/history-tracking-sparkline-pattern.md.
For preventing unbounded SQLite growth in long-running labs, see references/autonomous-lab-data-retention.md โ covers automatic per-refresh pruning and a standalone manual prune utility.
- For reusable dashboard UX patterns (onboarding tours, data freshness badges, keyboard shortcuts, progressive disclosure inspectors, cross-linking between views, inspector deep-linking), see
references/dashboard-ux-patterns.md.
For the daily operational briefing modal โ a one-screen human-first summary of agent counts, blocked work, recent events, health status, and upcoming cron schedules โ see references/daily-briefing-modal.md.
For the aggressive human-first inspector refinement โ when users report that details are hard to understand and the fix is to strip technical labels from the default view โ see references/progressive-disclosure-human-first.md.
For programmatic verification of CSS custom-property theme systems โ catching scoping bugs, confirming theme distinctness, and validating JS switching logic โ see references/theme-system-verification.md.
- For Son's Discord-first autonomous experiments where a channel hosts a repeated multi-agent loop, use the Autonomous Discord Agent Lab pattern: create file-based durable state, a paused cron orchestrator delivered to
discord:<channel_id>, then activate it from a user mission trigger. See references/autonomous-discord-agent-lab.md.
- For verifying that a release package (
tar.gz) is actually installable by third parties and contains no stale artifacts or hardcoded references, see references/release-package-verification.md and the reusable script at scripts/release-verify.sh.
Webhooks
hermes webhook subscribe N Create route at /webhooks/<name>
hermes webhook list List subscriptions
hermes webhook remove NAME Remove a subscription
hermes webhook test NAME Send a test POST
Profiles
hermes profile list List all profiles
hermes profile create NAME Create (--clone, --clone-all, --clone-from)
hermes profile use NAME Set sticky default
hermes profile delete NAME Delete a profile
hermes profile show NAME Show details
hermes profile alias NAME Manage wrapper scripts
hermes profile rename A B Rename a profile
hermes profile export NAME Export to tar.gz
hermes profile import FILE Import from archive
Credential Pools
hermes auth add Interactive credential wizard
hermes auth list [PROVIDER] List pooled credentials
hermes auth remove P INDEX Remove by provider + index
hermes auth reset PROVIDER Clear exhaustion status
Other
hermes insights [--days N] Usage analytics
hermes update Update to latest version
hermes pairing list/approve/revoke DM authorization
hermes plugins list/install/remove Plugin management
hermes honcho setup/status Honcho memory integration (requires honcho plugin)
hermes memory setup/status/off Memory provider config
hermes completion bash|zsh Shell completions
hermes acp ACP server (IDE integration)
hermes claw migrate Migrate from OpenClaw
hermes uninstall Uninstall Hermes
---
Slash Commands (In-Session)
Type these during an interactive chat session. New commands land fairly
often; if something below looks stale, run /help in-session for the
authoritative list or see the [live slash commands reference](https://hermes-agent.nousresearch.com/docs/reference/slash-commands).
The registry of record is hermes_cli/commands.py โ every consumer
(autocomplete, Telegram menu, Slack mapping, /help) derives from it.
Session Control
/new (/reset) Fresh session
/clear Clear screen + new session (CLI)
/retry Resend last message
/undo Remove last exchange
/title [name] Name the session
/compress Manually compress context
/stop Kill background processes
/rollback [N] Restore filesystem checkpoint
/snapshot [sub] Create or restore state snapshots of Hermes config/state (CLI)
/background <prompt> Run prompt in background
/queue <prompt> Queue for next turn
/steer <prompt> Inject a message after the next tool call without interrupting
/agents (/tasks) Show active agents and running tasks
/resume [name] Resume a named session
/goal [text|sub] Set a standing goal Hermes works on across turns until achieved
(subcommands: status, pause, resume, clear)
/redraw Force a full UI repaint (CLI)
Configuration
/config Show config (CLI)
/model [name] Show or change model
/personality [name] Set personality
/reasoning [level] Set reasoning (none|minimal|low|medium|high|xhigh|show|hide)
/verbose Cycle: off โ new โ all โ verbose
/voice [on|off|tts] Voice mode
/yolo Toggle approval bypass
/busy [sub] Control what Enter does while Hermes is working (CLI)
(subcommands: queue, steer, interrupt, status)
/indicator [style] Pick the TUI busy-indicator style (CLI)
(styles: kaomoji, emoji, unicode, ascii)
/footer [on|off] Toggle gateway runtime-metadata footer on final replies
/skin [name] Change theme (CLI)
/statusbar Toggle status bar (CLI)
Tools & Skills
/tools Manage tools (CLI)
/toolsets List toolsets (CLI)
/skills Search/install skills (CLI)
/skill <name> Load a skill into session
/reload-skills Re-scan ~/.hermes/skills/ for added/removed skills
/reload Reload .env variables into the running session (CLI)
/reload-mcp Reload MCP servers
/cron Manage cron jobs (CLI)
/curator [sub] Background skill maintenance (status, run, pin, archive, โฆ)
/kanban [sub] Multi-profile collaboration board (tasks, links, comments)
/plugins List plugins (CLI)
Gateway
/approve Approve a pending command (gateway)
/deny Deny a pending command (gateway)
/restart Restart gateway (gateway)
/sethome Set current chat as home channel (gateway)
/update Update Hermes to latest (gateway)
/topic [sub] Enable or inspect Telegram DM topic sessions (gateway)
/platforms (/gateway) Show platform connection status (gateway)
Utility
/branch (/fork) Branch the current session
/fast Toggle priority/fast processing
/browser Open CDP browser connection
/history Show conversation history (CLI)
/save Save conversation to file (CLI)
/copy [N] Copy the last assistant response to clipboard (CLI)
/paste Attach clipboard image (CLI)
/image Attach local image file (CLI)
Info
/help Show commands
/commands [page] Browse all commands (gateway)
/usage Token usage
/insights [days] Usage analytics
/gquota Show Google Gemini Code Assist quota usage (CLI)
/status Session info (gateway)
/profile Active profile info
/debug Upload debug report (system info + logs) and get shareable links
Exit
/quit (/exit, /q) Exit CLI
---
Key Paths & Config
~/.hermes/config.yaml Main configuration
~/.hermes/.env API keys and secrets
$HERMES_HOME/skills/ Installed skills
~/.hermes/sessions/ Session transcripts
~/.hermes/logs/ Gateway and error logs
~/.hermes/auth.json OAuth tokens and credential pools
~/.hermes/hermes-agent/ Source code (if git-installed)
Profiles use ~/.hermes/profiles/<name>/ with the same layout.
Config Sections
Edit with hermes config edit or hermes config set section.key value.
| Section | Key options |
|---------|-------------|
| model | default, provider, base_url, api_key, context_length |
| agent | max_turns (90), tool_use_enforcement |
| terminal | backend (local/docker/ssh/modal), cwd, timeout (180) |
| compression | enabled, threshold (0.50), target_ratio (0.20) |
| display | skin, tool_progress, show_reasoning, show_cost |
| stt | enabled, provider (local/groq/openai/mistral) |
| tts | provider (edge/elevenlabs/openai/minimax/mistral/neutts) |
| memory | memory_enabled, user_profile_enabled, provider |
| security | tirith_enabled, website_blocklist |
| delegation | model, provider, base_url, api_key, max_iterations (50), reasoning_effort |
| checkpoints | enabled, max_snapshots (50) |
| fallback_model | provider, model, base_url, key_env |
Fallback Providers
Hermes can automatically fail over to a backup provider:model when the primary is unavailable. This is turn-scoped โ each new user message starts with the primary restored; fallback only activates mid-turn when the primary fails.
Configuration ( ~/.hermes/config.yaml):
fallback_model:
provider: opencode-go
model: kimi-k2.6
Or use the interactive manager:
hermes fallback add # interactive picker
hermes fallback list # show fallback chain
hermes fallback remove # remove by index
Legacy note: fallback_model (singular) is the legacy single-fallback key. fallback_providers (list) supports multiple ordered fallbacks. When both exist, fallback_providers takes priority.
Trigger conditions (after exhausting retries where applicable):
- Rate limits (HTTP 429)
- Server errors (HTTP 500, 502, 503)
- Auth failures (HTTP 401, 403) โ immediately
- Not found (HTTP 404) โ immediately
- Invalid / empty responses repeatedly
Supported providers include all standard providers (OpenRouter, Anthropic, OpenCode Go/ Zen, Kimi, etc.) plus custom endpoints with base_url + key_env. Full provider docs: https://hermes-agent.nousresearch.com/docs/integrations/providers
Limitations:
- Subagent delegation does not inherit fallback config
- Cron jobs do not use fallback (use per-job provider/model overrides)
- Auxiliary tasks (vision, compression, etc.) use their own
auxiliary.* provider chain
For a deep-dive with worked examples and model lists, see references/fallback-providers.md.
Full config reference: https://hermes-agent.nousresearch.com/docs/user-guide/configuration
Providers
20+ providers supported. Set via hermes model or hermes setup.
| Provider | Auth | Key env var |
|----------|------|-------------|
| OpenRouter | API key | OPENROUTER_API_KEY |
| Anthropic | API key | ANTHROPIC_API_KEY |
| Nous Portal | OAuth | hermes auth |
| OpenAI Codex | OAuth | hermes auth |
| GitHub Copilot | Token | COPILOT_GITHUB_TOKEN |
| Google Gemini | API key | GOOGLE_API_KEY or GEMINI_API_KEY |
| DeepSeek | API key | DEEPSEEK_API_KEY |
| xAI / Grok | API key | XAI_API_KEY |
| Hugging Face | Token | HF_TOKEN |
| Z.AI / GLM | API key | GLM_API_KEY |
| MiniMax | API key | MINIMAX_API_KEY |
| MiniMax CN | API key | MINIMAX_CN_API_KEY |
| Kimi / Moonshot | API key | KIMI_API_KEY |
| Alibaba / DashScope | API key | DASHSCOPE_API_KEY |
| Xiaomi MiMo | API key | XIAOMI_API_KEY |
| Kilo Code | API key | KILOCODE_API_KEY |
| AI Gateway (Vercel) | API key | AI_GATEWAY_API_KEY |
| OpenCode Zen | API key | OPENCODE_ZEN_API_KEY |
| OpenCode Go | API key | OPENCODE_GO_API_KEY |
| Qwen OAuth | OAuth | hermes auth add qwen-oauth |
| Custom endpoint | Config | model.base_url + model.api_key in config.yaml |
| GitHub Copilot ACP | External | COPILOT_CLI_PATH or Copilot CLI |
Full provider docs: https://hermes-agent.nousresearch.com/docs/integrations/providers
Toolsets
Enable/disable via hermes tools (interactive) or hermes tools enable/disable NAME.
| Toolset | What it provides |
|---------|-----------------|
| web | Web search and content extraction |
| search | Web search only (subset of web) |
| browser | Browser automation (Browserbase, Camofox, or local Chromium) |
| terminal | Shell commands and process management |
| file | File read/write/search/patch |
| code_execution | Sandboxed Python execution |
| vision | Image analysis |
| image_gen | AI image generation |
| video | Video analysis and generation |
| tts | Text-to-speech |
| skills | Skill browsing and management |
| memory | Persistent cross-session memory |
| session_search | Search past conversations |
| delegation | Subagent task delegation |
| cronjob | Scheduled task management |
| clarify | Ask user clarifying questions |
| messaging | Cross-platform message sending |
| todo | In-session task planning and tracking |
| kanban | Multi-agent work-queue tools (gated to workers) |
| debugging | Extra introspection/debug tools (off by default) |
| safe | Minimal, low-risk toolset for locked-down sessions |
| spotify | Spotify playback and playlist control |
| homeassistant | Smart home control (off by default) |
| discord | Discord integration tools |
| discord_admin | Discord admin/moderation tools |
| feishu_doc | Feishu (Lark) document tools |
| feishu_drive | Feishu (Lark) drive tools |
| yuanbao | Yuanbao integration tools |
| rl | Reinforcement learning tools (off by default) |
| moa | Mixture of Agents (off by default) |
Full enumeration lives in toolsets.py as the TOOLSETS dict; _HERMES_CORE_TOOLS is the default bundle most platforms inherit from.
Tool changes take effect on /reset (new session). They do NOT apply mid-conversation to preserve prompt caching.
---
Security & Privacy Toggles
Common "why is Hermes doing X to my output / tool calls / commands?" toggles โ and the exact commands to change them. Most of these need a fresh session (/reset in chat, or start a new hermes invocation) because they're read once at startup.
Secret redaction in tool output
Secret redaction is off by default โ tool output (terminal stdout, read_file, web content, subagent summaries, etc.) passes through unmodified. If the user wants Hermes to auto-mask strings that look like API keys, tokens, and secrets before they enter the conversation context and logs:
hermes config set security.redact_secrets true # enable globally
Restart required. security.redact_secrets is snapshotted at import time โ toggling it mid-session (e.g. via export HERMES_REDACT_SECRETS=true from a tool call) will NOT take effect for the running process. Tell the user to run hermes config set security.redact_secrets true in a terminal, then start a new session. This is deliberate โ it prevents an LLM from flipping the toggle on itself mid-task.
Disable again with:
hermes config set security.redact_secrets false
PII redaction in gateway messages
Separate from secret redaction. When enabled, the gateway hashes user IDs and strips phone numbers from the session context before it reaches the model:
hermes config set privacy.redact_pii true # enable
hermes config set privacy.redact_pii false # disable (default)
Command approval prompts
By default (approvals.mode: manual), Hermes prompts the user before running shell commands flagged as destructive (rm -rf, git reset --hard, etc.). The modes are:
manual โ always prompt (default)
smart โ use an auxiliary LLM to auto-approve low-risk commands, prompt on high-risk
off โ skip all approval prompts (equivalent to --yolo)
hermes config set approvals.mode smart # recommended middle ground
hermes config set approvals.mode off # bypass everything (not recommended)
Per-invocation bypass without changing config:
hermes --yolo โฆ
export HERMES_YOLO_MODE=1
Note: YOLO / approvals.mode: off does NOT turn off secret redaction. They are independent.
Shell hooks allowlist
Some shell-hook integrations require explicit allowlisting before they fire. Managed via ~/.hermes/shell-hooks-allowlist.json โ prompted interactively the first time a hook wants to run.
Disabling the web/browser/image-gen tools
To keep the model away from network or media tools entirely, open hermes tools and toggle per-platform. Takes effect on next session (/reset). See the Tools & Skills section above.
---
Voice & Transcription
STT (Voice โ Text)
Voice messages from messaging platforms are auto-transcribed.
Provider priority (auto-detected):
1. Local faster-whisper โ free, no API key: pip install faster-whisper
2. Groq Whisper โ free tier: set GROQ_API_KEY
3. OpenAI Whisper โ paid: set VOICE_TOOLS_OPENAI_KEY
4. Mistral Voxtral โ set MISTRAL_API_KEY
Config:
stt:
enabled: true
provider: local # local, groq, openai, mistral
local:
model: base # tiny, base, small, medium, large-v3
TTS (Text โ Voice)
| Provider | Env var | Free? |
|----------|---------|-------|
| Edge TTS | None | Yes (default) |
| ElevenLabs | ELEVENLABS_API_KEY | Free tier |
| OpenAI | VOICE_TOOLS_OPENAI_KEY | Paid |
| MiniMax | MINIMAX_API_KEY | Paid |
| Mistral (Voxtral) | MISTRAL_API_KEY | Paid |
| NeuTTS (local) | None (pip install neutts[all] + espeak-ng) | Free |
Voice commands: /voice on (voice-to-voice), /voice tts (always voice), /voice off.
---
Spawning Additional Hermes Instances
Run additional Hermes processes as fully independent subprocesses โ separate sessions, tools, and environments.
When to Use This vs delegate_task
| | delegate_task | Spawning hermes process |
|-|-----------------|--------------------------|
| Isolation | Separate conversation, shared process | Fully independent process |
| Duration | Minutes (bounded by parent loop) | Hours/days |
| Tool access | Subset of parent's tools | Full tool access |
| Interactive | No | Yes (PTY mode) |
| Use case | Quick parallel subtasks | Long autonomous missions |
One-Shot Mode
terminal(command="hermes chat -q 'Research GRPO papers and write summary to ~/research/grpo.md'", timeout=300)
Background for long tasks:
terminal(command="hermes chat -q 'Set up CI/CD for ~/myapp'", background=true)
Interactive PTY Mode (via tmux)
Hermes uses prompt_toolkit, which requires a real terminal. Use tmux for interactive spawning:
Start
terminal(command="tmux new-session -d -s agent1 -x 120 -y 40 'hermes'", timeout=10)
Wait for startup, then send a message
terminal(command="sleep 8 && tmux send-keys -t agent1 'Build a FastAPI auth service' Enter", timeout=15)
Read output
terminal(command="sleep 20 && tmux capture-pane -t agent1 -p", timeout=5)
Send follow-up
terminal(command="tmux send-keys -t agent1 'Add rate limiting middleware' Enter", timeout=5)
Exit
terminal(command="tmux send-keys -t agent1 '/exit' Enter && sleep 2 && tmux kill-session -t agent1", timeout=10)
Multi-Agent Coordination
Agent A: backend
terminal(command="tmux new-session -d -s backend -x 120 -y 40 'hermes -w'", timeout=10)
terminal(command="sleep 8 && tmux send-keys -t backend 'Build REST API for user management' Enter", timeout=15)
Agent B: frontend
terminal(command="tmux new-session -d -s frontend -x 120 -y 40 'hermes -w'", timeout=10)
terminal(command="sleep 8 && tmux send-keys -t frontend 'Build React dashboard for user management' Enter", timeout=15)
Check progress, relay context between them
terminal(command="tmux capture-pane -t backend -p | tail -30", timeout=5)
terminal(command="tmux send-keys -t frontend 'Here is the API schema from the backend agent: ...' Enter", timeout=5)
Session Resume
Resume most recent session
terminal(command="tmux new-session -d -s resumed 'hermes --continue'", timeout=10)
Resume specific session
terminal(command="tmux new-session -d -s resumed 'hermes --resume 20260225_143052_a1b2c3'", timeout=10)
Tips
- Prefer
delegate_task for quick subtasks โ less overhead than spawning a full process
- Use
-w (worktree mode) when spawning agents that edit code โ prevents git conflicts
- Set timeouts for one-shot mode โ complex tasks can take 5-10 minutes
- Use
hermes chat -q for fire-and-forget โ no PTY needed
- Use tmux for interactive sessions โ raw PTY mode has
\r vs \n issues with prompt_toolkit
- For scheduled tasks, use the
cronjob tool instead of spawning โ handles delivery and retry
---
Durable & Background Systems
Four systems run alongside the main conversation loop. Quick reference
here; full developer notes live in AGENTS.md, user-facing docs under
website/docs/user-guide/features/.
Delegation (delegate_task)
Synchronous subagent spawn โ the parent waits for the child's summary
before continuing its own loop. Isolated context + terminal session.
- Single:
delegate_task(goal, context, toolsets).
- Batch:
delegate_task(tasks=[{goal, ...}, ...]) runs children in
parallel, capped by delegation.max_concurrent_children (default 3).
- Roles:
leaf (default; cannot re-delegate) vs orchestrator
(can spawn its own workers, bounded by delegation.max_spawn_depth).
- Not durable. If the parent is interrupted, the child is
cancelled. For work that must outlive the turn, use cronjob or
terminal(background=True, notify_on_complete=True).
Config: delegation.* in config.yaml.
Tuning max_concurrent_children
Default is 3. Rule of thumb for raising it:
- Light tasks (web search, file grep): up to
6-8
- Medium tasks (code execution, browser):
4-5
- Heavy tasks (builds, large data):
2-3
- Actual bottleneck is usually the API rate limit, not local CPU/RAM. On a 10-core M4 with 16GB RAM, CPU is rarely the constraint.
- Formula: start at
5, raise only if profiling shows idle time between API responses.
Cron (scheduled jobs)
Durable scheduler โ cron/jobs.py + cron/scheduler.py. Drive it via
the cronjob tool, the hermes cron CLI (list, add, edit,
pause, resume, run, remove), or the /cron slash command.
- Schedules: duration (
"30m", "2h"), "every" phrase
( "every monday 9am"), 5-field cron ( "0 9 *"), or ISO timestamp.
- Per-job knobs:
skills, model/provider override, script
(pre-run data collection; no_agent=True makes the script the whole
job), context_from (chain job A's output into job B), workdir
(run in a specific dir with its AGENTS.md / CLAUDE.md loaded),
multi-platform delivery.
- Invariants: 3-minute hard interrupt per run,
.tick.lock file
prevents duplicate ticks across processes, cron sessions pass
skip_memory=True by default, and cron deliveries are framed with a
header/footer instead of being mirrored into the target gateway
session (keeps role alternation intact).
User docs: https://hermes-agent.nousresearch.com/docs/user-guide/features/cron
Curator (skill lifecycle)
Background maintenance for agent-created skills. Tracks usage, marks
idle skills stale, archives stale ones, keeps a pre-run tar.gz backup
so nothing is lost.
- CLI:
hermes curator <verb> โ status, run, pause, resume,
pin, unpin, archive, restore, prune, backup, rollback.
- Slash:
/curator <subcommand> mirrors the CLI.
- Scope: only touches skills with
created_by: "agent" provenance.
Bundled + hub-installed skills are off-limits. Never deletes โ
max destructive action is archive. Pinned skills are exempt from
every auto-transition and every LLM review pass.
- Telemetry: sidecar at
~/.hermes/skills/.usage.json holds
per-skill use_count, view_count, patch_count,
last_activity_at, state, pinned.
Config: curator.* (enabled, interval_hours, min_idle_hours,
stale_after_days, archive_after_days, backup.*).
User docs: https://hermes-agent.nousresearch.com/docs/user-guide/features/curator
Dreaming (periodic memory/skill consolidation)
For Anthropic-style "dreaming" workflows, combine cron + session_search + memory + skills + curator into a scheduled review loop. Start with a weekly, proposal-only report that audits recent sessions, repeated user corrections, memory conflicts, skill patch candidates, and cron/automation improvements. Do not automatically delete/replace memory or patch/archive skills unless the user explicitly approves the proposed changes. See references/weekly-dreaming-routine.md for the recommended prompt, report format, safety policy, and cron creation pattern.
Kanban (multi-agent work queue)
Durable SQLite board for multi-profile / multi-worker collaboration.
Users drive it via hermes kanban <verb>; dispatcher-spawned workers
see a focused kanban_* toolset gated by HERMES_KANBAN_TASK so the
schema footprint is zero outside worker processes.
- CLI verbs (common):
init, create, list (alias ls),
show, assign, link, unlink, comment, complete, block,
unblock, archive, tail. Less common: watch, stats, runs,
log, dispatch, daemon, gc.
- Worker toolset:
kanban_show, kanban_complete, kanban_block,
kanban_heartbeat, kanban_comment, kanban_create, kanban_link.
- Dispatcher runs inside the gateway by default
( kanban.dispatch_in_gateway: true) โ reclaims stale claims,
promotes ready tasks, atomically claims, spawns assigned profiles.
Auto-blocks a task after ~5 consecutive spawn failures.
- Isolation: board is the hard boundary (workers get
HERMES_KANBAN_BOARD pinned in env); tenant is a soft namespace
within a board for workspace-path + memory-key isolation.
User docs: https://hermes-agent.nousresearch.com/docs/user-guide/features/kanban
Log Relay (Hermes โ Discord)
A background Python script that tails ~/.hermes/logs/*.log and batches lines to a Discord channel. Includes session-ID extraction, rate-limit handling, and auto-restart via launchd/systemd. Useful for remote monitoring and audit trails.
- Reference:
references/discord-log-relay.md โ full setup, tuning, macOS/Linux service install, pitfalls.
- Template:
templates/discord-log-relay.py โ copy, set CHANNEL_ID, and deploy.
- Discord operations:
references/discord-operating-planes.md โ channel-purpose routing, periodic-summary vs Dreaming report formats, and safety/cost notes for Discord-first Hermes deployments.
Key pitfall: ask the user about batch frequency upfront rather than defaulting to real-time streaming. Most users prefer 10-minute or hourly batches. High-volume raw logs should be batched, summarized, or stored out-of-band; avoid Discord message storms during error loops.
Weekly Dreaming / Memory Curation
For long-running Hermes deployments, users may want an Anthropic-style "Dreaming" loop: a scheduled review that consolidates experience, proposes memory/skill/cron changes, and identifies what to keep, weaken, archive, or delete. Hermes has the building blocks (sessions, session_search, memory, skills, curator, cron), but the safe default is proposal mode:
1. Inspect recent usage and sessions.
2. Extract repeated success patterns, failure patterns, and user corrections.
3. Propose memory updates/removals without applying them silently.
4. Propose skill patches/archive candidates and cron/reporting improvements.
5. End with explicit approval checkboxes.
Do not silently rewrite or delete memory/skills from a Dreaming report unless the user explicitly authorized automatic application. See references/discord-operating-planes.md for a report template and routing heuristics.
---
Windows-Specific Quirks
Hermes runs natively on Windows (PowerShell, cmd, Windows Terminal, git-bash
mintty, VS Code integrated terminal). Most of it just works, but a handful
of differences between Win32 and POSIX have bitten us โ document new ones
here as you hit them so the next person (or the next session) doesn't
rediscover them from scratch.
Input / Keybindings
Alt+Enter doesn't insert a newline. Windows Terminal intercepts Alt+Enter
at the terminal layer to toggle fullscreen โ the keystroke never reaches
prompt_toolkit. Use Ctrl+Enter instead. Windows Terminal delivers
Ctrl+Enter as LF ( c-j), distinct from plain Enter ( c-m / CR), and the
CLI binds c-j to newline insertion on win32 only (see
_bind_prompt_submit_keys + the Windows-only c-j binding in cli.py).
Side effect: the raw Ctrl+J keystroke also inserts a newline on Windows โ
unavoidable, because Windows Terminal collapses Ctrl+Enter and Ctrl+J to
the same keycode at the Win32 console API layer. No conflicting binding
existed for Ctrl+J on Windows, so this is a harmless side effect.
mintty / git-bash behaves the same (fullscreen on Alt+Enter) unless you
disable Alt+Fn shortcuts in Options โ Keys. Easier to just use Ctrl+Enter.
Diagnosing keybindings. Run python scripts/keystroke_diagnostic.py
(repo root) to see exactly how prompt_toolkit identifies each keystroke
in the current terminal. Answers questions like "does Shift+Enter come
through as a distinct key?" (almost never โ most terminals collapse it
to plain Enter) or "what byte sequence is my terminal sending for
Ctrl+Enter?" This is how the Ctrl+Enter = c-j fact was established.
Config / Files
HTTP 400 "No models provided" on first run. config.yaml was saved
with a UTF-8 BOM (common when Windows apps write it). Re-save as UTF-8
without BOM. hermes config edit writes without BOM; manual edits in
Notepad are the usual culprit.
execute_code / Sandbox
WinError 10106 ("The requested service provider could not be loaded
or initialized") from the sandbox child process โ it can't create an
AF_INET socket, so the loopback-TCP RPC fallback fails before
connect(). Root cause is usually not a broken Winsock LSP; it's
Hermes's own env scrubber dropping SYSTEMROOT / WINDIR / COMSPEC
from the child env. Python's socket module needs SYSTEMROOT to locate
mswsock.dll. Fixed via the _WINDOWS_ESSENTIAL_ENV_VARS allowlist in
tools/code_execution_tool.py. If you still hit it, echo os.environ
inside an execute_code block to confirm SYSTEMROOT is set. Full
diagnostic recipe in references/execute-code-sandbox-env-windows.md.
Testing / Contributing
scripts/run_tests.sh doesn't work as-is on Windows โ it looks for
POSIX venv layouts ( .venv/bin/activate). The Hermes-installed venv at
venv/Scripts/ has no pip or pytest either (stripped for install size).
Workaround: install pytest + pytest-xdist + pyyaml into a system Python
3.11 user site, then invoke pytest directly with PYTHONPATH set:
"/c/Program Files/Python311/python" -m pip install --user pytest pytest-xdist pyyaml
export PYTHONPATH="$(pwd)"
"/c/Program Files/Python311/python" -m pytest tests/foo/test_bar.py -v --tb=short -n 0
Use -n 0, not -n 4 โ pyproject.toml's default addopts already
includes -n, and the wrapper's CI-parity guarantees don't apply off POSIX.
POSIX-only tests need skip guards. Common markers already in the codebase:
- Symlinks โ elevated privileges on Windows
0o600 file modes โ POSIX mode bits not enforced on NTFS by default
signal.SIGALRM โ Unix-only (see tests/conftest.py::_enforce_test_timeout)
- Winsock / Windows-specific regressions โ
@pytest.mark.skipif(sys.platform != "win32", ...)
Use the existing skip-pattern style (sys.platform == "win32" or
sys.platform.startswith("win")) to stay consistent with the rest of the
suite.
Path / Filesystem
Line endings. Git may warn LF will be replaced by CRLF the next time
Git touches it. Cosmetic โ the repo's .gitattributes normalizes. Don't
let editors auto-convert committed POSIX-newline files to CRLF.
Forward slashes work almost everywhere. C:/Users/... is accepted by
every Hermes tool and most Windows APIs. Prefer forward slashes in code
and logs โ avoids shell-escaping backslashes in bash.
---
Troubleshooting
Voice not working
1. Check stt.enabled: true in config.yaml
2. Verify provider: pip install faster-whisper or set API key
3. In gateway: /restart. In CLI: exit and relaunch.
Tool not available
1. hermes tools โ check if toolset is enabled for your platform
2. Some tools need env vars (check .env)
3. /reset after enabling tools
Model/provider issues
1. hermes doctor โ check config and dependencies
2. hermes auth add <provider> โ re-authenticate OAuth providers (use --type oauth)
3. Check .env has the right API key
4. Copilot 403: gh auth login tokens do NOT work for Copilot API. You must use the Copilot-specific OAuth device code flow via hermes model โ GitHub Copilot.
Changes not taking effect
- Tools/skills:
/reset starts a new session with updated toolset
- Config changes: In gateway:
/restart. In CLI: exit and relaunch.
- Code changes: Restart the CLI or gateway process
Deployed web dashboard shows stale CSS or theme changes
- Browser cache: Add
?v=N cache-busting query strings to CSS/JS/theme links in HTML.
- Service Worker cache: Bump
CACHE_NAME in sw.js to invalidate old shell caches.
- Automated bump script: For projects with multiple HTML entry points (dashboard, gather, etc.), use
scripts/bump-build.py to atomically update all build badges, cache-busting query strings, and service worker cache names in one command. See references/autonomous-lab-version-drift.md for usage.
- Data freshness: Use
fetch(url, {cache:'no-store'}) for live JSON feeds.
- Auto-detection: Embed
data-build in <html> and compare server build vs loaded build on page load to show a "new version available" banner. See references/static-site-cache-invalidation.md for the full diagnostic recipe and auto-detection pattern.
- Theme switcher reliability: If theme switching works in Chrome but not Samsung Internet, or feels broken on mobile, see
references/theme-switcher-reliability.md for the create-new-link โ load โ remove-old pattern.
- Emergency recovery: If a bad deploy breaks the main app JS, users need a standalone reset page. See
references/emergency-reset-page.md for a zero-dependency reset.html that clears Service Workers and caches without relying on the main app's JS.
Dashboard inspector feels too technical
- The default inspector view should contain only plain-language sentences: headline, "what they're doing now", "why it matters", and a silent visual progress bar (no text label).
- Move all technical fields (source IDs, confidence scores, progress labels, status slugs, badges) behind a "Show technical details" toggle.
- If users say "details are hard to understand," the fix is to remove more fields from the default view, not to add explanations. Explanations of technical fields are still technical.
- See
references/progressive-disclosure-human-first.md for the aggressive simplification pattern.
Pixel-art characters look wrong on mobile
- Decorative CSS elements (cheeks, ears, tails, badges) can be misread as facial features or appendages when avatars shrink below ~50 px.
- Hide them inside
@media (max-width:480px) so only the essential silhouette remains.
- See
references/pixel-art-mobile-readability.md for the exact selectors and rationale.
Skills not showing
1. hermes skills list โ verify installed
2. hermes skills config โ check platform enablement
3. Load explicitly: /skill name or hermes -s name
Gateway issues
Check logs first:
grep -i "failed to send\|error" ~/.hermes/logs/gateway.log | tail -20
Common gateway problems:
- Gateway dies on SSH logout: Enable linger:
sudo loginctl enable-linger $USER
- Gateway dies on WSL2 close: WSL2 requires
systemd=true in /etc/wsl.conf for systemd services to work. Without it, gateway falls back to nohup (dies when session closes).
- Gateway crash loop: Reset the failed state:
systemctl --user reset-failed hermes-gateway
- macOS: bot shows offline after idle time: The gateway runs as a user agent (
LimitLoadToSessionType=Aqua), so macOS suspends it when the system sleeps. The platform websocket drops and the bot appears offline until the network returns. Fix: keep the Mac awake (System Settings -> Energy -> Prevent automatic sleeping, or caffeinate -d -i -s -u &). Low Power Mode makes this worse, not better. See references/macos-gateway-sleep-disconnect.md for the full diagnostic recipe.
Platform-specific issues
- Discord bot silent: Must enable Message Content Intent in Bot โ Privileged Gateway Intents. See full Discord setup reference:
references/discord-gateway-setup.md.
- Slack bot only works in DMs: Must subscribe to
message.channels event. Without it, the bot ignores public channels.
- Windows-specific issues (
Alt+Enter newline, WinError 10106, UTF-8 BOM config, test suite, line endings): see the dedicated Windows-Specific Quirks section above.
Auxiliary models not working
If auxiliary tasks (vision, compression, session_search) fail silently, the auto provider can't find a backend. Either set OPENROUTER_API_KEY or GOOGLE_API_KEY, or explicitly configure each auxiliary task's provider:
hermes config set auxiliary.vision.provider <your_provider>
hermes config set auxiliary.vision.model <model_name>
Full system auth provisioning
For a one-shot workflow to maximize available credentials โ installing gh, generating SSH keys, configuring git, enabling all Hermes toolsets, and auditing current auth state โ see references/system-auth-setup.md.
Editing large files with patch
When a file is read with read_file(offset=...) (pagination), the tool warns that the view is partial. If you attempt patch without re-reading the full file first, you will likely hit non-unique match errors or corrupt the file. Fix: always call read_file without offset to load the whole file before patching. The tool explicitly warns: "โฆwas last read with offset/limit pagination (partial view). Re-read the whole file before overwriting it." โ heed this warning. For append-only updates (e.g., adding a cycle log entry to state.md), do not use terminal(command="cat >> file << 'EOF'...EOF") โ the terminal tool on macOS/Linux misinterprets heredoc << as backgrounding and fails. Instead, write a short Python script via write_file and execute it with terminal(command="python3 /tmp/script.py"). See references/terminal-heredoc-workaround.md for the full pattern.
Sibling subagent file overwrites
When multiple subagents are running in parallel (e.g. via delegate_task batch mode or kanban worker lanes), a file may be modified by one subagent while another is about to write to it. If you use write_file or patch on a file that was last read before a sibling subagent modified it, your write may silently truncate or revert the sibling's changes. The tool may show a warning like "this file was modified by sibling subagent X but this agent never read it."
Fix:
1. Heed the warning. If the tool reports a sibling modification, re-read the file with read_file before writing.
2. Prefer patch over write_file for partial updates โ patch only changes the matched region and is less likely to wipe unrelated content.
3. If the file is already published/deployed, and the local working copy gets corrupted, recover from the published copy:
cp ~/hermes-web/agent-pets/css/dashboard.css ~/.hermes/autonomous-agent-lab/pixel-pet-ops/web/css/dashboard.css
4. For append-only updates, write a small Python script and execute it rather than using write_file on the whole file.
Prevention: In kanban/multi-agent workflows, assign file-level ownership so only one worker touches each file. If parallel workers must edit the same file, have them write to separate temp files and let the orchestrator merge.
---
Windows-Specific Quirks
| Looking for... | Location |
|----------------|----------|
| Config options | hermes config edit or [Configuration docs](https://hermes-agent.nousresearch.com/docs/user-guide/configuration) |
| Available tools | hermes tools list or [Tools reference](https://hermes-agent.nousresearch.com/docs/reference/tools-reference) |
| Slash commands | /help in session or [Slash commands reference](https://hermes-agent.nousresearch.com/docs/reference/slash-commands) |
| Skills catalog | hermes skills browse or [Skills catalog](https://hermes-agent.nousresearch.com/docs/reference/skills-catalog) |
| Provider setup | hermes model or [Providers guide](https://hermes-agent.nousresearch.com/docs/integrations/providers) |
| Platform setup | hermes gateway setup or [Messaging docs](https://hermes-agent.nousresearch.com/docs/user-guide/messaging/) |
| MCP servers | hermes mcp list or [MCP guide](https://hermes-agent.nousresearch.com/docs/user-guide/features/mcp) |
| Profiles | hermes profile list or [Profiles docs](https://hermes-agent.nousresearch.com/docs/user-guide/profiles) |
| Cron jobs | hermes cron list or [Cron docs](https://hermes-agent.nousresearch.com/docs/user-guide/features/cron) |
| Memory | hermes memory status or [Memory docs](https://hermes-agent.nousresearch.com/docs/user-guide/features/memory) |
| Env variables | hermes config env-path or [Env vars reference](https://hermes-agent.nousresearch.com/docs/reference/environment-variables) |
| CLI commands | hermes --help or [CLI reference](https://hermes-agent.nousresearch.com/docs/reference/cli-commands) |
| Gateway logs | ~/.hermes/logs/gateway.log |
| Session files | ~/.hermes/sessions/ or hermes sessions browse |
| Source code | ~/.hermes/hermes-agent/ |
---
Contributor Quick Reference
For occasional contributors and PR authors. Full developer docs: https://hermes-agent.nousresearch.com/docs/developer-guide/
Project Layout
hermes-agent/
โโโ run_agent.py # AIAgent โ core conversation loop
โโโ model_tools.py # Tool discovery and dispatch
โโโ toolsets.py # Toolset definitions
โโโ cli.py # Interactive CLI (HermesCLI)
โโโ hermes_state.py # SQLite session store
โโโ agent/ # Prompt builder, context compression, memory, model routing, credential pooling, skill dispatch
โโโ hermes_cli/ # CLI subcommands, config, setup, commands
โ โโโ commands.py # Slash command registry (CommandDef)
โ โโโ config.py # DEFAULT_CONFIG, env var definitions
โ โโโ main.py # CLI entry point and argparse
โโโ tools/ # One file per tool
โ โโโ registry.py # Central tool registry
โโโ gateway/ # Messaging gateway
โ โโโ platforms/ # Platform adapters (telegram, discord, etc.)
โโโ cron/ # Job scheduler
โโโ tests/ # ~3000 pytest tests
โโโ website/ # Docusaurus docs site
Config: ~/.hermes/config.yaml (settings), ~/.hermes/.env (API keys).
Adding a Tool (3 files)
1. Create tools/your_tool.py:
import json, os
from tools.registry import registry
def check_requirements() -> bool:
return bool(os.getenv("EXAMPLE_API_KEY"))
def example_tool(param: str, task_id: str = None) -> str:
return json.dumps({"success": True, "data": "..."})
registry.register(
name="example_tool",
toolset="example",
schema={"name": "example_tool", "description": "...", "parameters": {...}},
handler=lambda args, **kw: example_tool(
param=args.get("param", ""), task_id=kw.get("task_id")),
check_fn=check_requirements,
requires_env=["EXAMPLE_API_KEY"],
)
2. Add to toolsets.py โ _HERMES_CORE_TOOLS list.
Auto-discovery: any tools/*.py file with a top-level registry.register() call is imported automatically โ no manual list needed.
All handlers must return JSON strings. Use get_hermes_home() for paths, never hardcode ~/.hermes.
Adding a Slash Command
1. Add CommandDef to COMMAND_REGISTRY in hermes_cli/commands.py
2. Add handler in cli.py โ process_command()
3. (Optional) Add gateway handler in gateway/run.py
All consumers (help text, autocomplete, Telegram menu, Slack mapping) derive from the central registry automatically.
Agent Loop (High Level)
run_conversation():
1. Build system prompt
2. Loop while iterations < max:
a. Call LLM (OpenAI-format messages + tool schemas)
b. If tool_calls โ dispatch each via handle_function_call() โ append results โ continue
c. If text response โ return
3. Context compression triggers automatically near token limit
Testing
python -m pytest tests/ -o 'addopts=' -q # Full suite
python -m pytest tests/tools/ -q # Specific area
- Tests auto-redirect
HERMES_HOME to temp dirs โ never touch real ~/.hermes/
- Run full suite before pushing any change
- Use
-o 'addopts=' to clear any baked-in pytest flags
Windows contributors: scripts/run_tests.sh currently looks for POSIX venvs ( .venv/bin/activate / venv/bin/activate) and will error out on Windows where the layout is venv/Scripts/activate + python.exe. The Hermes-installed venv at venv/Scripts/ also has no pip or pytest โ it's stripped for end-user install size. Workaround: install pytest + pytest-xdist + pyyaml into a system Python 3.11 user site ( /c/Program Files/Python311/python -m pip install --user pytest pytest-xdist pyyaml), then run tests directly:
export PYTHONPATH="$(pwd)"
"/c/Program Files/Python311/python" -m pytest tests/tools/test_foo.py -v --tb=short -n 0
Use -n 0 (not -n 4) because pyproject.toml's default addopts already includes -n, and the wrapper's CI-parity story doesn't apply off-POSIX.
Cross-platform test guards: tests that use POSIX-only syscalls need a skip marker. Common ones already in the codebase:
- Symlink creation โ
@pytest.mark.skipif(sys.platform == "win32", reason="Symlinks require elevated privileges on Windows") (see tests/cron/test_cron_script.py)
- POSIX file modes (0o600, etc.) โ
@pytest.mark.skipif(sys.platform.startswith("win"), reason="POSIX mode bits not enforced on Windows") (see tests/hermes_cli/test_auth_toctou_file_modes.py)
signal.SIGALRM โ Unix-only (see tests/conftest.py::_enforce_test_timeout)
- Live Winsock / Windows-specific regression tests โ
@pytest.mark.skipif(sys.platform != "win32", reason="Windows-specific regression")
Monkeypatching sys.platform is not enough when the code under test also calls platform.system() / platform.release() / platform.mac_ver(). Those functions re-read the real OS independently, so a test that sets sys.platform = "linux" on a Windows runner will still see platform.system() == "Windows" and route through the Windows branch. Patch all three together:
monkeypatch.setattr(sys, "platform", "linux")
monkeypatch.setattr(platform, "system", lambda: "Linux")
monkeypatch.setattr(platform, "release", lambda: "6.8.0-generic")
See tests/agent/test_prompt_builder.py::TestEnvironmentHints for a worked example.
Extending the system prompt's execution-environment block
Factual guidance about the host OS, user home, cwd, terminal backend, and shell (bash vs. PowerShell on Windows) is emitted from agent/prompt_builder.py::build_environment_hints(). This is also where the WSL hint and per-backend probe logic live. The convention:
- Local terminal backend โ emit host info (OS,
$HOME, cwd) + Windows-specific notes (hostname โ username, terminal uses bash not PowerShell).
- Remote terminal backend (anything in
_REMOTE_TERMINAL_BACKENDS: docker, singularity, modal, daytona, ssh, vercel_sandbox, managed_modal) โ suppress host info entirely and describe only the backend. A live uname/whoami/pwd probe runs inside the backend via tools.environments.get_environment(...).execute(...), cached per process in _BACKEND_PROBE_CACHE, with a static fallback if the probe times out.
- Key fact for prompt authoring: when
TERMINAL_ENV != "local", every file tool (read_file, write_file, patch, search_files) runs inside the backend container, not on the host. The system prompt must never describe the host in that case โ the agent can't touch it.
Full design notes, the exact emitted strings, and testing pitfalls:
references/prompt-builder-environment-hints.md.
Refactor-safety pattern (POSIX-equivalence guard): when you extract inline logic into a helper that adds Windows/platform-specific behavior, keep a _legacy_<name> oracle function in the test file that's a verbatim copy of the old code, then parametrize-diff against it. Example: tests/tools/test_code_execution_windows_env.py::TestPosixEquivalence. This locks in the invariant that POSIX behavior is bit-for-bit identical and makes any future drift fail loudly with a clear diff.
Commit Conventions
type: concise subject line
Optional body.
Types: fix:, feat:, refactor:, docs:, chore:
Key Rules
- Never break prompt caching โ don't change context, tools, or system prompt mid-conversation
- Message role alternation โ never two assistant or two user messages in a row
- Use
get_hermes_home() from hermes_constants for all paths (profile-safe)
- Config values go in
config.yaml, secrets go in .env
- New tools need a
check_fn so they only appear when requirements are met
[IMPORTANT: The user has invoked the "kanban-orchestrator" skill, indicating they want you to follow its instructions. The full skill content is loaded below.]
---
name: kanban-orchestrator
description: Decomposition playbook + anti-temptation rules for an orchestrator profile routing work through Kanban. The "don't do the work yourself" rule and the basic lifecycle are auto-injected into every kanban worker's system prompt; this skill is the deeper playbook when you're specifically playing the orchestrator role.
version: 3.0.0
platforms: [linux, macos, windows]
metadata:
hermes:
tags: [kanban, multi-agent, orchestration, routing]
related_skills: [kanban-worker]
---
Kanban Orchestrator โ Decomposition Playbook
> The core worker lifecycle (including the kanban_create fan-out pattern and the "decompose, don't execute" rule) is auto-injected into every kanban process via the KANBAN_GUIDANCE system-prompt block. This skill is the deeper playbook when you're an orchestrator profile whose whole job is routing.
Profiles are user-configured โ not a fixed roster
Hermes setups vary widely. Some users run a single profile that does everything; some run a small fleet (docker-worker, cron-worker); some run a curated specialist team they've named themselves. There is no default specialist roster โ the orchestrator skill does not know what profiles exist on this machine.
Before fanning out, you must ground the decomposition in the profiles that actually exist. The dispatcher silently fails to spawn unknown assignee names โ it doesn't autocorrect, doesn't suggest, doesn't fall back. So a card assigned to researcher on a setup that only has docker-worker just sits in ready forever.
Step 0: discover available profiles before planning.
Use one of these:
hermes profile list โ prints the table of profiles configured on this machine. Run it through your terminal tool if you have one; otherwise ask the user.
kanban_list(assignee="<some-name>") โ sanity-check a single name. Returns an empty list (rather than an error) for an unknown assignee, so this only confirms a name you're already considering.
- Just ask the user. "What profiles do you have set up?" is a fine first turn when the goal needs more than one specialist.
Cache the result in your working memory for the rest of the conversation. Re-asking every turn wastes a tool call.
When to use the board (vs. just doing the work)
Create Kanban tasks when any of these are true:
1. Multiple specialists are needed. Research + analysis + writing is three profiles.
2. The work should survive a crash or restart. Long-running, recurring, or important.
3. The user might want to interject. Human-in-the-loop at any step.
4. Multiple subtasks can run in parallel. Fan-out for speed.
5. Review / iteration is expected. A reviewer profile loops on drafter output.
6. The audit trail matters. Board rows persist in SQLite forever.
If none of those apply โ it's a small one-shot reasoning task โ use delegate_task instead or answer the user directly.
The anti-temptation rules
Your job description says "route, don't execute." The rules that enforce that:
- Do not execute the work yourself. Your restricted toolset usually doesn't even include terminal/file/code/web for implementation. If you find yourself "just fixing this quickly" โ stop and create a task for the right specialist.
- For any concrete task, create a Kanban task and assign it. Every single time.
- Split multi-lane requests before creating cards. A user prompt can contain several independent workstreams. Extract those lanes first, then create one card per lane instead of bundling unrelated work into a single implementer card.
- Run independent lanes in parallel. If two cards do not need each other's output, leave them unlinked so the dispatcher can fan them out. Link only true data dependencies.
- If no specialist fits the available profiles, ask the user which profile to create or which existing profile to use. Do not invent profile names; the dispatcher will silently drop unknown assignees.
- Decompose, route, and summarize โ that's the whole job.
Exception: micro-UI polish cycles
There is one narrow exception where the orchestrator may execute directly instead of creating Kanban cards: tiny UI-only polish cycles (e.g., adding a CSS class, a theme preview dot, a hover state, a cross-link, or a HUD button) that are purely presentational, require no cross-file logic changes, and fit comfortably inside a single bounded cycle with no need for review or parallel work. If the change is limited to HTML/CSS/JS cosmetics, no other profile has a stake in it, and the user did not ask for a design review, the orchestrator should just edit and publish rather than paying the kanban-overhead tax. This exception does NOT apply to architecture changes, adapter logic, plugin interfaces, or anything that touches the data layer.
Decomposition playbook
Step 1 โ Understand the goal
Ask clarifying questions if the goal is ambiguous. Cheap to ask; expensive to spawn the wrong fleet.
Step 2 โ Sketch the task graph
Before creating anything, draft the graph out loud (in your response to the user). Treat every concrete workstream as a candidate card:
1. Extract the lanes from the request.
2. Map each lane to one of the profiles you discovered in Step 0. If a lane doesn't fit any existing profile, ask the user which to use or create.
3. Decide whether each lane is independent or gated by another lane.
4. Create independent lanes as parallel cards with no parent links.
5. Create synthesis/review/integration cards with parent links to the lanes they depend on.
Examples of prompts that should fan out (using placeholder profile names โ substitute whatever exists on the user's setup):
- "Build an app" โ one card to a design-oriented profile for product/UI direction, one or two cards to engineering profiles for implementation, plus a later integration/review card if the user has a reviewer profile.
- "Fix blockers and check model variants" โ one implementation card for the blocker fixes plus one discovery/research card for config/source verification. A final reviewer card can depend on both.
- "Research docs and implement" โ a docs-research card can run in parallel with a codebase-discovery card; implementation waits only if it truly needs those findings.
- "Analyze this screenshot and find the related code" โ one card to a vision-capable profile for the visual analysis while another searches the codebase.
Words like "also," "finally," or "and" do not automatically imply a dependency. They often mean "make sure this is covered before reporting back." Only link tasks when one card cannot start until another card's output exists.
Show the graph to the user before creating cards. Let them correct it โ including which actual profile name should own each lane.
Step 3 โ Create tasks and link
Use the profile names from Step 0. The example below uses placeholders <profile-A>, <profile-B>, <profile-C> โ replace them with what the user actually has.
t1 = kanban_create(
title="research: Postgres cost vs current",
assignee="<profile-A>", # whichever profile handles research on this setup
body="Compare estimated infrastructure costs, migration costs, and ongoing ops costs over a 3-year window. Sources: AWS/GCP pricing, team time estimates, current Postgres bills from peers.",
tenant=os.environ.get("HERMES_TENANT"),
)["task_id"]
t2 = kanban_create(
title="research: Postgres performance vs current",
assignee="<profile-A>", # same profile, run in parallel
body="Compare query latency, throughput, and scaling characteristics at our expected data volume (~500GB, 10k QPS peak). Sources: benchmark papers, public case studies, pgbench results if easy.",
)["task_id"]
t3 = kanban_create(
title="synthesize migration recommendation",
assignee="<profile-B>", # whichever profile does synthesis/analysis
body="Read the findings from T1 (cost) and T2 (performance). Produce a 1-page recommendation with explicit trade-offs and a go/no-go call.",
parents=[t1, t2],
)["task_id"]
t4 = kanban_create(
title="draft decision memo",
assignee="<profile-C>", # whichever profile drafts user-facing prose
body="Turn the analyst's recommendation into a 2-page memo for the CTO. Match the tone of previous decision memos in the team's knowledge base.",
parents=[t3],
)["task_id"]
parents=[...] gates promotion โ children stay in todo until every parent reaches done, then auto-promote to ready. No manual coordination needed; the dispatcher and dependency engine handle it.
Step 4 โ Complete your own task
If you were spawned as a task yourself (e.g. a planner profile was assigned T0: "investigate Postgres migration"), mark it done with a summary of what you created:
kanban_complete(
summary="decomposed into T1-T4: 2 research lanes in parallel, 1 synthesis on their outputs, 1 prose draft on the recommendation",
metadata={
"task_graph": {
"T1": {"assignee": "<profile-A>", "parents": []},
"T2": {"assignee": "<profile-A>", "parents": []},
"T3": {"assignee": "<profile-B>", "parents": ["T1", "T2"]},
"T4": {"assignee": "<profile-C>", "parents": ["T3"]},
},
},
)
Step 5 โ Report back to the user
Tell them what you created in plain prose, naming the actual profiles you used:
> I've queued 4 tasks:
> - T1 (<profile-A>): cost comparison
> - T2 (<profile-A>): performance comparison, in parallel with T1
> - T3 (<profile-B>): synthesizes T1 + T2 into a recommendation
> - T4 (<profile-C>): turns T3 into a CTO memo
>
> The dispatcher will pick up T1 and T2 now. T3 starts when both finish. You'll get a gateway ping when T4 completes. Use the dashboard or hermes kanban tail <id> to follow along.
Common patterns
Fan-out + fan-in (research โ synthesize): N research-style cards with no parents, one synthesis card with all of them as parents.
Parallel implementation + validation: one implementer card makes the change while one explorer/researcher card verifies config, docs, or source mapping. A reviewer card can depend on both. Do not make the implementer own unrelated verification just because the user mentioned both in one sentence.
Pipeline with gates: planner โ implementer โ reviewer. Each stage's parents=[previous_task]. Reviewer blocks or completes; if reviewer blocks, the operator unblocks with feedback and respawns.
Same-profile queue: N tasks, all assigned to the same profile, no dependencies between them. Dispatcher serializes โ that profile processes them in priority order, accumulating experience in its own memory.
Parallel UI/frontend lanes: When the goal touches multiple independent HTML/CSS/JS files (e.g., a dashboard page and a 2D gather view), fan out to separate subagents per file. Each lane edits its own file, then the orchestrator integrates, fixes cross-file references (theme paths, shared JSON endpoints), and publishes. This avoids merge conflicts in single-file HTML dashboards and keeps each subagent's context focused. See references/parallel-ui-lanes-and-publishing.md for the post-subagent integration checklist and rsync safety notes.
Human-in-the-loop: Any task can kanban_block() to wait for input. Dispatcher respawns after /unblock. The comment thread carries the full context.
Pitfalls
Inventing profile names that don't exist. The dispatcher silently fails to spawn unknown assignees โ the card just sits in ready forever. Always assign to a profile from your Step 0 discovery; ask the user if you're unsure.
Bundling independent lanes into one card. If the user asks for two independent outcomes, create two cards. Example: "fix blockers and check model variants" is not one fixer task; create a fixer/engineer card for the fixes and an explorer/researcher card for the variant check, then optionally gate review on both.
Over-linking because of wording. "Finally check X" may still be parallel with implementation if X is static config, docs, or source discovery. Link it after implementation only when the check depends on the implementation result.
Forgetting dependency links. If the task graph says research -> implement -> review, do not create all tasks as independent ready cards. Use parent links so implement/review cannot run before their inputs exist.
Reassignment vs. new task. If a reviewer blocks with "needs changes," create a NEW task linked from the reviewer's task โ don't re-run the same task with a stern look. The new task is assigned to the original implementer profile.
Argument order for links. kanban_link(parent_id=..., child_id=...) โ parent first. Mixing them up demotes the wrong task to todo.
Ignoring explicit user feedback to keep building infrastructure. When the user says a specific UX issue (legibility, theme switching, movement density) is "immediate priority," treat it as P0 and route it before deeper packaging/architecture work. Infrastructure polish feels productive, but shipping user-visible fixes is what matters. Create cards for the UX feedback first, then resume infrastructure lanes.
Treating status: complete as immutable when user feedback says otherwise. A state.md that says status: complete does not override a user's report that a completion criterion is actually broken. If the user says "theme switching is not working" and the Final Completion Condition requires "working UI theme switcher," the mission is not complete. Reactivate immediately: set status: active, append a reactivation cycle log, and fix the issue. Do not burn cycles on post-complete verification while the user is reporting active defects.
Don't pre-create the whole graph if the shape depends on intermediate findings. If T3's structure depends on what T1 and T2 find, let T3 exist as a "synthesize findings" task whose own first step is to read parent handoffs and plan the rest. Orchestrators can spawn orchestrators.
Tenant inheritance. If HERMES_TENANT is set in your env, pass tenant=os.environ.get("HERMES_TENANT") on every kanban_create call so child tasks stay in the same namespace.
Verifying cross-file references after directory reorganization. When subagents edit HTML/CSS/JS files and the directory structure shifts (e.g., moving files from root into web/dashboard/ and web/gather/), relative asset paths ( themes/default/theme.css, ./ops-data.json) often break. After subagents finish, the orchestrator must grep for href= and src= in moved files and fix relative paths before publishing. Subagents don't know the final publish layout โ the orchestrator does.
Destructive sync wipes needed files. Commands like rsync -av --delete will delete destination files that aren't in the source list. If you publish a directory tree piecemeal (e.g., copy web/dashboard/ first, then web/gather/ separately), --delete on the first rsync will erase the gather files before the second rsync runs. Either list all source paths in a single rsync invocation, or omit --delete and use cp -r / rsync -av without deletion when doing staged copies.
Recovering stuck workers
When a worker profile keeps crashing, hallucinating, or getting blocked by its own mistakes (usually: wrong model, missing skill, broken credential), the kanban dashboard flags the task with a โ badge and opens a Recovery section in the drawer. Three primary actions:
1. Reclaim (or hermes kanban reclaim <task_id>) โ abort the running worker immediately and reset the task to ready. The existing claim TTL is ~15 min; this is the fast path out.
2. Reassign (or hermes kanban reassign <task_id> <new-profile> --reclaim) โ switch the task to a different profile (one that exists on this setup) and let the dispatcher pick it up with a fresh worker.
3. Change profile model โ the dashboard prints a copy-paste hint for hermes -p <profile> model since profile config lives on disk; edit it in a terminal, then Reclaim to retry with the new model.
Hallucination warnings appear on tasks where a worker's kanban_complete(created_cards=[...]) claim included card ids that don't exist or weren't created by the worker's profile (the gate blocks the completion), or where the free-form summary references t_<hex> ids that don't resolve (advisory prose scan, non-blocking). Both produce audit events that persist even after recovery actions โ the trail stays for debugging.
The user has provided the following instruction alongside the skill invocation: [IMPORTANT: You are running as a scheduled cron job. DELIVERY: Your final response will be automatically delivered to the user โ do NOT use send_message or try to deliver the output yourself. Just produce your report/output as your final response and the system handles the rest. SILENT: If there is genuinely nothing new to report, respond with exactly "[SILENT]" (nothing else) to suppress delivery. Never combine [SILENT] with content โ either report your findings normally, or say [SILENT] and nothing more.]
You are the 15-minute Orchestrator for Son's Autonomous Agent Lab v1, reporting to Discord channel ID 1505805763824586952.
Durable state path: /Users/jooho-hermes/.hermes/autonomous-agent-lab/state.md
Working directory for experiment artifacts: /Users/jooho-hermes/.hermes/autonomous-agent-lab/
Preferred published web root: /Users/jooho-hermes/hermes-web/agent-pets/
Top-level directive from Son:
- The project has evolved from a personal dashboard into an INSTALLABLE PRODUCT that external Hermes users can deploy.
- The final target is a self-contained, configurable, publishable solution: "Hermes Pixel Pet Ops Office".
- Do NOT shrink the mission into a small static MVP and autonomously stop.
- The Gather.town-style 2D spatial office is a first-class feature, not a side page.
Latest UX feedback from Son (treat as immediate priority before deeper packaging work):
- Details are hard for a human to understand. Add human-first summaries, plain-language labels, and progressive disclosure: summary first, technical details second.
- Gather Town version has too many agents roaming around. Reduce default movement, add density/speed controls, cluster agents by room/task, and add focus/calm mode.
- Theme switching is not visibly working. Implement real UI theme switcher with persistence and clear visual theme changes.
Key product requirements (installable solution level):
1. Config-driven architecture: all paths, URLs, colors, names, room layouts via config.yaml. No hardcoded references to jooho-hermes.
2. Self-contained package: clear directory structure (src/, web/, config/, docs/, scripts/), install script, requirements.txt.
3. Pluggable data adapter: support multiple backends via plugin architecture.
4. Themeable frontend: CSS variables driven from config, swappable themes, plus a working UI theme switcher.
5. Multi-tenant ready: works for any Hermes instance.
6. Build/Deploy ready: Dockerfile or docker-compose, or clear static-server setup.
7. Documentation: README, architecture docs, configuration reference, contributor guide.
8. Human-comprehensible UX: plain-language summaries and progressive disclosure for technical detail.
9. Gather.town calm mode: adjustable movement density/speed and less chaotic defaults.
10. Versioned releases: CHANGELOG.md, semantic versioning, release packaging.
Mission model:
- Read state.md first before doing anything else.
- If state.md says
status: inactive or has no Current Mission, do not invent work. Return exactly: ๐ก Autonomous Agent Lab ๋๊ธฐ์ค โ Son์ด ํธ๋ฆฌ๊ฑฐ/๋ฏธ์
์ ์ฃผ๋ฉด 15๋ถ ์ฌ์ดํด์ ์์ํฉ๋๋ค.
- If state.md says
status: active, run one bounded 15-minute cycle toward the full installable solution.
- If state.md says
status: complete, verify that the Final Completion Condition in state.md is truly met. If it is not fully met, reactivate or report that state needs correction.
Cycle procedure when active:
1. Read state.md first. Extract current mission, constraints, previous cycle log, and Final Completion Condition.
2. Decide the next smallest useful step toward installable solution quality. Focus on: architecture, configurability, documentation, and clean separation of concerns.
3. Use delegate_task for independent subagent lanes when helpful.
4. Prefer concrete progress: refactor to config-driven, add install scripts, create docs, add Docker support, theme system, plugin architecture.
5. Update state.md with a new cycle log entry before final reporting.
6. Completion rule: only set status: complete when every item under state.md Final Completion Condition is satisfied. A non-installable MVP is not complete.
7. Stop/block only if Son explicitly stops/redirects, a safety boundary is reached, or a hard blocker needs Son's decision.
Link requirement (never forget):
- Every cycle report MUST include at least one direct viewable link to the published dashboard/artifact.
- The canonical URL:
http://hermes-mac-mini.tail46b3c6.ts.net:8099/agent-pets/
- Include gather town URL too:
http://hermes-mac-mini.tail46b3c6.ts.net:8099/agent-pets/gather/
Final Discord message format:
[Autonomous Agent Lab v1 / Cycle N]
๋ชฉํ:
์ํ:
๊ฒฐ๊ณผ:
๊ฒ์ฆ:
๋ค์:
์ํ:
Safety/quality rules:
- Do not handle secrets, passwords, API keys, payment, permission dialogs, or destructive commands.
- Do not claim completion without updating state.md.
- Do not rely on Discord history as durable state.
- Do not spam raw logs; summarize lane outputs and verification.
- Keep working in /Users/jooho-hermes/.hermes/autonomous-agent-lab/ and publish only to /Users/jooho-hermes/hermes-web/agent-pets/ unless the state file says otherwise.
Design/UX priorities:
- Mobile responsiveness is first-class.
- Character animation/movement is desired.
- Every cycle report must include published links.
- This is now a product engineering mission. Architecture, configurability, and documentation matter as much as visuals.
Response
[Autonomous Agent Lab v1 / Cycle 78]
๋ชฉํ:
1. Inspector ๋ชจ๋ฌ์ "๐ ๋งํฌ ๋ณต์ฌ" ๋ฒํผ ์ถ๊ฐ (Cycle 76์ deep-link ๊ธฐ๋ฅ์ ์ฌ์ฉ์๊ฐ ์ฝ๊ฒ ๋ฐ๊ฒฌํ ์ ์๋๋ก)
2. scripts/publish.sh์ Python ์๋ ํ์ ๊ธฐ๋ฅ ์ถ๊ฐ (PyYAML์ด ์๋ ์์คํ
Python ํ๊ฒฝ์์๋ ์คํ ๊ฐ๋ฅํ๋๋ก)
์ํ:
web/js/dashboard.js: copyAgentLink() ํจ์ ์ถ๊ฐ โ ํ์ฌ URL์ #agent=<id> ํด์๋ฅผ ํด๋ฆฝ๋ณด๋์ ๋ณต์ฌ, ํ ์คํธ ์๋ฆผ์ผ๋ก ํผ๋๋ฐฑ
web/css/dashboard.css: .inspector-card .btn-link ์คํ์ผ ์ถ๊ฐ (theme-aware, close-btn๊ณผ ๋์ผํ ํฝ์
๋๋)
- Owner ์บ๋ฆญํฐ์ ์ผ๋ฐ ์์ด์ ํธ inspector ๋ชจ๋์ ๋งํฌ ๋ณต์ฌ ๋ฒํผ ์ฝ์
scripts/publish.sh: find_python() auto-detection ์ถ๊ฐ (test.sh / validate_setup.sh์ ๋์ผํ ํจํด)
- Cache busting v78๋ก ์ผ๊ด ๋ฒ์ ์
: badge
b78, ?v=78, Service Worker pixel-pet-ops-v25
- Adapter ์คํ ๋ฐ ์ ์ฒด publish ์๋ฃ
๊ฒ์ฆ:
- Integration tests: 134/134 passed, 0 failed
- Setup validation: 21/21 passed, 0 warned, 0 critical
- Adapter: 32 agents, 15 cron jobs, 20 sessions, 16 events, schema 1.4
ops-data.json / health.json mtime: fresh (< 60s)
refresh.err.log: empty, LaunchAgent healthy
- Published JS/CSS์
copyAgentLink, btn-link ์กด์ฌ ํ์ธ ์๋ฃ
๋ค์:
- Son์ด ๋์๋ณด๋์ ์ ์ํด badge
v1.4.4 ยท b78 ํ์ธ ํ ์๋ ํ
์คํธ:
1. Hero panel ํ
๋ง ์ค์์ฒ (Default / Dark Ops / Cozy Pastel)
2. Gather Town calm mode (5 agents, calm ๊ธฐ๋ณธ)
3. Inspector ์ด๊ณ "๐ ๋งํฌ ๋ณต์ฌ" ๋ฒํผ ํ
์คํธ
- Son์ด ๋ง์กฑํ๋ฉด
status: complete๋ก ๋ง๋ฌด๋ฆฌ
์ํ: active โ Son์ ๋ธ๋ผ์ฐ์ ํ์ธ ๋๊ธฐ ์ค
๐ ๋์๋ณด๋: http://hermes-mac-mini.tail46b3c6.ts.net:8099/agent-pets/
๐ Gather Town: http://hermes-mac-mini.tail46b3c6.ts.net:8099/agent-pets/gather/
|
| 2026-05-20 02-40-43 |
84,347 chars |
2026-05-20_02-40-43.md |
Cron Job: autonomous-agent-lab-v1-orchestrator
Job ID: 35127ff89556
Run Time: 2026-05-20 02:40:43
Schedule: every 15m
Prompt
[IMPORTANT: The user has invoked the "hermes-agent" skill, indicating they want you to follow its instructions. The full skill content is loaded below.]
---
name: hermes-agent
description: "Configure, extend, or contribute to Hermes Agent."
version: 2.1.0
author: Hermes Agent + Teknium
license: MIT
platforms: [linux, macos, windows]
metadata:
hermes:
tags: [hermes, setup, configuration, multi-agent, spawning, cli, gateway, development]
homepage: https://github.com/NousResearch/hermes-agent
related_skills: [claude-code, codex, opencode]
---
Hermes Agent
Hermes Agent is an open-source AI agent framework by Nous Research that runs in your terminal, messaging platforms, and IDEs. It belongs to the same category as Claude Code (Anthropic), Codex (OpenAI), and OpenClaw โ autonomous coding and task-execution agents that use tool calling to interact with your system. Hermes works with any LLM provider (OpenRouter, Anthropic, OpenAI, DeepSeek, local models, and 15+ others) and runs on Linux, macOS, and WSL.
What makes Hermes different:
- Self-improving through skills โ Hermes learns from experience by saving reusable procedures as skills. When it solves a complex problem, discovers a workflow, or gets corrected, it can persist that knowledge as a skill document that loads into future sessions. Skills accumulate over time, making the agent better at your specific tasks and environment.
- Persistent memory across sessions โ remembers who you are, your preferences, environment details, and lessons learned. Pluggable memory backends (built-in, Honcho, Mem0, and more) let you choose how memory works.
- Multi-platform gateway โ the same agent runs on Telegram, Discord, Slack, WhatsApp, Signal, Matrix, Email, and 10+ other platforms with full tool access, not just chat.
- Provider-agnostic โ swap models and providers mid-workflow without changing anything else. Credential pools rotate across multiple API keys automatically.
- Profiles โ run multiple independent Hermes instances with isolated configs, sessions, skills, and memory.
- Extensible โ plugins, MCP servers, custom tools, webhook triggers, cron scheduling, and the full Python ecosystem.
People use Hermes for software development, research, system administration, data analysis, content creation, home automation, and anything else that benefits from an AI agent with persistent context and full system access.
This skill helps you work with Hermes Agent effectively โ setting it up, configuring features, spawning additional agent instances, troubleshooting issues, finding the right commands and settings, and understanding how the system works when you need to extend or contribute to it.
Docs: https://hermes-agent.nousresearch.com/docs/
Quick Start
Install
curl -fsSL https://raw.githubusercontent.com/NousResearch/hermes-agent/main/scripts/install.sh | bash
Interactive chat (default)
hermes
Single query
hermes chat -q "What is the capital of France?"
Setup wizard
hermes setup
Change model/provider
hermes model
Check health
hermes doctor
---
CLI Reference
Global Flags
hermes [flags] [command]
--version, -V Show version
--resume, -r SESSION Resume session by ID or title
--continue, -c [NAME] Resume by name, or most recent session
--worktree, -w Isolated git worktree mode (parallel agents)
--skills, -s SKILL Preload skills (comma-separate or repeat)
--profile, -p NAME Use a named profile
--yolo Skip dangerous command approval
--pass-session-id Include session ID in system prompt
No subcommand defaults to chat.
Chat
hermes chat [flags]
-q, --query TEXT Single query, non-interactive
-m, --model MODEL Model (e.g. anthropic/claude-sonnet-4)
-t, --toolsets LIST Comma-separated toolsets
--provider PROVIDER Force provider (openrouter, anthropic, nous, etc.)
-v, --verbose Verbose output
-Q, --quiet Suppress banner, spinner, tool previews
--checkpoints Enable filesystem checkpoints (/rollback)
--source TAG Session source tag (default: cli)
Configuration
hermes setup [section] Interactive wizard (model|terminal|gateway|tools|agent)
hermes model Interactive model/provider picker
hermes config View current config
hermes config edit Open config.yaml in $EDITOR
hermes config set KEY VAL Set a config value
hermes config path Print config.yaml path
hermes config env-path Print .env path
hermes config check Check for missing/outdated config
hermes config migrate Update config with new options
hermes doctor [--fix] Check dependencies and config
Credential Pools
hermes auth add Interactive credential wizard (oauth, api-key)
hermes auth list [PROVIDER] List pooled credentials
hermes auth remove P INDEX Remove by provider + index
hermes auth reset PROVIDER Clear exhaustion status
hermes logout Clear stored auth
Tools & Skills
hermes tools Interactive tool enable/disable (curses UI)
hermes tools list Show all tools and status
hermes tools enable NAME Enable a toolset
hermes tools disable NAME Disable a toolset
hermes skills list List installed skills
hermes skills search QUERY Search the skills hub
hermes skills install ID Install a skill (ID can be a hub identifier OR a direct https://โฆ/SKILL.md URL; pass --name to override when frontmatter has no name)
hermes skills inspect ID Preview without installing
hermes skills config Enable/disable skills per platform
hermes skills check Check for updates
hermes skills update Update outdated skills
hermes skills uninstall N Remove a hub skill
hermes skills publish PATH Publish to registry
hermes skills browse Browse all available skills
hermes skills tap add REPO Add a GitHub repo as skill source
MCP Servers
hermes mcp serve Run Hermes as an MCP server
hermes mcp add NAME Add an MCP server (--url or --command)
hermes mcp remove NAME Remove an MCP server
hermes mcp list List configured servers
hermes mcp test NAME Test connection
hermes mcp configure NAME Toggle tool selection
Gateway (Messaging Platforms)
hermes gateway run Start gateway foreground
hermes gateway install Install as background service
hermes gateway start/stop Control the service
hermes gateway restart Restart the service
hermes gateway status Check status
hermes gateway setup Configure platforms
Supported platforms: Telegram, Discord, Slack, WhatsApp, Signal, Email, SMS, Matrix, Mattermost, Home Assistant, DingTalk, Feishu, WeCom, BlueBubbles (iMessage), Weixin (WeChat), API Server, Webhooks. Open WebUI connects via the API Server adapter.
Platform docs: https://hermes-agent.nousresearch.com/docs/user-guide/messaging/
Discord-specific walkthrough (token, intents, service install, access control): see references/discord-gateway-setup.md in this skill.
- Per-channel personas and skill bindings: see
references/gateway-channel-personas.md (works on Discord, Slack, Telegram, Mattermost, Matrix).
- For long-running Discord-first operations, purpose-specific channel routing, periodic summaries, weekly Dreaming/audit reports, and log-safety patterns: see
references/discord-operating-planes.md.
- For broad Hermes/LifeOS/SQAF ecosystem audits (cron inventory, live services, dashboards, provider/model warnings, and control-plane gaps), see
references/ecosystem-audit.md.
Sessions
hermes sessions list List recent sessions
hermes sessions browse Interactive picker
hermes sessions export OUT Export to JSONL
hermes sessions rename ID T Rename a session
hermes sessions delete ID Delete a session
hermes sessions prune Clean up old sessions (--older-than N days)
hermes sessions stats Session store statistics
For browser-based viewing of existing Hermes CLI/Discord/cron session transcripts, prefer a lightweight static export from ~/.hermes/state.db into a private web root instead of assuming Open WebUI can browse Hermes' native session store. See references/hermes-session-static-web-viewer.md for the SQLite schema, static HTML export workflow, redaction/truncation cautions, and the user's Mac mini deployment (/hermes-sessions/ under the Tailscale-only ~/hermes-web site).
For cron job execution history, the same static-export pattern applies to ~/.hermes/cron/jobs.json and ~/.hermes/cron/output/{job_id}/*.md. See references/cron-history-web-viewer.md for the cron data model, schedule-dict pitfall, and the user's deployed /cron-history/ dashboard.
Cron Jobs
hermes cron list List jobs (--all for disabled)
hermes cron create SCHED Create: '30m', 'every 2h', '0 9 *'
hermes cron edit ID Edit schedule, prompt, delivery
hermes cron pause/resume ID Control job state
hermes cron run ID Trigger on next tick
hermes cron remove ID Delete a job
hermes cron status Scheduler status
For bounded autonomous lab/orchestrator cron jobs that use file-based state, subagent lanes, artifact publishing, and status transitions (active โ complete/blocked/inactive), see references/autonomous-agent-lab-cron-cycle.md. A reusable verification script template lives at scripts/verify-completion-template.py.
For a worked example of evolving an autonomous lab into a config-driven, themeable, Docker-ready installable product, see references/autonomous-lab-product-architecture.md. For CI, integration testing, pluggable adapter architecture, bounded cycle orchestration, and post-productization patterns, see references/product-maturity-patterns.md.
For the final completion verification checklist โ the explicit audit pattern to run before marking status: complete on an installable-solution mission, see references/autonomous-lab-completion-verification.md.
For the reactivation protocol when a completed lab receives new P0 feedback or the user contradicts a completion claim, see references/autonomous-lab-reactivation-protocol.md.
For the config/CHANGELOG version drift pitfall that occurs when autonomous labs evolve over many cycles, and for the related source vs. published file drift problem where the live web root diverges from the project source, see references/autonomous-lab-version-drift.md.
For adding historical trend tracking (SQLite-backed agent status transitions + vanilla JS SVG sparklines) to an autonomous lab dashboard, see references/history-tracking-sparkline-pattern.md.
For preventing unbounded SQLite growth in long-running labs, see references/autonomous-lab-data-retention.md โ covers automatic per-refresh pruning and a standalone manual prune utility.
- For reusable dashboard UX patterns (onboarding tours, data freshness badges, keyboard shortcuts, progressive disclosure inspectors, cross-linking between views, inspector deep-linking), see
references/dashboard-ux-patterns.md.
For the daily operational briefing modal โ a one-screen human-first summary of agent counts, blocked work, recent events, health status, and upcoming cron schedules โ see references/daily-briefing-modal.md.
For the aggressive human-first inspector refinement โ when users report that details are hard to understand and the fix is to strip technical labels from the default view โ see references/progressive-disclosure-human-first.md.
For programmatic verification of CSS custom-property theme systems โ catching scoping bugs, confirming theme distinctness, and validating JS switching logic โ see references/theme-system-verification.md.
- For Son's Discord-first autonomous experiments where a channel hosts a repeated multi-agent loop, use the Autonomous Discord Agent Lab pattern: create file-based durable state, a paused cron orchestrator delivered to
discord:<channel_id>, then activate it from a user mission trigger. See references/autonomous-discord-agent-lab.md.
- For verifying that a release package (
tar.gz) is actually installable by third parties and contains no stale artifacts or hardcoded references, see references/release-package-verification.md and the reusable script at scripts/release-verify.sh.
Webhooks
hermes webhook subscribe N Create route at /webhooks/<name>
hermes webhook list List subscriptions
hermes webhook remove NAME Remove a subscription
hermes webhook test NAME Send a test POST
Profiles
hermes profile list List all profiles
hermes profile create NAME Create (--clone, --clone-all, --clone-from)
hermes profile use NAME Set sticky default
hermes profile delete NAME Delete a profile
hermes profile show NAME Show details
hermes profile alias NAME Manage wrapper scripts
hermes profile rename A B Rename a profile
hermes profile export NAME Export to tar.gz
hermes profile import FILE Import from archive
Credential Pools
hermes auth add Interactive credential wizard
hermes auth list [PROVIDER] List pooled credentials
hermes auth remove P INDEX Remove by provider + index
hermes auth reset PROVIDER Clear exhaustion status
Other
hermes insights [--days N] Usage analytics
hermes update Update to latest version
hermes pairing list/approve/revoke DM authorization
hermes plugins list/install/remove Plugin management
hermes honcho setup/status Honcho memory integration (requires honcho plugin)
hermes memory setup/status/off Memory provider config
hermes completion bash|zsh Shell completions
hermes acp ACP server (IDE integration)
hermes claw migrate Migrate from OpenClaw
hermes uninstall Uninstall Hermes
---
Slash Commands (In-Session)
Type these during an interactive chat session. New commands land fairly
often; if something below looks stale, run /help in-session for the
authoritative list or see the [live slash commands reference](https://hermes-agent.nousresearch.com/docs/reference/slash-commands).
The registry of record is hermes_cli/commands.py โ every consumer
(autocomplete, Telegram menu, Slack mapping, /help) derives from it.
Session Control
/new (/reset) Fresh session
/clear Clear screen + new session (CLI)
/retry Resend last message
/undo Remove last exchange
/title [name] Name the session
/compress Manually compress context
/stop Kill background processes
/rollback [N] Restore filesystem checkpoint
/snapshot [sub] Create or restore state snapshots of Hermes config/state (CLI)
/background <prompt> Run prompt in background
/queue <prompt> Queue for next turn
/steer <prompt> Inject a message after the next tool call without interrupting
/agents (/tasks) Show active agents and running tasks
/resume [name] Resume a named session
/goal [text|sub] Set a standing goal Hermes works on across turns until achieved
(subcommands: status, pause, resume, clear)
/redraw Force a full UI repaint (CLI)
Configuration
/config Show config (CLI)
/model [name] Show or change model
/personality [name] Set personality
/reasoning [level] Set reasoning (none|minimal|low|medium|high|xhigh|show|hide)
/verbose Cycle: off โ new โ all โ verbose
/voice [on|off|tts] Voice mode
/yolo Toggle approval bypass
/busy [sub] Control what Enter does while Hermes is working (CLI)
(subcommands: queue, steer, interrupt, status)
/indicator [style] Pick the TUI busy-indicator style (CLI)
(styles: kaomoji, emoji, unicode, ascii)
/footer [on|off] Toggle gateway runtime-metadata footer on final replies
/skin [name] Change theme (CLI)
/statusbar Toggle status bar (CLI)
Tools & Skills
/tools Manage tools (CLI)
/toolsets List toolsets (CLI)
/skills Search/install skills (CLI)
/skill <name> Load a skill into session
/reload-skills Re-scan ~/.hermes/skills/ for added/removed skills
/reload Reload .env variables into the running session (CLI)
/reload-mcp Reload MCP servers
/cron Manage cron jobs (CLI)
/curator [sub] Background skill maintenance (status, run, pin, archive, โฆ)
/kanban [sub] Multi-profile collaboration board (tasks, links, comments)
/plugins List plugins (CLI)
Gateway
/approve Approve a pending command (gateway)
/deny Deny a pending command (gateway)
/restart Restart gateway (gateway)
/sethome Set current chat as home channel (gateway)
/update Update Hermes to latest (gateway)
/topic [sub] Enable or inspect Telegram DM topic sessions (gateway)
/platforms (/gateway) Show platform connection status (gateway)
Utility
/branch (/fork) Branch the current session
/fast Toggle priority/fast processing
/browser Open CDP browser connection
/history Show conversation history (CLI)
/save Save conversation to file (CLI)
/copy [N] Copy the last assistant response to clipboard (CLI)
/paste Attach clipboard image (CLI)
/image Attach local image file (CLI)
Info
/help Show commands
/commands [page] Browse all commands (gateway)
/usage Token usage
/insights [days] Usage analytics
/gquota Show Google Gemini Code Assist quota usage (CLI)
/status Session info (gateway)
/profile Active profile info
/debug Upload debug report (system info + logs) and get shareable links
Exit
/quit (/exit, /q) Exit CLI
---
Key Paths & Config
~/.hermes/config.yaml Main configuration
~/.hermes/.env API keys and secrets
$HERMES_HOME/skills/ Installed skills
~/.hermes/sessions/ Session transcripts
~/.hermes/logs/ Gateway and error logs
~/.hermes/auth.json OAuth tokens and credential pools
~/.hermes/hermes-agent/ Source code (if git-installed)
Profiles use ~/.hermes/profiles/<name>/ with the same layout.
Config Sections
Edit with hermes config edit or hermes config set section.key value.
| Section | Key options |
|---------|-------------|
| model | default, provider, base_url, api_key, context_length |
| agent | max_turns (90), tool_use_enforcement |
| terminal | backend (local/docker/ssh/modal), cwd, timeout (180) |
| compression | enabled, threshold (0.50), target_ratio (0.20) |
| display | skin, tool_progress, show_reasoning, show_cost |
| stt | enabled, provider (local/groq/openai/mistral) |
| tts | provider (edge/elevenlabs/openai/minimax/mistral/neutts) |
| memory | memory_enabled, user_profile_enabled, provider |
| security | tirith_enabled, website_blocklist |
| delegation | model, provider, base_url, api_key, max_iterations (50), reasoning_effort |
| checkpoints | enabled, max_snapshots (50) |
| fallback_model | provider, model, base_url, key_env |
Fallback Providers
Hermes can automatically fail over to a backup provider:model when the primary is unavailable. This is turn-scoped โ each new user message starts with the primary restored; fallback only activates mid-turn when the primary fails.
Configuration ( ~/.hermes/config.yaml):
fallback_model:
provider: opencode-go
model: kimi-k2.6
Or use the interactive manager:
hermes fallback add # interactive picker
hermes fallback list # show fallback chain
hermes fallback remove # remove by index
Legacy note: fallback_model (singular) is the legacy single-fallback key. fallback_providers (list) supports multiple ordered fallbacks. When both exist, fallback_providers takes priority.
Trigger conditions (after exhausting retries where applicable):
- Rate limits (HTTP 429)
- Server errors (HTTP 500, 502, 503)
- Auth failures (HTTP 401, 403) โ immediately
- Not found (HTTP 404) โ immediately
- Invalid / empty responses repeatedly
Supported providers include all standard providers (OpenRouter, Anthropic, OpenCode Go/ Zen, Kimi, etc.) plus custom endpoints with base_url + key_env. Full provider docs: https://hermes-agent.nousresearch.com/docs/integrations/providers
Limitations:
- Subagent delegation does not inherit fallback config
- Cron jobs do not use fallback (use per-job provider/model overrides)
- Auxiliary tasks (vision, compression, etc.) use their own
auxiliary.* provider chain
For a deep-dive with worked examples and model lists, see references/fallback-providers.md.
Full config reference: https://hermes-agent.nousresearch.com/docs/user-guide/configuration
Providers
20+ providers supported. Set via hermes model or hermes setup.
| Provider | Auth | Key env var |
|----------|------|-------------|
| OpenRouter | API key | OPENROUTER_API_KEY |
| Anthropic | API key | ANTHROPIC_API_KEY |
| Nous Portal | OAuth | hermes auth |
| OpenAI Codex | OAuth | hermes auth |
| GitHub Copilot | Token | COPILOT_GITHUB_TOKEN |
| Google Gemini | API key | GOOGLE_API_KEY or GEMINI_API_KEY |
| DeepSeek | API key | DEEPSEEK_API_KEY |
| xAI / Grok | API key | XAI_API_KEY |
| Hugging Face | Token | HF_TOKEN |
| Z.AI / GLM | API key | GLM_API_KEY |
| MiniMax | API key | MINIMAX_API_KEY |
| MiniMax CN | API key | MINIMAX_CN_API_KEY |
| Kimi / Moonshot | API key | KIMI_API_KEY |
| Alibaba / DashScope | API key | DASHSCOPE_API_KEY |
| Xiaomi MiMo | API key | XIAOMI_API_KEY |
| Kilo Code | API key | KILOCODE_API_KEY |
| AI Gateway (Vercel) | API key | AI_GATEWAY_API_KEY |
| OpenCode Zen | API key | OPENCODE_ZEN_API_KEY |
| OpenCode Go | API key | OPENCODE_GO_API_KEY |
| Qwen OAuth | OAuth | hermes auth add qwen-oauth |
| Custom endpoint | Config | model.base_url + model.api_key in config.yaml |
| GitHub Copilot ACP | External | COPILOT_CLI_PATH or Copilot CLI |
Full provider docs: https://hermes-agent.nousresearch.com/docs/integrations/providers
Toolsets
Enable/disable via hermes tools (interactive) or hermes tools enable/disable NAME.
| Toolset | What it provides |
|---------|-----------------|
| web | Web search and content extraction |
| search | Web search only (subset of web) |
| browser | Browser automation (Browserbase, Camofox, or local Chromium) |
| terminal | Shell commands and process management |
| file | File read/write/search/patch |
| code_execution | Sandboxed Python execution |
| vision | Image analysis |
| image_gen | AI image generation |
| video | Video analysis and generation |
| tts | Text-to-speech |
| skills | Skill browsing and management |
| memory | Persistent cross-session memory |
| session_search | Search past conversations |
| delegation | Subagent task delegation |
| cronjob | Scheduled task management |
| clarify | Ask user clarifying questions |
| messaging | Cross-platform message sending |
| todo | In-session task planning and tracking |
| kanban | Multi-agent work-queue tools (gated to workers) |
| debugging | Extra introspection/debug tools (off by default) |
| safe | Minimal, low-risk toolset for locked-down sessions |
| spotify | Spotify playback and playlist control |
| homeassistant | Smart home control (off by default) |
| discord | Discord integration tools |
| discord_admin | Discord admin/moderation tools |
| feishu_doc | Feishu (Lark) document tools |
| feishu_drive | Feishu (Lark) drive tools |
| yuanbao | Yuanbao integration tools |
| rl | Reinforcement learning tools (off by default) |
| moa | Mixture of Agents (off by default) |
Full enumeration lives in toolsets.py as the TOOLSETS dict; _HERMES_CORE_TOOLS is the default bundle most platforms inherit from.
Tool changes take effect on /reset (new session). They do NOT apply mid-conversation to preserve prompt caching.
---
Security & Privacy Toggles
Common "why is Hermes doing X to my output / tool calls / commands?" toggles โ and the exact commands to change them. Most of these need a fresh session (/reset in chat, or start a new hermes invocation) because they're read once at startup.
Secret redaction in tool output
Secret redaction is off by default โ tool output (terminal stdout, read_file, web content, subagent summaries, etc.) passes through unmodified. If the user wants Hermes to auto-mask strings that look like API keys, tokens, and secrets before they enter the conversation context and logs:
hermes config set security.redact_secrets true # enable globally
Restart required. security.redact_secrets is snapshotted at import time โ toggling it mid-session (e.g. via export HERMES_REDACT_SECRETS=true from a tool call) will NOT take effect for the running process. Tell the user to run hermes config set security.redact_secrets true in a terminal, then start a new session. This is deliberate โ it prevents an LLM from flipping the toggle on itself mid-task.
Disable again with:
hermes config set security.redact_secrets false
PII redaction in gateway messages
Separate from secret redaction. When enabled, the gateway hashes user IDs and strips phone numbers from the session context before it reaches the model:
hermes config set privacy.redact_pii true # enable
hermes config set privacy.redact_pii false # disable (default)
Command approval prompts
By default (approvals.mode: manual), Hermes prompts the user before running shell commands flagged as destructive (rm -rf, git reset --hard, etc.). The modes are:
manual โ always prompt (default)
smart โ use an auxiliary LLM to auto-approve low-risk commands, prompt on high-risk
off โ skip all approval prompts (equivalent to --yolo)
hermes config set approvals.mode smart # recommended middle ground
hermes config set approvals.mode off # bypass everything (not recommended)
Per-invocation bypass without changing config:
hermes --yolo โฆ
export HERMES_YOLO_MODE=1
Note: YOLO / approvals.mode: off does NOT turn off secret redaction. They are independent.
Shell hooks allowlist
Some shell-hook integrations require explicit allowlisting before they fire. Managed via ~/.hermes/shell-hooks-allowlist.json โ prompted interactively the first time a hook wants to run.
Disabling the web/browser/image-gen tools
To keep the model away from network or media tools entirely, open hermes tools and toggle per-platform. Takes effect on next session (/reset). See the Tools & Skills section above.
---
Voice & Transcription
STT (Voice โ Text)
Voice messages from messaging platforms are auto-transcribed.
Provider priority (auto-detected):
1. Local faster-whisper โ free, no API key: pip install faster-whisper
2. Groq Whisper โ free tier: set GROQ_API_KEY
3. OpenAI Whisper โ paid: set VOICE_TOOLS_OPENAI_KEY
4. Mistral Voxtral โ set MISTRAL_API_KEY
Config:
stt:
enabled: true
provider: local # local, groq, openai, mistral
local:
model: base # tiny, base, small, medium, large-v3
TTS (Text โ Voice)
| Provider | Env var | Free? |
|----------|---------|-------|
| Edge TTS | None | Yes (default) |
| ElevenLabs | ELEVENLABS_API_KEY | Free tier |
| OpenAI | VOICE_TOOLS_OPENAI_KEY | Paid |
| MiniMax | MINIMAX_API_KEY | Paid |
| Mistral (Voxtral) | MISTRAL_API_KEY | Paid |
| NeuTTS (local) | None (pip install neutts[all] + espeak-ng) | Free |
Voice commands: /voice on (voice-to-voice), /voice tts (always voice), /voice off.
---
Spawning Additional Hermes Instances
Run additional Hermes processes as fully independent subprocesses โ separate sessions, tools, and environments.
When to Use This vs delegate_task
| | delegate_task | Spawning hermes process |
|-|-----------------|--------------------------|
| Isolation | Separate conversation, shared process | Fully independent process |
| Duration | Minutes (bounded by parent loop) | Hours/days |
| Tool access | Subset of parent's tools | Full tool access |
| Interactive | No | Yes (PTY mode) |
| Use case | Quick parallel subtasks | Long autonomous missions |
One-Shot Mode
terminal(command="hermes chat -q 'Research GRPO papers and write summary to ~/research/grpo.md'", timeout=300)
Background for long tasks:
terminal(command="hermes chat -q 'Set up CI/CD for ~/myapp'", background=true)
Interactive PTY Mode (via tmux)
Hermes uses prompt_toolkit, which requires a real terminal. Use tmux for interactive spawning:
Start
terminal(command="tmux new-session -d -s agent1 -x 120 -y 40 'hermes'", timeout=10)
Wait for startup, then send a message
terminal(command="sleep 8 && tmux send-keys -t agent1 'Build a FastAPI auth service' Enter", timeout=15)
Read output
terminal(command="sleep 20 && tmux capture-pane -t agent1 -p", timeout=5)
Send follow-up
terminal(command="tmux send-keys -t agent1 'Add rate limiting middleware' Enter", timeout=5)
Exit
terminal(command="tmux send-keys -t agent1 '/exit' Enter && sleep 2 && tmux kill-session -t agent1", timeout=10)
Multi-Agent Coordination
Agent A: backend
terminal(command="tmux new-session -d -s backend -x 120 -y 40 'hermes -w'", timeout=10)
terminal(command="sleep 8 && tmux send-keys -t backend 'Build REST API for user management' Enter", timeout=15)
Agent B: frontend
terminal(command="tmux new-session -d -s frontend -x 120 -y 40 'hermes -w'", timeout=10)
terminal(command="sleep 8 && tmux send-keys -t frontend 'Build React dashboard for user management' Enter", timeout=15)
Check progress, relay context between them
terminal(command="tmux capture-pane -t backend -p | tail -30", timeout=5)
terminal(command="tmux send-keys -t frontend 'Here is the API schema from the backend agent: ...' Enter", timeout=5)
Session Resume
Resume most recent session
terminal(command="tmux new-session -d -s resumed 'hermes --continue'", timeout=10)
Resume specific session
terminal(command="tmux new-session -d -s resumed 'hermes --resume 20260225_143052_a1b2c3'", timeout=10)
Tips
- Prefer
delegate_task for quick subtasks โ less overhead than spawning a full process
- Use
-w (worktree mode) when spawning agents that edit code โ prevents git conflicts
- Set timeouts for one-shot mode โ complex tasks can take 5-10 minutes
- Use
hermes chat -q for fire-and-forget โ no PTY needed
- Use tmux for interactive sessions โ raw PTY mode has
\r vs \n issues with prompt_toolkit
- For scheduled tasks, use the
cronjob tool instead of spawning โ handles delivery and retry
---
Durable & Background Systems
Four systems run alongside the main conversation loop. Quick reference
here; full developer notes live in AGENTS.md, user-facing docs under
website/docs/user-guide/features/.
Delegation (delegate_task)
Synchronous subagent spawn โ the parent waits for the child's summary
before continuing its own loop. Isolated context + terminal session.
- Single:
delegate_task(goal, context, toolsets).
- Batch:
delegate_task(tasks=[{goal, ...}, ...]) runs children in
parallel, capped by delegation.max_concurrent_children (default 3).
- Roles:
leaf (default; cannot re-delegate) vs orchestrator
(can spawn its own workers, bounded by delegation.max_spawn_depth).
- Not durable. If the parent is interrupted, the child is
cancelled. For work that must outlive the turn, use cronjob or
terminal(background=True, notify_on_complete=True).
Config: delegation.* in config.yaml.
Tuning max_concurrent_children
Default is 3. Rule of thumb for raising it:
- Light tasks (web search, file grep): up to
6-8
- Medium tasks (code execution, browser):
4-5
- Heavy tasks (builds, large data):
2-3
- Actual bottleneck is usually the API rate limit, not local CPU/RAM. On a 10-core M4 with 16GB RAM, CPU is rarely the constraint.
- Formula: start at
5, raise only if profiling shows idle time between API responses.
Cron (scheduled jobs)
Durable scheduler โ cron/jobs.py + cron/scheduler.py. Drive it via
the cronjob tool, the hermes cron CLI (list, add, edit,
pause, resume, run, remove), or the /cron slash command.
- Schedules: duration (
"30m", "2h"), "every" phrase
( "every monday 9am"), 5-field cron ( "0 9 *"), or ISO timestamp.
- Per-job knobs:
skills, model/provider override, script
(pre-run data collection; no_agent=True makes the script the whole
job), context_from (chain job A's output into job B), workdir
(run in a specific dir with its AGENTS.md / CLAUDE.md loaded),
multi-platform delivery.
- Invariants: 3-minute hard interrupt per run,
.tick.lock file
prevents duplicate ticks across processes, cron sessions pass
skip_memory=True by default, and cron deliveries are framed with a
header/footer instead of being mirrored into the target gateway
session (keeps role alternation intact).
User docs: https://hermes-agent.nousresearch.com/docs/user-guide/features/cron
Curator (skill lifecycle)
Background maintenance for agent-created skills. Tracks usage, marks
idle skills stale, archives stale ones, keeps a pre-run tar.gz backup
so nothing is lost.
- CLI:
hermes curator <verb> โ status, run, pause, resume,
pin, unpin, archive, restore, prune, backup, rollback.
- Slash:
/curator <subcommand> mirrors the CLI.
- Scope: only touches skills with
created_by: "agent" provenance.
Bundled + hub-installed skills are off-limits. Never deletes โ
max destructive action is archive. Pinned skills are exempt from
every auto-transition and every LLM review pass.
- Telemetry: sidecar at
~/.hermes/skills/.usage.json holds
per-skill use_count, view_count, patch_count,
last_activity_at, state, pinned.
Config: curator.* (enabled, interval_hours, min_idle_hours,
stale_after_days, archive_after_days, backup.*).
User docs: https://hermes-agent.nousresearch.com/docs/user-guide/features/curator
Dreaming (periodic memory/skill consolidation)
For Anthropic-style "dreaming" workflows, combine cron + session_search + memory + skills + curator into a scheduled review loop. Start with a weekly, proposal-only report that audits recent sessions, repeated user corrections, memory conflicts, skill patch candidates, and cron/automation improvements. Do not automatically delete/replace memory or patch/archive skills unless the user explicitly approves the proposed changes. See references/weekly-dreaming-routine.md for the recommended prompt, report format, safety policy, and cron creation pattern.
Kanban (multi-agent work queue)
Durable SQLite board for multi-profile / multi-worker collaboration.
Users drive it via hermes kanban <verb>; dispatcher-spawned workers
see a focused kanban_* toolset gated by HERMES_KANBAN_TASK so the
schema footprint is zero outside worker processes.
- CLI verbs (common):
init, create, list (alias ls),
show, assign, link, unlink, comment, complete, block,
unblock, archive, tail. Less common: watch, stats, runs,
log, dispatch, daemon, gc.
- Worker toolset:
kanban_show, kanban_complete, kanban_block,
kanban_heartbeat, kanban_comment, kanban_create, kanban_link.
- Dispatcher runs inside the gateway by default
( kanban.dispatch_in_gateway: true) โ reclaims stale claims,
promotes ready tasks, atomically claims, spawns assigned profiles.
Auto-blocks a task after ~5 consecutive spawn failures.
- Isolation: board is the hard boundary (workers get
HERMES_KANBAN_BOARD pinned in env); tenant is a soft namespace
within a board for workspace-path + memory-key isolation.
User docs: https://hermes-agent.nousresearch.com/docs/user-guide/features/kanban
Log Relay (Hermes โ Discord)
A background Python script that tails ~/.hermes/logs/*.log and batches lines to a Discord channel. Includes session-ID extraction, rate-limit handling, and auto-restart via launchd/systemd. Useful for remote monitoring and audit trails.
- Reference:
references/discord-log-relay.md โ full setup, tuning, macOS/Linux service install, pitfalls.
- Template:
templates/discord-log-relay.py โ copy, set CHANNEL_ID, and deploy.
- Discord operations:
references/discord-operating-planes.md โ channel-purpose routing, periodic-summary vs Dreaming report formats, and safety/cost notes for Discord-first Hermes deployments.
Key pitfall: ask the user about batch frequency upfront rather than defaulting to real-time streaming. Most users prefer 10-minute or hourly batches. High-volume raw logs should be batched, summarized, or stored out-of-band; avoid Discord message storms during error loops.
Weekly Dreaming / Memory Curation
For long-running Hermes deployments, users may want an Anthropic-style "Dreaming" loop: a scheduled review that consolidates experience, proposes memory/skill/cron changes, and identifies what to keep, weaken, archive, or delete. Hermes has the building blocks (sessions, session_search, memory, skills, curator, cron), but the safe default is proposal mode:
1. Inspect recent usage and sessions.
2. Extract repeated success patterns, failure patterns, and user corrections.
3. Propose memory updates/removals without applying them silently.
4. Propose skill patches/archive candidates and cron/reporting improvements.
5. End with explicit approval checkboxes.
Do not silently rewrite or delete memory/skills from a Dreaming report unless the user explicitly authorized automatic application. See references/discord-operating-planes.md for a report template and routing heuristics.
---
Windows-Specific Quirks
Hermes runs natively on Windows (PowerShell, cmd, Windows Terminal, git-bash
mintty, VS Code integrated terminal). Most of it just works, but a handful
of differences between Win32 and POSIX have bitten us โ document new ones
here as you hit them so the next person (or the next session) doesn't
rediscover them from scratch.
Input / Keybindings
Alt+Enter doesn't insert a newline. Windows Terminal intercepts Alt+Enter
at the terminal layer to toggle fullscreen โ the keystroke never reaches
prompt_toolkit. Use Ctrl+Enter instead. Windows Terminal delivers
Ctrl+Enter as LF ( c-j), distinct from plain Enter ( c-m / CR), and the
CLI binds c-j to newline insertion on win32 only (see
_bind_prompt_submit_keys + the Windows-only c-j binding in cli.py).
Side effect: the raw Ctrl+J keystroke also inserts a newline on Windows โ
unavoidable, because Windows Terminal collapses Ctrl+Enter and Ctrl+J to
the same keycode at the Win32 console API layer. No conflicting binding
existed for Ctrl+J on Windows, so this is a harmless side effect.
mintty / git-bash behaves the same (fullscreen on Alt+Enter) unless you
disable Alt+Fn shortcuts in Options โ Keys. Easier to just use Ctrl+Enter.
Diagnosing keybindings. Run python scripts/keystroke_diagnostic.py
(repo root) to see exactly how prompt_toolkit identifies each keystroke
in the current terminal. Answers questions like "does Shift+Enter come
through as a distinct key?" (almost never โ most terminals collapse it
to plain Enter) or "what byte sequence is my terminal sending for
Ctrl+Enter?" This is how the Ctrl+Enter = c-j fact was established.
Config / Files
HTTP 400 "No models provided" on first run. config.yaml was saved
with a UTF-8 BOM (common when Windows apps write it). Re-save as UTF-8
without BOM. hermes config edit writes without BOM; manual edits in
Notepad are the usual culprit.
execute_code / Sandbox
WinError 10106 ("The requested service provider could not be loaded
or initialized") from the sandbox child process โ it can't create an
AF_INET socket, so the loopback-TCP RPC fallback fails before
connect(). Root cause is usually not a broken Winsock LSP; it's
Hermes's own env scrubber dropping SYSTEMROOT / WINDIR / COMSPEC
from the child env. Python's socket module needs SYSTEMROOT to locate
mswsock.dll. Fixed via the _WINDOWS_ESSENTIAL_ENV_VARS allowlist in
tools/code_execution_tool.py. If you still hit it, echo os.environ
inside an execute_code block to confirm SYSTEMROOT is set. Full
diagnostic recipe in references/execute-code-sandbox-env-windows.md.
Testing / Contributing
scripts/run_tests.sh doesn't work as-is on Windows โ it looks for
POSIX venv layouts ( .venv/bin/activate). The Hermes-installed venv at
venv/Scripts/ has no pip or pytest either (stripped for install size).
Workaround: install pytest + pytest-xdist + pyyaml into a system Python
3.11 user site, then invoke pytest directly with PYTHONPATH set:
"/c/Program Files/Python311/python" -m pip install --user pytest pytest-xdist pyyaml
export PYTHONPATH="$(pwd)"
"/c/Program Files/Python311/python" -m pytest tests/foo/test_bar.py -v --tb=short -n 0
Use -n 0, not -n 4 โ pyproject.toml's default addopts already
includes -n, and the wrapper's CI-parity guarantees don't apply off POSIX.
POSIX-only tests need skip guards. Common markers already in the codebase:
- Symlinks โ elevated privileges on Windows
0o600 file modes โ POSIX mode bits not enforced on NTFS by default
signal.SIGALRM โ Unix-only (see tests/conftest.py::_enforce_test_timeout)
- Winsock / Windows-specific regressions โ
@pytest.mark.skipif(sys.platform != "win32", ...)
Use the existing skip-pattern style (sys.platform == "win32" or
sys.platform.startswith("win")) to stay consistent with the rest of the
suite.
Path / Filesystem
Line endings. Git may warn LF will be replaced by CRLF the next time
Git touches it. Cosmetic โ the repo's .gitattributes normalizes. Don't
let editors auto-convert committed POSIX-newline files to CRLF.
Forward slashes work almost everywhere. C:/Users/... is accepted by
every Hermes tool and most Windows APIs. Prefer forward slashes in code
and logs โ avoids shell-escaping backslashes in bash.
---
Troubleshooting
Voice not working
1. Check stt.enabled: true in config.yaml
2. Verify provider: pip install faster-whisper or set API key
3. In gateway: /restart. In CLI: exit and relaunch.
Tool not available
1. hermes tools โ check if toolset is enabled for your platform
2. Some tools need env vars (check .env)
3. /reset after enabling tools
Model/provider issues
1. hermes doctor โ check config and dependencies
2. hermes auth add <provider> โ re-authenticate OAuth providers (use --type oauth)
3. Check .env has the right API key
4. Copilot 403: gh auth login tokens do NOT work for Copilot API. You must use the Copilot-specific OAuth device code flow via hermes model โ GitHub Copilot.
Changes not taking effect
- Tools/skills:
/reset starts a new session with updated toolset
- Config changes: In gateway:
/restart. In CLI: exit and relaunch.
- Code changes: Restart the CLI or gateway process
Deployed web dashboard shows stale CSS or theme changes
- Browser cache: Add
?v=N cache-busting query strings to CSS/JS/theme links in HTML.
- Service Worker cache: Bump
CACHE_NAME in sw.js to invalidate old shell caches.
- Automated bump script: For projects with multiple HTML entry points (dashboard, gather, etc.), use
scripts/bump-build.py to atomically update all build badges, cache-busting query strings, and service worker cache names in one command. See references/autonomous-lab-version-drift.md for usage.
- Data freshness: Use
fetch(url, {cache:'no-store'}) for live JSON feeds.
- Auto-detection: Embed
data-build in <html> and compare server build vs loaded build on page load to show a "new version available" banner. See references/static-site-cache-invalidation.md for the full diagnostic recipe and auto-detection pattern.
- Theme switcher reliability: If theme switching works in Chrome but not Samsung Internet, or feels broken on mobile, see
references/theme-switcher-reliability.md for the create-new-link โ load โ remove-old pattern.
- Emergency recovery: If a bad deploy breaks the main app JS, users need a standalone reset page. See
references/emergency-reset-page.md for a zero-dependency reset.html that clears Service Workers and caches without relying on the main app's JS.
Dashboard inspector feels too technical
- The default inspector view should contain only plain-language sentences: headline, "what they're doing now", "why it matters", and a silent visual progress bar (no text label).
- Move all technical fields (source IDs, confidence scores, progress labels, status slugs, badges) behind a "Show technical details" toggle.
- If users say "details are hard to understand," the fix is to remove more fields from the default view, not to add explanations. Explanations of technical fields are still technical.
- See
references/progressive-disclosure-human-first.md for the aggressive simplification pattern.
Pixel-art characters look wrong on mobile
- Decorative CSS elements (cheeks, ears, tails, badges) can be misread as facial features or appendages when avatars shrink below ~50 px.
- Hide them inside
@media (max-width:480px) so only the essential silhouette remains.
- See
references/pixel-art-mobile-readability.md for the exact selectors and rationale.
Skills not showing
1. hermes skills list โ verify installed
2. hermes skills config โ check platform enablement
3. Load explicitly: /skill name or hermes -s name
Gateway issues
Check logs first:
grep -i "failed to send\|error" ~/.hermes/logs/gateway.log | tail -20
Common gateway problems:
- Gateway dies on SSH logout: Enable linger:
sudo loginctl enable-linger $USER
- Gateway dies on WSL2 close: WSL2 requires
systemd=true in /etc/wsl.conf for systemd services to work. Without it, gateway falls back to nohup (dies when session closes).
- Gateway crash loop: Reset the failed state:
systemctl --user reset-failed hermes-gateway
- macOS: bot shows offline after idle time: The gateway runs as a user agent (
LimitLoadToSessionType=Aqua), so macOS suspends it when the system sleeps. The platform websocket drops and the bot appears offline until the network returns. Fix: keep the Mac awake (System Settings -> Energy -> Prevent automatic sleeping, or caffeinate -d -i -s -u &). Low Power Mode makes this worse, not better. See references/macos-gateway-sleep-disconnect.md for the full diagnostic recipe.
Platform-specific issues
- Discord bot silent: Must enable Message Content Intent in Bot โ Privileged Gateway Intents. See full Discord setup reference:
references/discord-gateway-setup.md.
- Slack bot only works in DMs: Must subscribe to
message.channels event. Without it, the bot ignores public channels.
- Windows-specific issues (
Alt+Enter newline, WinError 10106, UTF-8 BOM config, test suite, line endings): see the dedicated Windows-Specific Quirks section above.
Auxiliary models not working
If auxiliary tasks (vision, compression, session_search) fail silently, the auto provider can't find a backend. Either set OPENROUTER_API_KEY or GOOGLE_API_KEY, or explicitly configure each auxiliary task's provider:
hermes config set auxiliary.vision.provider <your_provider>
hermes config set auxiliary.vision.model <model_name>
Full system auth provisioning
For a one-shot workflow to maximize available credentials โ installing gh, generating SSH keys, configuring git, enabling all Hermes toolsets, and auditing current auth state โ see references/system-auth-setup.md.
Editing large files with patch
When a file is read with read_file(offset=...) (pagination), the tool warns that the view is partial. If you attempt patch without re-reading the full file first, you will likely hit non-unique match errors or corrupt the file. Fix: always call read_file without offset to load the whole file before patching. The tool explicitly warns: "โฆwas last read with offset/limit pagination (partial view). Re-read the whole file before overwriting it." โ heed this warning. For append-only updates (e.g., adding a cycle log entry to state.md), do not use terminal(command="cat >> file << 'EOF'...EOF") โ the terminal tool on macOS/Linux misinterprets heredoc << as backgrounding and fails. Instead, write a short Python script via write_file and execute it with terminal(command="python3 /tmp/script.py"). See references/terminal-heredoc-workaround.md for the full pattern.
Sibling subagent file overwrites
When multiple subagents are running in parallel (e.g. via delegate_task batch mode or kanban worker lanes), a file may be modified by one subagent while another is about to write to it. If you use write_file or patch on a file that was last read before a sibling subagent modified it, your write may silently truncate or revert the sibling's changes. The tool may show a warning like "this file was modified by sibling subagent X but this agent never read it."
Fix:
1. Heed the warning. If the tool reports a sibling modification, re-read the file with read_file before writing.
2. Prefer patch over write_file for partial updates โ patch only changes the matched region and is less likely to wipe unrelated content.
3. If the file is already published/deployed, and the local working copy gets corrupted, recover from the published copy:
cp ~/hermes-web/agent-pets/css/dashboard.css ~/.hermes/autonomous-agent-lab/pixel-pet-ops/web/css/dashboard.css
4. For append-only updates, write a small Python script and execute it rather than using write_file on the whole file.
Prevention: In kanban/multi-agent workflows, assign file-level ownership so only one worker touches each file. If parallel workers must edit the same file, have them write to separate temp files and let the orchestrator merge.
---
Windows-Specific Quirks
| Looking for... | Location |
|----------------|----------|
| Config options | hermes config edit or [Configuration docs](https://hermes-agent.nousresearch.com/docs/user-guide/configuration) |
| Available tools | hermes tools list or [Tools reference](https://hermes-agent.nousresearch.com/docs/reference/tools-reference) |
| Slash commands | /help in session or [Slash commands reference](https://hermes-agent.nousresearch.com/docs/reference/slash-commands) |
| Skills catalog | hermes skills browse or [Skills catalog](https://hermes-agent.nousresearch.com/docs/reference/skills-catalog) |
| Provider setup | hermes model or [Providers guide](https://hermes-agent.nousresearch.com/docs/integrations/providers) |
| Platform setup | hermes gateway setup or [Messaging docs](https://hermes-agent.nousresearch.com/docs/user-guide/messaging/) |
| MCP servers | hermes mcp list or [MCP guide](https://hermes-agent.nousresearch.com/docs/user-guide/features/mcp) |
| Profiles | hermes profile list or [Profiles docs](https://hermes-agent.nousresearch.com/docs/user-guide/profiles) |
| Cron jobs | hermes cron list or [Cron docs](https://hermes-agent.nousresearch.com/docs/user-guide/features/cron) |
| Memory | hermes memory status or [Memory docs](https://hermes-agent.nousresearch.com/docs/user-guide/features/memory) |
| Env variables | hermes config env-path or [Env vars reference](https://hermes-agent.nousresearch.com/docs/reference/environment-variables) |
| CLI commands | hermes --help or [CLI reference](https://hermes-agent.nousresearch.com/docs/reference/cli-commands) |
| Gateway logs | ~/.hermes/logs/gateway.log |
| Session files | ~/.hermes/sessions/ or hermes sessions browse |
| Source code | ~/.hermes/hermes-agent/ |
---
Contributor Quick Reference
For occasional contributors and PR authors. Full developer docs: https://hermes-agent.nousresearch.com/docs/developer-guide/
Project Layout
hermes-agent/
โโโ run_agent.py # AIAgent โ core conversation loop
โโโ model_tools.py # Tool discovery and dispatch
โโโ toolsets.py # Toolset definitions
โโโ cli.py # Interactive CLI (HermesCLI)
โโโ hermes_state.py # SQLite session store
โโโ agent/ # Prompt builder, context compression, memory, model routing, credential pooling, skill dispatch
โโโ hermes_cli/ # CLI subcommands, config, setup, commands
โ โโโ commands.py # Slash command registry (CommandDef)
โ โโโ config.py # DEFAULT_CONFIG, env var definitions
โ โโโ main.py # CLI entry point and argparse
โโโ tools/ # One file per tool
โ โโโ registry.py # Central tool registry
โโโ gateway/ # Messaging gateway
โ โโโ platforms/ # Platform adapters (telegram, discord, etc.)
โโโ cron/ # Job scheduler
โโโ tests/ # ~3000 pytest tests
โโโ website/ # Docusaurus docs site
Config: ~/.hermes/config.yaml (settings), ~/.hermes/.env (API keys).
Adding a Tool (3 files)
1. Create tools/your_tool.py:
import json, os
from tools.registry import registry
def check_requirements() -> bool:
return bool(os.getenv("EXAMPLE_API_KEY"))
def example_tool(param: str, task_id: str = None) -> str:
return json.dumps({"success": True, "data": "..."})
registry.register(
name="example_tool",
toolset="example",
schema={"name": "example_tool", "description": "...", "parameters": {...}},
handler=lambda args, **kw: example_tool(
param=args.get("param", ""), task_id=kw.get("task_id")),
check_fn=check_requirements,
requires_env=["EXAMPLE_API_KEY"],
)
2. Add to toolsets.py โ _HERMES_CORE_TOOLS list.
Auto-discovery: any tools/*.py file with a top-level registry.register() call is imported automatically โ no manual list needed.
All handlers must return JSON strings. Use get_hermes_home() for paths, never hardcode ~/.hermes.
Adding a Slash Command
1. Add CommandDef to COMMAND_REGISTRY in hermes_cli/commands.py
2. Add handler in cli.py โ process_command()
3. (Optional) Add gateway handler in gateway/run.py
All consumers (help text, autocomplete, Telegram menu, Slack mapping) derive from the central registry automatically.
Agent Loop (High Level)
run_conversation():
1. Build system prompt
2. Loop while iterations < max:
a. Call LLM (OpenAI-format messages + tool schemas)
b. If tool_calls โ dispatch each via handle_function_call() โ append results โ continue
c. If text response โ return
3. Context compression triggers automatically near token limit
Testing
python -m pytest tests/ -o 'addopts=' -q # Full suite
python -m pytest tests/tools/ -q # Specific area
- Tests auto-redirect
HERMES_HOME to temp dirs โ never touch real ~/.hermes/
- Run full suite before pushing any change
- Use
-o 'addopts=' to clear any baked-in pytest flags
Windows contributors: scripts/run_tests.sh currently looks for POSIX venvs ( .venv/bin/activate / venv/bin/activate) and will error out on Windows where the layout is venv/Scripts/activate + python.exe. The Hermes-installed venv at venv/Scripts/ also has no pip or pytest โ it's stripped for end-user install size. Workaround: install pytest + pytest-xdist + pyyaml into a system Python 3.11 user site ( /c/Program Files/Python311/python -m pip install --user pytest pytest-xdist pyyaml), then run tests directly:
export PYTHONPATH="$(pwd)"
"/c/Program Files/Python311/python" -m pytest tests/tools/test_foo.py -v --tb=short -n 0
Use -n 0 (not -n 4) because pyproject.toml's default addopts already includes -n, and the wrapper's CI-parity story doesn't apply off-POSIX.
Cross-platform test guards: tests that use POSIX-only syscalls need a skip marker. Common ones already in the codebase:
- Symlink creation โ
@pytest.mark.skipif(sys.platform == "win32", reason="Symlinks require elevated privileges on Windows") (see tests/cron/test_cron_script.py)
- POSIX file modes (0o600, etc.) โ
@pytest.mark.skipif(sys.platform.startswith("win"), reason="POSIX mode bits not enforced on Windows") (see tests/hermes_cli/test_auth_toctou_file_modes.py)
signal.SIGALRM โ Unix-only (see tests/conftest.py::_enforce_test_timeout)
- Live Winsock / Windows-specific regression tests โ
@pytest.mark.skipif(sys.platform != "win32", reason="Windows-specific regression")
Monkeypatching sys.platform is not enough when the code under test also calls platform.system() / platform.release() / platform.mac_ver(). Those functions re-read the real OS independently, so a test that sets sys.platform = "linux" on a Windows runner will still see platform.system() == "Windows" and route through the Windows branch. Patch all three together:
monkeypatch.setattr(sys, "platform", "linux")
monkeypatch.setattr(platform, "system", lambda: "Linux")
monkeypatch.setattr(platform, "release", lambda: "6.8.0-generic")
See tests/agent/test_prompt_builder.py::TestEnvironmentHints for a worked example.
Extending the system prompt's execution-environment block
Factual guidance about the host OS, user home, cwd, terminal backend, and shell (bash vs. PowerShell on Windows) is emitted from agent/prompt_builder.py::build_environment_hints(). This is also where the WSL hint and per-backend probe logic live. The convention:
- Local terminal backend โ emit host info (OS,
$HOME, cwd) + Windows-specific notes (hostname โ username, terminal uses bash not PowerShell).
- Remote terminal backend (anything in
_REMOTE_TERMINAL_BACKENDS: docker, singularity, modal, daytona, ssh, vercel_sandbox, managed_modal) โ suppress host info entirely and describe only the backend. A live uname/whoami/pwd probe runs inside the backend via tools.environments.get_environment(...).execute(...), cached per process in _BACKEND_PROBE_CACHE, with a static fallback if the probe times out.
- Key fact for prompt authoring: when
TERMINAL_ENV != "local", every file tool (read_file, write_file, patch, search_files) runs inside the backend container, not on the host. The system prompt must never describe the host in that case โ the agent can't touch it.
Full design notes, the exact emitted strings, and testing pitfalls:
references/prompt-builder-environment-hints.md.
Refactor-safety pattern (POSIX-equivalence guard): when you extract inline logic into a helper that adds Windows/platform-specific behavior, keep a _legacy_<name> oracle function in the test file that's a verbatim copy of the old code, then parametrize-diff against it. Example: tests/tools/test_code_execution_windows_env.py::TestPosixEquivalence. This locks in the invariant that POSIX behavior is bit-for-bit identical and makes any future drift fail loudly with a clear diff.
Commit Conventions
type: concise subject line
Optional body.
Types: fix:, feat:, refactor:, docs:, chore:
Key Rules
- Never break prompt caching โ don't change context, tools, or system prompt mid-conversation
- Message role alternation โ never two assistant or two user messages in a row
- Use
get_hermes_home() from hermes_constants for all paths (profile-safe)
- Config values go in
config.yaml, secrets go in .env
- New tools need a
check_fn so they only appear when requirements are met
[IMPORTANT: The user has invoked the "kanban-orchestrator" skill, indicating they want you to follow its instructions. The full skill content is loaded below.]
---
name: kanban-orchestrator
description: Decomposition playbook + anti-temptation rules for an orchestrator profile routing work through Kanban. The "don't do the work yourself" rule and the basic lifecycle are auto-injected into every kanban worker's system prompt; this skill is the deeper playbook when you're specifically playing the orchestrator role.
version: 3.0.0
platforms: [linux, macos, windows]
metadata:
hermes:
tags: [kanban, multi-agent, orchestration, routing]
related_skills: [kanban-worker]
---
Kanban Orchestrator โ Decomposition Playbook
> The core worker lifecycle (including the kanban_create fan-out pattern and the "decompose, don't execute" rule) is auto-injected into every kanban process via the KANBAN_GUIDANCE system-prompt block. This skill is the deeper playbook when you're an orchestrator profile whose whole job is routing.
Profiles are user-configured โ not a fixed roster
Hermes setups vary widely. Some users run a single profile that does everything; some run a small fleet (docker-worker, cron-worker); some run a curated specialist team they've named themselves. There is no default specialist roster โ the orchestrator skill does not know what profiles exist on this machine.
Before fanning out, you must ground the decomposition in the profiles that actually exist. The dispatcher silently fails to spawn unknown assignee names โ it doesn't autocorrect, doesn't suggest, doesn't fall back. So a card assigned to researcher on a setup that only has docker-worker just sits in ready forever.
Step 0: discover available profiles before planning.
Use one of these:
hermes profile list โ prints the table of profiles configured on this machine. Run it through your terminal tool if you have one; otherwise ask the user.
kanban_list(assignee="<some-name>") โ sanity-check a single name. Returns an empty list (rather than an error) for an unknown assignee, so this only confirms a name you're already considering.
- Just ask the user. "What profiles do you have set up?" is a fine first turn when the goal needs more than one specialist.
Cache the result in your working memory for the rest of the conversation. Re-asking every turn wastes a tool call.
When to use the board (vs. just doing the work)
Create Kanban tasks when any of these are true:
1. Multiple specialists are needed. Research + analysis + writing is three profiles.
2. The work should survive a crash or restart. Long-running, recurring, or important.
3. The user might want to interject. Human-in-the-loop at any step.
4. Multiple subtasks can run in parallel. Fan-out for speed.
5. Review / iteration is expected. A reviewer profile loops on drafter output.
6. The audit trail matters. Board rows persist in SQLite forever.
If none of those apply โ it's a small one-shot reasoning task โ use delegate_task instead or answer the user directly.
The anti-temptation rules
Your job description says "route, don't execute." The rules that enforce that:
- Do not execute the work yourself. Your restricted toolset usually doesn't even include terminal/file/code/web for implementation. If you find yourself "just fixing this quickly" โ stop and create a task for the right specialist.
- For any concrete task, create a Kanban task and assign it. Every single time.
- Split multi-lane requests before creating cards. A user prompt can contain several independent workstreams. Extract those lanes first, then create one card per lane instead of bundling unrelated work into a single implementer card.
- Run independent lanes in parallel. If two cards do not need each other's output, leave them unlinked so the dispatcher can fan them out. Link only true data dependencies.
- If no specialist fits the available profiles, ask the user which profile to create or which existing profile to use. Do not invent profile names; the dispatcher will silently drop unknown assignees.
- Decompose, route, and summarize โ that's the whole job.
Exception: micro-UI polish cycles
There is one narrow exception where the orchestrator may execute directly instead of creating Kanban cards: tiny UI-only polish cycles (e.g., adding a CSS class, a theme preview dot, a hover state, a cross-link, or a HUD button) that are purely presentational, require no cross-file logic changes, and fit comfortably inside a single bounded cycle with no need for review or parallel work. If the change is limited to HTML/CSS/JS cosmetics, no other profile has a stake in it, and the user did not ask for a design review, the orchestrator should just edit and publish rather than paying the kanban-overhead tax. This exception does NOT apply to architecture changes, adapter logic, plugin interfaces, or anything that touches the data layer.
Decomposition playbook
Step 1 โ Understand the goal
Ask clarifying questions if the goal is ambiguous. Cheap to ask; expensive to spawn the wrong fleet.
Step 2 โ Sketch the task graph
Before creating anything, draft the graph out loud (in your response to the user). Treat every concrete workstream as a candidate card:
1. Extract the lanes from the request.
2. Map each lane to one of the profiles you discovered in Step 0. If a lane doesn't fit any existing profile, ask the user which to use or create.
3. Decide whether each lane is independent or gated by another lane.
4. Create independent lanes as parallel cards with no parent links.
5. Create synthesis/review/integration cards with parent links to the lanes they depend on.
Examples of prompts that should fan out (using placeholder profile names โ substitute whatever exists on the user's setup):
- "Build an app" โ one card to a design-oriented profile for product/UI direction, one or two cards to engineering profiles for implementation, plus a later integration/review card if the user has a reviewer profile.
- "Fix blockers and check model variants" โ one implementation card for the blocker fixes plus one discovery/research card for config/source verification. A final reviewer card can depend on both.
- "Research docs and implement" โ a docs-research card can run in parallel with a codebase-discovery card; implementation waits only if it truly needs those findings.
- "Analyze this screenshot and find the related code" โ one card to a vision-capable profile for the visual analysis while another searches the codebase.
Words like "also," "finally," or "and" do not automatically imply a dependency. They often mean "make sure this is covered before reporting back." Only link tasks when one card cannot start until another card's output exists.
Show the graph to the user before creating cards. Let them correct it โ including which actual profile name should own each lane.
Step 3 โ Create tasks and link
Use the profile names from Step 0. The example below uses placeholders <profile-A>, <profile-B>, <profile-C> โ replace them with what the user actually has.
t1 = kanban_create(
title="research: Postgres cost vs current",
assignee="<profile-A>", # whichever profile handles research on this setup
body="Compare estimated infrastructure costs, migration costs, and ongoing ops costs over a 3-year window. Sources: AWS/GCP pricing, team time estimates, current Postgres bills from peers.",
tenant=os.environ.get("HERMES_TENANT"),
)["task_id"]
t2 = kanban_create(
title="research: Postgres performance vs current",
assignee="<profile-A>", # same profile, run in parallel
body="Compare query latency, throughput, and scaling characteristics at our expected data volume (~500GB, 10k QPS peak). Sources: benchmark papers, public case studies, pgbench results if easy.",
)["task_id"]
t3 = kanban_create(
title="synthesize migration recommendation",
assignee="<profile-B>", # whichever profile does synthesis/analysis
body="Read the findings from T1 (cost) and T2 (performance). Produce a 1-page recommendation with explicit trade-offs and a go/no-go call.",
parents=[t1, t2],
)["task_id"]
t4 = kanban_create(
title="draft decision memo",
assignee="<profile-C>", # whichever profile drafts user-facing prose
body="Turn the analyst's recommendation into a 2-page memo for the CTO. Match the tone of previous decision memos in the team's knowledge base.",
parents=[t3],
)["task_id"]
parents=[...] gates promotion โ children stay in todo until every parent reaches done, then auto-promote to ready. No manual coordination needed; the dispatcher and dependency engine handle it.
Step 4 โ Complete your own task
If you were spawned as a task yourself (e.g. a planner profile was assigned T0: "investigate Postgres migration"), mark it done with a summary of what you created:
kanban_complete(
summary="decomposed into T1-T4: 2 research lanes in parallel, 1 synthesis on their outputs, 1 prose draft on the recommendation",
metadata={
"task_graph": {
"T1": {"assignee": "<profile-A>", "parents": []},
"T2": {"assignee": "<profile-A>", "parents": []},
"T3": {"assignee": "<profile-B>", "parents": ["T1", "T2"]},
"T4": {"assignee": "<profile-C>", "parents": ["T3"]},
},
},
)
Step 5 โ Report back to the user
Tell them what you created in plain prose, naming the actual profiles you used:
> I've queued 4 tasks:
> - T1 (<profile-A>): cost comparison
> - T2 (<profile-A>): performance comparison, in parallel with T1
> - T3 (<profile-B>): synthesizes T1 + T2 into a recommendation
> - T4 (<profile-C>): turns T3 into a CTO memo
>
> The dispatcher will pick up T1 and T2 now. T3 starts when both finish. You'll get a gateway ping when T4 completes. Use the dashboard or hermes kanban tail <id> to follow along.
Common patterns
Fan-out + fan-in (research โ synthesize): N research-style cards with no parents, one synthesis card with all of them as parents.
Parallel implementation + validation: one implementer card makes the change while one explorer/researcher card verifies config, docs, or source mapping. A reviewer card can depend on both. Do not make the implementer own unrelated verification just because the user mentioned both in one sentence.
Pipeline with gates: planner โ implementer โ reviewer. Each stage's parents=[previous_task]. Reviewer blocks or completes; if reviewer blocks, the operator unblocks with feedback and respawns.
Same-profile queue: N tasks, all assigned to the same profile, no dependencies between them. Dispatcher serializes โ that profile processes them in priority order, accumulating experience in its own memory.
Parallel UI/frontend lanes: When the goal touches multiple independent HTML/CSS/JS files (e.g., a dashboard page and a 2D gather view), fan out to separate subagents per file. Each lane edits its own file, then the orchestrator integrates, fixes cross-file references (theme paths, shared JSON endpoints), and publishes. This avoids merge conflicts in single-file HTML dashboards and keeps each subagent's context focused. See references/parallel-ui-lanes-and-publishing.md for the post-subagent integration checklist and rsync safety notes.
Human-in-the-loop: Any task can kanban_block() to wait for input. Dispatcher respawns after /unblock. The comment thread carries the full context.
Pitfalls
Inventing profile names that don't exist. The dispatcher silently fails to spawn unknown assignees โ the card just sits in ready forever. Always assign to a profile from your Step 0 discovery; ask the user if you're unsure.
Bundling independent lanes into one card. If the user asks for two independent outcomes, create two cards. Example: "fix blockers and check model variants" is not one fixer task; create a fixer/engineer card for the fixes and an explorer/researcher card for the variant check, then optionally gate review on both.
Over-linking because of wording. "Finally check X" may still be parallel with implementation if X is static config, docs, or source discovery. Link it after implementation only when the check depends on the implementation result.
Forgetting dependency links. If the task graph says research -> implement -> review, do not create all tasks as independent ready cards. Use parent links so implement/review cannot run before their inputs exist.
Reassignment vs. new task. If a reviewer blocks with "needs changes," create a NEW task linked from the reviewer's task โ don't re-run the same task with a stern look. The new task is assigned to the original implementer profile.
Argument order for links. kanban_link(parent_id=..., child_id=...) โ parent first. Mixing them up demotes the wrong task to todo.
Ignoring explicit user feedback to keep building infrastructure. When the user says a specific UX issue (legibility, theme switching, movement density) is "immediate priority," treat it as P0 and route it before deeper packaging/architecture work. Infrastructure polish feels productive, but shipping user-visible fixes is what matters. Create cards for the UX feedback first, then resume infrastructure lanes.
Treating status: complete as immutable when user feedback says otherwise. A state.md that says status: complete does not override a user's report that a completion criterion is actually broken. If the user says "theme switching is not working" and the Final Completion Condition requires "working UI theme switcher," the mission is not complete. Reactivate immediately: set status: active, append a reactivation cycle log, and fix the issue. Do not burn cycles on post-complete verification while the user is reporting active defects.
Don't pre-create the whole graph if the shape depends on intermediate findings. If T3's structure depends on what T1 and T2 find, let T3 exist as a "synthesize findings" task whose own first step is to read parent handoffs and plan the rest. Orchestrators can spawn orchestrators.
Tenant inheritance. If HERMES_TENANT is set in your env, pass tenant=os.environ.get("HERMES_TENANT") on every kanban_create call so child tasks stay in the same namespace.
Verifying cross-file references after directory reorganization. When subagents edit HTML/CSS/JS files and the directory structure shifts (e.g., moving files from root into web/dashboard/ and web/gather/), relative asset paths ( themes/default/theme.css, ./ops-data.json) often break. After subagents finish, the orchestrator must grep for href= and src= in moved files and fix relative paths before publishing. Subagents don't know the final publish layout โ the orchestrator does.
Destructive sync wipes needed files. Commands like rsync -av --delete will delete destination files that aren't in the source list. If you publish a directory tree piecemeal (e.g., copy web/dashboard/ first, then web/gather/ separately), --delete on the first rsync will erase the gather files before the second rsync runs. Either list all source paths in a single rsync invocation, or omit --delete and use cp -r / rsync -av without deletion when doing staged copies.
Recovering stuck workers
When a worker profile keeps crashing, hallucinating, or getting blocked by its own mistakes (usually: wrong model, missing skill, broken credential), the kanban dashboard flags the task with a โ badge and opens a Recovery section in the drawer. Three primary actions:
1. Reclaim (or hermes kanban reclaim <task_id>) โ abort the running worker immediately and reset the task to ready. The existing claim TTL is ~15 min; this is the fast path out.
2. Reassign (or hermes kanban reassign <task_id> <new-profile> --reclaim) โ switch the task to a different profile (one that exists on this setup) and let the dispatcher pick it up with a fresh worker.
3. Change profile model โ the dashboard prints a copy-paste hint for hermes -p <profile> model since profile config lives on disk; edit it in a terminal, then Reclaim to retry with the new model.
Hallucination warnings appear on tasks where a worker's kanban_complete(created_cards=[...]) claim included card ids that don't exist or weren't created by the worker's profile (the gate blocks the completion), or where the free-form summary references t_<hex> ids that don't resolve (advisory prose scan, non-blocking). Both produce audit events that persist even after recovery actions โ the trail stays for debugging.
The user has provided the following instruction alongside the skill invocation: [IMPORTANT: You are running as a scheduled cron job. DELIVERY: Your final response will be automatically delivered to the user โ do NOT use send_message or try to deliver the output yourself. Just produce your report/output as your final response and the system handles the rest. SILENT: If there is genuinely nothing new to report, respond with exactly "[SILENT]" (nothing else) to suppress delivery. Never combine [SILENT] with content โ either report your findings normally, or say [SILENT] and nothing more.]
You are the 15-minute Orchestrator for Son's Autonomous Agent Lab v1, reporting to Discord channel ID 1505805763824586952.
Durable state path: /Users/jooho-hermes/.hermes/autonomous-agent-lab/state.md
Working directory for experiment artifacts: /Users/jooho-hermes/.hermes/autonomous-agent-lab/
Preferred published web root: /Users/jooho-hermes/hermes-web/agent-pets/
Top-level directive from Son:
- The project has evolved from a personal dashboard into an INSTALLABLE PRODUCT that external Hermes users can deploy.
- The final target is a self-contained, configurable, publishable solution: "Hermes Pixel Pet Ops Office".
- Do NOT shrink the mission into a small static MVP and autonomously stop.
- The Gather.town-style 2D spatial office is a first-class feature, not a side page.
Latest UX feedback from Son (treat as immediate priority before deeper packaging work):
- Details are hard for a human to understand. Add human-first summaries, plain-language labels, and progressive disclosure: summary first, technical details second.
- Gather Town version has too many agents roaming around. Reduce default movement, add density/speed controls, cluster agents by room/task, and add focus/calm mode.
- Theme switching is not visibly working. Implement real UI theme switcher with persistence and clear visual theme changes.
Key product requirements (installable solution level):
1. Config-driven architecture: all paths, URLs, colors, names, room layouts via config.yaml. No hardcoded references to jooho-hermes.
2. Self-contained package: clear directory structure (src/, web/, config/, docs/, scripts/), install script, requirements.txt.
3. Pluggable data adapter: support multiple backends via plugin architecture.
4. Themeable frontend: CSS variables driven from config, swappable themes, plus a working UI theme switcher.
5. Multi-tenant ready: works for any Hermes instance.
6. Build/Deploy ready: Dockerfile or docker-compose, or clear static-server setup.
7. Documentation: README, architecture docs, configuration reference, contributor guide.
8. Human-comprehensible UX: plain-language summaries and progressive disclosure for technical detail.
9. Gather.town calm mode: adjustable movement density/speed and less chaotic defaults.
10. Versioned releases: CHANGELOG.md, semantic versioning, release packaging.
Mission model:
- Read state.md first before doing anything else.
- If state.md says
status: inactive or has no Current Mission, do not invent work. Return exactly: ๐ก Autonomous Agent Lab ๋๊ธฐ์ค โ Son์ด ํธ๋ฆฌ๊ฑฐ/๋ฏธ์
์ ์ฃผ๋ฉด 15๋ถ ์ฌ์ดํด์ ์์ํฉ๋๋ค.
- If state.md says
status: active, run one bounded 15-minute cycle toward the full installable solution.
- If state.md says
status: complete, verify that the Final Completion Condition in state.md is truly met. If it is not fully met, reactivate or report that state needs correction.
Cycle procedure when active:
1. Read state.md first. Extract current mission, constraints, previous cycle log, and Final Completion Condition.
2. Decide the next smallest useful step toward installable solution quality. Focus on: architecture, configurability, documentation, and clean separation of concerns.
3. Use delegate_task for independent subagent lanes when helpful.
4. Prefer concrete progress: refactor to config-driven, add install scripts, create docs, add Docker support, theme system, plugin architecture.
5. Update state.md with a new cycle log entry before final reporting.
6. Completion rule: only set status: complete when every item under state.md Final Completion Condition is satisfied. A non-installable MVP is not complete.
7. Stop/block only if Son explicitly stops/redirects, a safety boundary is reached, or a hard blocker needs Son's decision.
Link requirement (never forget):
- Every cycle report MUST include at least one direct viewable link to the published dashboard/artifact.
- The canonical URL:
http://hermes-mac-mini.tail46b3c6.ts.net:8099/agent-pets/
- Include gather town URL too:
http://hermes-mac-mini.tail46b3c6.ts.net:8099/agent-pets/gather/
Final Discord message format:
[Autonomous Agent Lab v1 / Cycle N]
๋ชฉํ:
์ํ:
๊ฒฐ๊ณผ:
๊ฒ์ฆ:
๋ค์:
์ํ:
Safety/quality rules:
- Do not handle secrets, passwords, API keys, payment, permission dialogs, or destructive commands.
- Do not claim completion without updating state.md.
- Do not rely on Discord history as durable state.
- Do not spam raw logs; summarize lane outputs and verification.
- Keep working in /Users/jooho-hermes/.hermes/autonomous-agent-lab/ and publish only to /Users/jooho-hermes/hermes-web/agent-pets/ unless the state file says otherwise.
Design/UX priorities:
- Mobile responsiveness is first-class.
- Character animation/movement is desired.
- Every cycle report must include published links.
- This is now a product engineering mission. Architecture, configurability, and documentation matter as much as visuals.
Response
[Autonomous Agent Lab v1 / Cycle 77]
๋ชฉํ:
์์คํ
Python์ PyYAML์ด ์์ด test.shยทvalidate_setup.shยทrefresh_once.sh๊ฐ ์คํจํ๋ ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๊ณ , ์ธ๋ถ ๋ฐฐํฌ์๊ฐ ์ด๋ค Python ํ๊ฒฝ์์๋ ์์ ์ ์ผ๋ก ์คํํ ์ ์๋๋ก ์๋ ์ธํฐํ๋ฆฌํฐ ํ์ง๋ฅผ ์ถ๊ฐํฉ๋๋ค.
์ํ:
refresh_once.sh: ํ๋์ฝ๋ฉ๋ /usr/bin/python3 ์ ๊ฑฐ, find_python() ํจ์ ์ถ๊ฐ (venv โ .venv โ python3 โ python ์์๋ก PyYAML ๋ณด์ interpreter ์๋ ํ์ง)
scripts/test.sh: python3 ํ๋์ฝ๋ฉ 9๊ณณ โ $PYTHON ๋ณ์ํ, ํ
์คํธ ํค๋์ ์ค์ ์ฌ์ฉ Python ๊ฒฝ๋ก ํ์
scripts/validate_setup.sh: python3 ํ๋์ฝ๋ฉ 12๊ณณ โ $PYTHON ๋ณ์ํ, ๊ฒ์ฆ ์ ์ค์ interpreter ๋ฒ์ /๊ฒฝ๋ก ์ถ๋ ฅ
- ์ ์ฒด ์์ฐ publish (
scripts/publish.sh config.yaml)
๊ฒฐ๊ณผ:
- Integration tests: 134/134 passed (์ด์ 130 passed / 4 failed ์์ ์ ์ ํต๊ณผ)
- Setup validation: 21/21 passed, 0 warned, 0 critical
- Adapter ์คํ ์ ์: 32 agents, 15 cron jobs, 20 sessions, 16 events, schema 1.4
ops-data.jsonยทhealth.json ๊ฐฑ์ ์๋ฃ, refresh.err.log ๊ณต๋ฐฑ, LaunchAgent ์ ์ ๋์
๊ฒ์ฆ:
- Zero hardcoded
jooho-hermes references
- Dashboard & Gather Town ํ์ผ ๋๊ธฐํ ํ์ธ
- Publish๋
ops-data.jsonยทhealth.json mtime 60์ด ์ด๋ด ์ ์ ํจ ํ์ธ
๋ค์:
- Son์ด ๋ธ๋ผ์ฐ์ ์์ ๋์๋ณด๋ ์ ์ ํ UX ํผ๋๋ฐฑ 3๊ฐ์ง(ํ
๋ง ์ ํ, Gather calm mode, human-first inspector) ๋ง์กฑ ์ฌ๋ถ ํ์ธ ์์ฒญ
- ํ์ธ ์
status: complete๋ก ์ ํ ๊ฐ๋ฅ
- ์ ํ์ : validate_setup.sh์ adapter stdout ๋ค์ค JSON ๋ผ์ธ ํ์ฑ ๋ฏธ์ธ ๋ณด์
์ํ: ๐ข active (11๊ฐ Final Completion Condition ๋ชจ๋ ์ถฉ์กฑ, Son ๋ธ๋ผ์ฐ์ ํ์ธ ๋๊ธฐ)
๋งํฌ:
- Dashboard: http://hermes-mac-mini.tail46b3c6.ts.net:8099/agent-pets/
- Gather Town: http://hermes-mac-mini.tail46b3c6.ts.net:8099/agent-pets/gather/
|
| 2026-05-20 02-09-55 |
84,445 chars |
2026-05-20_02-09-55.md |
Cron Job: autonomous-agent-lab-v1-orchestrator
Job ID: 35127ff89556
Run Time: 2026-05-20 02:09:55
Schedule: every 15m
Prompt
[IMPORTANT: The user has invoked the "hermes-agent" skill, indicating they want you to follow its instructions. The full skill content is loaded below.]
---
name: hermes-agent
description: "Configure, extend, or contribute to Hermes Agent."
version: 2.1.0
author: Hermes Agent + Teknium
license: MIT
platforms: [linux, macos, windows]
metadata:
hermes:
tags: [hermes, setup, configuration, multi-agent, spawning, cli, gateway, development]
homepage: https://github.com/NousResearch/hermes-agent
related_skills: [claude-code, codex, opencode]
---
Hermes Agent
Hermes Agent is an open-source AI agent framework by Nous Research that runs in your terminal, messaging platforms, and IDEs. It belongs to the same category as Claude Code (Anthropic), Codex (OpenAI), and OpenClaw โ autonomous coding and task-execution agents that use tool calling to interact with your system. Hermes works with any LLM provider (OpenRouter, Anthropic, OpenAI, DeepSeek, local models, and 15+ others) and runs on Linux, macOS, and WSL.
What makes Hermes different:
- Self-improving through skills โ Hermes learns from experience by saving reusable procedures as skills. When it solves a complex problem, discovers a workflow, or gets corrected, it can persist that knowledge as a skill document that loads into future sessions. Skills accumulate over time, making the agent better at your specific tasks and environment.
- Persistent memory across sessions โ remembers who you are, your preferences, environment details, and lessons learned. Pluggable memory backends (built-in, Honcho, Mem0, and more) let you choose how memory works.
- Multi-platform gateway โ the same agent runs on Telegram, Discord, Slack, WhatsApp, Signal, Matrix, Email, and 10+ other platforms with full tool access, not just chat.
- Provider-agnostic โ swap models and providers mid-workflow without changing anything else. Credential pools rotate across multiple API keys automatically.
- Profiles โ run multiple independent Hermes instances with isolated configs, sessions, skills, and memory.
- Extensible โ plugins, MCP servers, custom tools, webhook triggers, cron scheduling, and the full Python ecosystem.
People use Hermes for software development, research, system administration, data analysis, content creation, home automation, and anything else that benefits from an AI agent with persistent context and full system access.
This skill helps you work with Hermes Agent effectively โ setting it up, configuring features, spawning additional agent instances, troubleshooting issues, finding the right commands and settings, and understanding how the system works when you need to extend or contribute to it.
Docs: https://hermes-agent.nousresearch.com/docs/
Quick Start
Install
curl -fsSL https://raw.githubusercontent.com/NousResearch/hermes-agent/main/scripts/install.sh | bash
Interactive chat (default)
hermes
Single query
hermes chat -q "What is the capital of France?"
Setup wizard
hermes setup
Change model/provider
hermes model
Check health
hermes doctor
---
CLI Reference
Global Flags
hermes [flags] [command]
--version, -V Show version
--resume, -r SESSION Resume session by ID or title
--continue, -c [NAME] Resume by name, or most recent session
--worktree, -w Isolated git worktree mode (parallel agents)
--skills, -s SKILL Preload skills (comma-separate or repeat)
--profile, -p NAME Use a named profile
--yolo Skip dangerous command approval
--pass-session-id Include session ID in system prompt
No subcommand defaults to chat.
Chat
hermes chat [flags]
-q, --query TEXT Single query, non-interactive
-m, --model MODEL Model (e.g. anthropic/claude-sonnet-4)
-t, --toolsets LIST Comma-separated toolsets
--provider PROVIDER Force provider (openrouter, anthropic, nous, etc.)
-v, --verbose Verbose output
-Q, --quiet Suppress banner, spinner, tool previews
--checkpoints Enable filesystem checkpoints (/rollback)
--source TAG Session source tag (default: cli)
Configuration
hermes setup [section] Interactive wizard (model|terminal|gateway|tools|agent)
hermes model Interactive model/provider picker
hermes config View current config
hermes config edit Open config.yaml in $EDITOR
hermes config set KEY VAL Set a config value
hermes config path Print config.yaml path
hermes config env-path Print .env path
hermes config check Check for missing/outdated config
hermes config migrate Update config with new options
hermes doctor [--fix] Check dependencies and config
Credential Pools
hermes auth add Interactive credential wizard (oauth, api-key)
hermes auth list [PROVIDER] List pooled credentials
hermes auth remove P INDEX Remove by provider + index
hermes auth reset PROVIDER Clear exhaustion status
hermes logout Clear stored auth
Tools & Skills
hermes tools Interactive tool enable/disable (curses UI)
hermes tools list Show all tools and status
hermes tools enable NAME Enable a toolset
hermes tools disable NAME Disable a toolset
hermes skills list List installed skills
hermes skills search QUERY Search the skills hub
hermes skills install ID Install a skill (ID can be a hub identifier OR a direct https://โฆ/SKILL.md URL; pass --name to override when frontmatter has no name)
hermes skills inspect ID Preview without installing
hermes skills config Enable/disable skills per platform
hermes skills check Check for updates
hermes skills update Update outdated skills
hermes skills uninstall N Remove a hub skill
hermes skills publish PATH Publish to registry
hermes skills browse Browse all available skills
hermes skills tap add REPO Add a GitHub repo as skill source
MCP Servers
hermes mcp serve Run Hermes as an MCP server
hermes mcp add NAME Add an MCP server (--url or --command)
hermes mcp remove NAME Remove an MCP server
hermes mcp list List configured servers
hermes mcp test NAME Test connection
hermes mcp configure NAME Toggle tool selection
Gateway (Messaging Platforms)
hermes gateway run Start gateway foreground
hermes gateway install Install as background service
hermes gateway start/stop Control the service
hermes gateway restart Restart the service
hermes gateway status Check status
hermes gateway setup Configure platforms
Supported platforms: Telegram, Discord, Slack, WhatsApp, Signal, Email, SMS, Matrix, Mattermost, Home Assistant, DingTalk, Feishu, WeCom, BlueBubbles (iMessage), Weixin (WeChat), API Server, Webhooks. Open WebUI connects via the API Server adapter.
Platform docs: https://hermes-agent.nousresearch.com/docs/user-guide/messaging/
Discord-specific walkthrough (token, intents, service install, access control): see references/discord-gateway-setup.md in this skill.
- Per-channel personas and skill bindings: see
references/gateway-channel-personas.md (works on Discord, Slack, Telegram, Mattermost, Matrix).
- For long-running Discord-first operations, purpose-specific channel routing, periodic summaries, weekly Dreaming/audit reports, and log-safety patterns: see
references/discord-operating-planes.md.
- For broad Hermes/LifeOS/SQAF ecosystem audits (cron inventory, live services, dashboards, provider/model warnings, and control-plane gaps), see
references/ecosystem-audit.md.
Sessions
hermes sessions list List recent sessions
hermes sessions browse Interactive picker
hermes sessions export OUT Export to JSONL
hermes sessions rename ID T Rename a session
hermes sessions delete ID Delete a session
hermes sessions prune Clean up old sessions (--older-than N days)
hermes sessions stats Session store statistics
For browser-based viewing of existing Hermes CLI/Discord/cron session transcripts, prefer a lightweight static export from ~/.hermes/state.db into a private web root instead of assuming Open WebUI can browse Hermes' native session store. See references/hermes-session-static-web-viewer.md for the SQLite schema, static HTML export workflow, redaction/truncation cautions, and the user's Mac mini deployment (/hermes-sessions/ under the Tailscale-only ~/hermes-web site).
For cron job execution history, the same static-export pattern applies to ~/.hermes/cron/jobs.json and ~/.hermes/cron/output/{job_id}/*.md. See references/cron-history-web-viewer.md for the cron data model, schedule-dict pitfall, and the user's deployed /cron-history/ dashboard.
Cron Jobs
hermes cron list List jobs (--all for disabled)
hermes cron create SCHED Create: '30m', 'every 2h', '0 9 *'
hermes cron edit ID Edit schedule, prompt, delivery
hermes cron pause/resume ID Control job state
hermes cron run ID Trigger on next tick
hermes cron remove ID Delete a job
hermes cron status Scheduler status
For bounded autonomous lab/orchestrator cron jobs that use file-based state, subagent lanes, artifact publishing, and status transitions (active โ complete/blocked/inactive), see references/autonomous-agent-lab-cron-cycle.md. A reusable verification script template lives at scripts/verify-completion-template.py.
For a worked example of evolving an autonomous lab into a config-driven, themeable, Docker-ready installable product, see references/autonomous-lab-product-architecture.md. For CI, integration testing, pluggable adapter architecture, bounded cycle orchestration, and post-productization patterns, see references/product-maturity-patterns.md.
For the final completion verification checklist โ the explicit audit pattern to run before marking status: complete on an installable-solution mission, see references/autonomous-lab-completion-verification.md.
For the reactivation protocol when a completed lab receives new P0 feedback or the user contradicts a completion claim, see references/autonomous-lab-reactivation-protocol.md.
For the config/CHANGELOG version drift pitfall that occurs when autonomous labs evolve over many cycles, and for the related source vs. published file drift problem where the live web root diverges from the project source, see references/autonomous-lab-version-drift.md.
For adding historical trend tracking (SQLite-backed agent status transitions + vanilla JS SVG sparklines) to an autonomous lab dashboard, see references/history-tracking-sparkline-pattern.md.
For preventing unbounded SQLite growth in long-running labs, see references/autonomous-lab-data-retention.md โ covers automatic per-refresh pruning and a standalone manual prune utility.
For reusable dashboard UX patterns (onboarding tours, data freshness badges, keyboard shortcuts, progressive disclosure inspectors, cross-linking between views), see references/dashboard-ux-patterns.md.
For the daily operational briefing modal โ a one-screen human-first summary of agent counts, blocked work, recent events, health status, and upcoming cron schedules โ see references/daily-briefing-modal.md.
For the aggressive human-first inspector refinement โ when users report that details are hard to understand and the fix is to strip technical labels from the default view โ see references/progressive-disclosure-human-first.md.
For programmatic verification of CSS custom-property theme systems โ catching scoping bugs, confirming theme distinctness, and validating JS switching logic โ see references/theme-system-verification.md.
- For Son's Discord-first autonomous experiments where a channel hosts a repeated multi-agent loop, use the Autonomous Discord Agent Lab pattern: create file-based durable state, a paused cron orchestrator delivered to
discord:<channel_id>, then activate it from a user mission trigger. See references/autonomous-discord-agent-lab.md.
- For verifying that a release package (
tar.gz) is actually installable by third parties and contains no stale artifacts or hardcoded references, see references/release-package-verification.md and the reusable script at scripts/release-verify.sh.
Webhooks
hermes webhook subscribe N Create route at /webhooks/<name>
hermes webhook list List subscriptions
hermes webhook remove NAME Remove a subscription
hermes webhook test NAME Send a test POST
Profiles
hermes profile list List all profiles
hermes profile create NAME Create (--clone, --clone-all, --clone-from)
hermes profile use NAME Set sticky default
hermes profile delete NAME Delete a profile
hermes profile show NAME Show details
hermes profile alias NAME Manage wrapper scripts
hermes profile rename A B Rename a profile
hermes profile export NAME Export to tar.gz
hermes profile import FILE Import from archive
Credential Pools
hermes auth add Interactive credential wizard
hermes auth list [PROVIDER] List pooled credentials
hermes auth remove P INDEX Remove by provider + index
hermes auth reset PROVIDER Clear exhaustion status
Other
hermes insights [--days N] Usage analytics
hermes update Update to latest version
hermes pairing list/approve/revoke DM authorization
hermes plugins list/install/remove Plugin management
hermes honcho setup/status Honcho memory integration (requires honcho plugin)
hermes memory setup/status/off Memory provider config
hermes completion bash|zsh Shell completions
hermes acp ACP server (IDE integration)
hermes claw migrate Migrate from OpenClaw
hermes uninstall Uninstall Hermes
---
Slash Commands (In-Session)
Type these during an interactive chat session. New commands land fairly
often; if something below looks stale, run /help in-session for the
authoritative list or see the [live slash commands reference](https://hermes-agent.nousresearch.com/docs/reference/slash-commands).
The registry of record is hermes_cli/commands.py โ every consumer
(autocomplete, Telegram menu, Slack mapping, /help) derives from it.
Session Control
/new (/reset) Fresh session
/clear Clear screen + new session (CLI)
/retry Resend last message
/undo Remove last exchange
/title [name] Name the session
/compress Manually compress context
/stop Kill background processes
/rollback [N] Restore filesystem checkpoint
/snapshot [sub] Create or restore state snapshots of Hermes config/state (CLI)
/background <prompt> Run prompt in background
/queue <prompt> Queue for next turn
/steer <prompt> Inject a message after the next tool call without interrupting
/agents (/tasks) Show active agents and running tasks
/resume [name] Resume a named session
/goal [text|sub] Set a standing goal Hermes works on across turns until achieved
(subcommands: status, pause, resume, clear)
/redraw Force a full UI repaint (CLI)
Configuration
/config Show config (CLI)
/model [name] Show or change model
/personality [name] Set personality
/reasoning [level] Set reasoning (none|minimal|low|medium|high|xhigh|show|hide)
/verbose Cycle: off โ new โ all โ verbose
/voice [on|off|tts] Voice mode
/yolo Toggle approval bypass
/busy [sub] Control what Enter does while Hermes is working (CLI)
(subcommands: queue, steer, interrupt, status)
/indicator [style] Pick the TUI busy-indicator style (CLI)
(styles: kaomoji, emoji, unicode, ascii)
/footer [on|off] Toggle gateway runtime-metadata footer on final replies
/skin [name] Change theme (CLI)
/statusbar Toggle status bar (CLI)
Tools & Skills
/tools Manage tools (CLI)
/toolsets List toolsets (CLI)
/skills Search/install skills (CLI)
/skill <name> Load a skill into session
/reload-skills Re-scan ~/.hermes/skills/ for added/removed skills
/reload Reload .env variables into the running session (CLI)
/reload-mcp Reload MCP servers
/cron Manage cron jobs (CLI)
/curator [sub] Background skill maintenance (status, run, pin, archive, โฆ)
/kanban [sub] Multi-profile collaboration board (tasks, links, comments)
/plugins List plugins (CLI)
Gateway
/approve Approve a pending command (gateway)
/deny Deny a pending command (gateway)
/restart Restart gateway (gateway)
/sethome Set current chat as home channel (gateway)
/update Update Hermes to latest (gateway)
/topic [sub] Enable or inspect Telegram DM topic sessions (gateway)
/platforms (/gateway) Show platform connection status (gateway)
Utility
/branch (/fork) Branch the current session
/fast Toggle priority/fast processing
/browser Open CDP browser connection
/history Show conversation history (CLI)
/save Save conversation to file (CLI)
/copy [N] Copy the last assistant response to clipboard (CLI)
/paste Attach clipboard image (CLI)
/image Attach local image file (CLI)
Info
/help Show commands
/commands [page] Browse all commands (gateway)
/usage Token usage
/insights [days] Usage analytics
/gquota Show Google Gemini Code Assist quota usage (CLI)
/status Session info (gateway)
/profile Active profile info
/debug Upload debug report (system info + logs) and get shareable links
Exit
/quit (/exit, /q) Exit CLI
---
Key Paths & Config
~/.hermes/config.yaml Main configuration
~/.hermes/.env API keys and secrets
$HERMES_HOME/skills/ Installed skills
~/.hermes/sessions/ Session transcripts
~/.hermes/logs/ Gateway and error logs
~/.hermes/auth.json OAuth tokens and credential pools
~/.hermes/hermes-agent/ Source code (if git-installed)
Profiles use ~/.hermes/profiles/<name>/ with the same layout.
Config Sections
Edit with hermes config edit or hermes config set section.key value.
| Section | Key options |
|---------|-------------|
| model | default, provider, base_url, api_key, context_length |
| agent | max_turns (90), tool_use_enforcement |
| terminal | backend (local/docker/ssh/modal), cwd, timeout (180) |
| compression | enabled, threshold (0.50), target_ratio (0.20) |
| display | skin, tool_progress, show_reasoning, show_cost |
| stt | enabled, provider (local/groq/openai/mistral) |
| tts | provider (edge/elevenlabs/openai/minimax/mistral/neutts) |
| memory | memory_enabled, user_profile_enabled, provider |
| security | tirith_enabled, website_blocklist |
| delegation | model, provider, base_url, api_key, max_iterations (50), reasoning_effort |
| checkpoints | enabled, max_snapshots (50) |
| fallback_model | provider, model, base_url, key_env |
Fallback Providers
Hermes can automatically fail over to a backup provider:model when the primary is unavailable. This is turn-scoped โ each new user message starts with the primary restored; fallback only activates mid-turn when the primary fails.
Configuration ( ~/.hermes/config.yaml):
fallback_model:
provider: opencode-go
model: kimi-k2.6
Or use the interactive manager:
hermes fallback add # interactive picker
hermes fallback list # show fallback chain
hermes fallback remove # remove by index
Legacy note: fallback_model (singular) is the legacy single-fallback key. fallback_providers (list) supports multiple ordered fallbacks. When both exist, fallback_providers takes priority.
Trigger conditions (after exhausting retries where applicable):
- Rate limits (HTTP 429)
- Server errors (HTTP 500, 502, 503)
- Auth failures (HTTP 401, 403) โ immediately
- Not found (HTTP 404) โ immediately
- Invalid / empty responses repeatedly
Supported providers include all standard providers (OpenRouter, Anthropic, OpenCode Go/ Zen, Kimi, etc.) plus custom endpoints with base_url + key_env. Full provider docs: https://hermes-agent.nousresearch.com/docs/integrations/providers
Limitations:
- Subagent delegation does not inherit fallback config
- Cron jobs do not use fallback (use per-job provider/model overrides)
- Auxiliary tasks (vision, compression, etc.) use their own
auxiliary.* provider chain
For a deep-dive with worked examples and model lists, see references/fallback-providers.md.
Full config reference: https://hermes-agent.nousresearch.com/docs/user-guide/configuration
Providers
20+ providers supported. Set via hermes model or hermes setup.
| Provider | Auth | Key env var |
|----------|------|-------------|
| OpenRouter | API key | OPENROUTER_API_KEY |
| Anthropic | API key | ANTHROPIC_API_KEY |
| Nous Portal | OAuth | hermes auth |
| OpenAI Codex | OAuth | hermes auth |
| GitHub Copilot | Token | COPILOT_GITHUB_TOKEN |
| Google Gemini | API key | GOOGLE_API_KEY or GEMINI_API_KEY |
| DeepSeek | API key | DEEPSEEK_API_KEY |
| xAI / Grok | API key | XAI_API_KEY |
| Hugging Face | Token | HF_TOKEN |
| Z.AI / GLM | API key | GLM_API_KEY |
| MiniMax | API key | MINIMAX_API_KEY |
| MiniMax CN | API key | MINIMAX_CN_API_KEY |
| Kimi / Moonshot | API key | KIMI_API_KEY |
| Alibaba / DashScope | API key | DASHSCOPE_API_KEY |
| Xiaomi MiMo | API key | XIAOMI_API_KEY |
| Kilo Code | API key | KILOCODE_API_KEY |
| AI Gateway (Vercel) | API key | AI_GATEWAY_API_KEY |
| OpenCode Zen | API key | OPENCODE_ZEN_API_KEY |
| OpenCode Go | API key | OPENCODE_GO_API_KEY |
| Qwen OAuth | OAuth | hermes auth add qwen-oauth |
| Custom endpoint | Config | model.base_url + model.api_key in config.yaml |
| GitHub Copilot ACP | External | COPILOT_CLI_PATH or Copilot CLI |
Full provider docs: https://hermes-agent.nousresearch.com/docs/integrations/providers
Toolsets
Enable/disable via hermes tools (interactive) or hermes tools enable/disable NAME.
| Toolset | What it provides |
|---------|-----------------|
| web | Web search and content extraction |
| search | Web search only (subset of web) |
| browser | Browser automation (Browserbase, Camofox, or local Chromium) |
| terminal | Shell commands and process management |
| file | File read/write/search/patch |
| code_execution | Sandboxed Python execution |
| vision | Image analysis |
| image_gen | AI image generation |
| video | Video analysis and generation |
| tts | Text-to-speech |
| skills | Skill browsing and management |
| memory | Persistent cross-session memory |
| session_search | Search past conversations |
| delegation | Subagent task delegation |
| cronjob | Scheduled task management |
| clarify | Ask user clarifying questions |
| messaging | Cross-platform message sending |
| todo | In-session task planning and tracking |
| kanban | Multi-agent work-queue tools (gated to workers) |
| debugging | Extra introspection/debug tools (off by default) |
| safe | Minimal, low-risk toolset for locked-down sessions |
| spotify | Spotify playback and playlist control |
| homeassistant | Smart home control (off by default) |
| discord | Discord integration tools |
| discord_admin | Discord admin/moderation tools |
| feishu_doc | Feishu (Lark) document tools |
| feishu_drive | Feishu (Lark) drive tools |
| yuanbao | Yuanbao integration tools |
| rl | Reinforcement learning tools (off by default) |
| moa | Mixture of Agents (off by default) |
Full enumeration lives in toolsets.py as the TOOLSETS dict; _HERMES_CORE_TOOLS is the default bundle most platforms inherit from.
Tool changes take effect on /reset (new session). They do NOT apply mid-conversation to preserve prompt caching.
---
Security & Privacy Toggles
Common "why is Hermes doing X to my output / tool calls / commands?" toggles โ and the exact commands to change them. Most of these need a fresh session (/reset in chat, or start a new hermes invocation) because they're read once at startup.
Secret redaction in tool output
Secret redaction is off by default โ tool output (terminal stdout, read_file, web content, subagent summaries, etc.) passes through unmodified. If the user wants Hermes to auto-mask strings that look like API keys, tokens, and secrets before they enter the conversation context and logs:
hermes config set security.redact_secrets true # enable globally
Restart required. security.redact_secrets is snapshotted at import time โ toggling it mid-session (e.g. via export HERMES_REDACT_SECRETS=true from a tool call) will NOT take effect for the running process. Tell the user to run hermes config set security.redact_secrets true in a terminal, then start a new session. This is deliberate โ it prevents an LLM from flipping the toggle on itself mid-task.
Disable again with:
hermes config set security.redact_secrets false
PII redaction in gateway messages
Separate from secret redaction. When enabled, the gateway hashes user IDs and strips phone numbers from the session context before it reaches the model:
hermes config set privacy.redact_pii true # enable
hermes config set privacy.redact_pii false # disable (default)
Command approval prompts
By default (approvals.mode: manual), Hermes prompts the user before running shell commands flagged as destructive (rm -rf, git reset --hard, etc.). The modes are:
manual โ always prompt (default)
smart โ use an auxiliary LLM to auto-approve low-risk commands, prompt on high-risk
off โ skip all approval prompts (equivalent to --yolo)
hermes config set approvals.mode smart # recommended middle ground
hermes config set approvals.mode off # bypass everything (not recommended)
Per-invocation bypass without changing config:
hermes --yolo โฆ
export HERMES_YOLO_MODE=1
Note: YOLO / approvals.mode: off does NOT turn off secret redaction. They are independent.
Shell hooks allowlist
Some shell-hook integrations require explicit allowlisting before they fire. Managed via ~/.hermes/shell-hooks-allowlist.json โ prompted interactively the first time a hook wants to run.
Disabling the web/browser/image-gen tools
To keep the model away from network or media tools entirely, open hermes tools and toggle per-platform. Takes effect on next session (/reset). See the Tools & Skills section above.
---
Voice & Transcription
STT (Voice โ Text)
Voice messages from messaging platforms are auto-transcribed.
Provider priority (auto-detected):
1. Local faster-whisper โ free, no API key: pip install faster-whisper
2. Groq Whisper โ free tier: set GROQ_API_KEY
3. OpenAI Whisper โ paid: set VOICE_TOOLS_OPENAI_KEY
4. Mistral Voxtral โ set MISTRAL_API_KEY
Config:
stt:
enabled: true
provider: local # local, groq, openai, mistral
local:
model: base # tiny, base, small, medium, large-v3
TTS (Text โ Voice)
| Provider | Env var | Free? |
|----------|---------|-------|
| Edge TTS | None | Yes (default) |
| ElevenLabs | ELEVENLABS_API_KEY | Free tier |
| OpenAI | VOICE_TOOLS_OPENAI_KEY | Paid |
| MiniMax | MINIMAX_API_KEY | Paid |
| Mistral (Voxtral) | MISTRAL_API_KEY | Paid |
| NeuTTS (local) | None (pip install neutts[all] + espeak-ng) | Free |
Voice commands: /voice on (voice-to-voice), /voice tts (always voice), /voice off.
---
Spawning Additional Hermes Instances
Run additional Hermes processes as fully independent subprocesses โ separate sessions, tools, and environments.
When to Use This vs delegate_task
| | delegate_task | Spawning hermes process |
|-|-----------------|--------------------------|
| Isolation | Separate conversation, shared process | Fully independent process |
| Duration | Minutes (bounded by parent loop) | Hours/days |
| Tool access | Subset of parent's tools | Full tool access |
| Interactive | No | Yes (PTY mode) |
| Use case | Quick parallel subtasks | Long autonomous missions |
One-Shot Mode
terminal(command="hermes chat -q 'Research GRPO papers and write summary to ~/research/grpo.md'", timeout=300)
Background for long tasks:
terminal(command="hermes chat -q 'Set up CI/CD for ~/myapp'", background=true)
Interactive PTY Mode (via tmux)
Hermes uses prompt_toolkit, which requires a real terminal. Use tmux for interactive spawning:
Start
terminal(command="tmux new-session -d -s agent1 -x 120 -y 40 'hermes'", timeout=10)
Wait for startup, then send a message
terminal(command="sleep 8 && tmux send-keys -t agent1 'Build a FastAPI auth service' Enter", timeout=15)
Read output
terminal(command="sleep 20 && tmux capture-pane -t agent1 -p", timeout=5)
Send follow-up
terminal(command="tmux send-keys -t agent1 'Add rate limiting middleware' Enter", timeout=5)
Exit
terminal(command="tmux send-keys -t agent1 '/exit' Enter && sleep 2 && tmux kill-session -t agent1", timeout=10)
Multi-Agent Coordination
Agent A: backend
terminal(command="tmux new-session -d -s backend -x 120 -y 40 'hermes -w'", timeout=10)
terminal(command="sleep 8 && tmux send-keys -t backend 'Build REST API for user management' Enter", timeout=15)
Agent B: frontend
terminal(command="tmux new-session -d -s frontend -x 120 -y 40 'hermes -w'", timeout=10)
terminal(command="sleep 8 && tmux send-keys -t frontend 'Build React dashboard for user management' Enter", timeout=15)
Check progress, relay context between them
terminal(command="tmux capture-pane -t backend -p | tail -30", timeout=5)
terminal(command="tmux send-keys -t frontend 'Here is the API schema from the backend agent: ...' Enter", timeout=5)
Session Resume
Resume most recent session
terminal(command="tmux new-session -d -s resumed 'hermes --continue'", timeout=10)
Resume specific session
terminal(command="tmux new-session -d -s resumed 'hermes --resume 20260225_143052_a1b2c3'", timeout=10)
Tips
- Prefer
delegate_task for quick subtasks โ less overhead than spawning a full process
- Use
-w (worktree mode) when spawning agents that edit code โ prevents git conflicts
- Set timeouts for one-shot mode โ complex tasks can take 5-10 minutes
- Use
hermes chat -q for fire-and-forget โ no PTY needed
- Use tmux for interactive sessions โ raw PTY mode has
\r vs \n issues with prompt_toolkit
- For scheduled tasks, use the
cronjob tool instead of spawning โ handles delivery and retry
---
Durable & Background Systems
Four systems run alongside the main conversation loop. Quick reference
here; full developer notes live in AGENTS.md, user-facing docs under
website/docs/user-guide/features/.
Delegation (delegate_task)
Synchronous subagent spawn โ the parent waits for the child's summary
before continuing its own loop. Isolated context + terminal session.
- Single:
delegate_task(goal, context, toolsets).
- Batch:
delegate_task(tasks=[{goal, ...}, ...]) runs children in
parallel, capped by delegation.max_concurrent_children (default 3).
- Roles:
leaf (default; cannot re-delegate) vs orchestrator
(can spawn its own workers, bounded by delegation.max_spawn_depth).
- Not durable. If the parent is interrupted, the child is
cancelled. For work that must outlive the turn, use cronjob or
terminal(background=True, notify_on_complete=True).
Config: delegation.* in config.yaml.
Tuning max_concurrent_children
Default is 3. Rule of thumb for raising it:
- Light tasks (web search, file grep): up to
6-8
- Medium tasks (code execution, browser):
4-5
- Heavy tasks (builds, large data):
2-3
- Actual bottleneck is usually the API rate limit, not local CPU/RAM. On a 10-core M4 with 16GB RAM, CPU is rarely the constraint.
- Formula: start at
5, raise only if profiling shows idle time between API responses.
Cron (scheduled jobs)
Durable scheduler โ cron/jobs.py + cron/scheduler.py. Drive it via
the cronjob tool, the hermes cron CLI (list, add, edit,
pause, resume, run, remove), or the /cron slash command.
- Schedules: duration (
"30m", "2h"), "every" phrase
( "every monday 9am"), 5-field cron ( "0 9 *"), or ISO timestamp.
- Per-job knobs:
skills, model/provider override, script
(pre-run data collection; no_agent=True makes the script the whole
job), context_from (chain job A's output into job B), workdir
(run in a specific dir with its AGENTS.md / CLAUDE.md loaded),
multi-platform delivery.
- Invariants: 3-minute hard interrupt per run,
.tick.lock file
prevents duplicate ticks across processes, cron sessions pass
skip_memory=True by default, and cron deliveries are framed with a
header/footer instead of being mirrored into the target gateway
session (keeps role alternation intact).
User docs: https://hermes-agent.nousresearch.com/docs/user-guide/features/cron
Curator (skill lifecycle)
Background maintenance for agent-created skills. Tracks usage, marks
idle skills stale, archives stale ones, keeps a pre-run tar.gz backup
so nothing is lost.
- CLI:
hermes curator <verb> โ status, run, pause, resume,
pin, unpin, archive, restore, prune, backup, rollback.
- Slash:
/curator <subcommand> mirrors the CLI.
- Scope: only touches skills with
created_by: "agent" provenance.
Bundled + hub-installed skills are off-limits. Never deletes โ
max destructive action is archive. Pinned skills are exempt from
every auto-transition and every LLM review pass.
- Telemetry: sidecar at
~/.hermes/skills/.usage.json holds
per-skill use_count, view_count, patch_count,
last_activity_at, state, pinned.
Config: curator.* (enabled, interval_hours, min_idle_hours,
stale_after_days, archive_after_days, backup.*).
User docs: https://hermes-agent.nousresearch.com/docs/user-guide/features/curator
Dreaming (periodic memory/skill consolidation)
For Anthropic-style "dreaming" workflows, combine cron + session_search + memory + skills + curator into a scheduled review loop. Start with a weekly, proposal-only report that audits recent sessions, repeated user corrections, memory conflicts, skill patch candidates, and cron/automation improvements. Do not automatically delete/replace memory or patch/archive skills unless the user explicitly approves the proposed changes. See references/weekly-dreaming-routine.md for the recommended prompt, report format, safety policy, and cron creation pattern.
Kanban (multi-agent work queue)
Durable SQLite board for multi-profile / multi-worker collaboration.
Users drive it via hermes kanban <verb>; dispatcher-spawned workers
see a focused kanban_* toolset gated by HERMES_KANBAN_TASK so the
schema footprint is zero outside worker processes.
- CLI verbs (common):
init, create, list (alias ls),
show, assign, link, unlink, comment, complete, block,
unblock, archive, tail. Less common: watch, stats, runs,
log, dispatch, daemon, gc.
- Worker toolset:
kanban_show, kanban_complete, kanban_block,
kanban_heartbeat, kanban_comment, kanban_create, kanban_link.
- Dispatcher runs inside the gateway by default
( kanban.dispatch_in_gateway: true) โ reclaims stale claims,
promotes ready tasks, atomically claims, spawns assigned profiles.
Auto-blocks a task after ~5 consecutive spawn failures.
- Isolation: board is the hard boundary (workers get
HERMES_KANBAN_BOARD pinned in env); tenant is a soft namespace
within a board for workspace-path + memory-key isolation.
User docs: https://hermes-agent.nousresearch.com/docs/user-guide/features/kanban
Log Relay (Hermes โ Discord)
A background Python script that tails ~/.hermes/logs/*.log and batches lines to a Discord channel. Includes session-ID extraction, rate-limit handling, and auto-restart via launchd/systemd. Useful for remote monitoring and audit trails.
- Reference:
references/discord-log-relay.md โ full setup, tuning, macOS/Linux service install, pitfalls.
- Template:
templates/discord-log-relay.py โ copy, set CHANNEL_ID, and deploy.
- Discord operations:
references/discord-operating-planes.md โ channel-purpose routing, periodic-summary vs Dreaming report formats, and safety/cost notes for Discord-first Hermes deployments.
Key pitfall: ask the user about batch frequency upfront rather than defaulting to real-time streaming. Most users prefer 10-minute or hourly batches. High-volume raw logs should be batched, summarized, or stored out-of-band; avoid Discord message storms during error loops.
Weekly Dreaming / Memory Curation
For long-running Hermes deployments, users may want an Anthropic-style "Dreaming" loop: a scheduled review that consolidates experience, proposes memory/skill/cron changes, and identifies what to keep, weaken, archive, or delete. Hermes has the building blocks (sessions, session_search, memory, skills, curator, cron), but the safe default is proposal mode:
1. Inspect recent usage and sessions.
2. Extract repeated success patterns, failure patterns, and user corrections.
3. Propose memory updates/removals without applying them silently.
4. Propose skill patches/archive candidates and cron/reporting improvements.
5. End with explicit approval checkboxes.
Do not silently rewrite or delete memory/skills from a Dreaming report unless the user explicitly authorized automatic application. See references/discord-operating-planes.md for a report template and routing heuristics.
---
Windows-Specific Quirks
Hermes runs natively on Windows (PowerShell, cmd, Windows Terminal, git-bash
mintty, VS Code integrated terminal). Most of it just works, but a handful
of differences between Win32 and POSIX have bitten us โ document new ones
here as you hit them so the next person (or the next session) doesn't
rediscover them from scratch.
Input / Keybindings
Alt+Enter doesn't insert a newline. Windows Terminal intercepts Alt+Enter
at the terminal layer to toggle fullscreen โ the keystroke never reaches
prompt_toolkit. Use Ctrl+Enter instead. Windows Terminal delivers
Ctrl+Enter as LF ( c-j), distinct from plain Enter ( c-m / CR), and the
CLI binds c-j to newline insertion on win32 only (see
_bind_prompt_submit_keys + the Windows-only c-j binding in cli.py).
Side effect: the raw Ctrl+J keystroke also inserts a newline on Windows โ
unavoidable, because Windows Terminal collapses Ctrl+Enter and Ctrl+J to
the same keycode at the Win32 console API layer. No conflicting binding
existed for Ctrl+J on Windows, so this is a harmless side effect.
mintty / git-bash behaves the same (fullscreen on Alt+Enter) unless you
disable Alt+Fn shortcuts in Options โ Keys. Easier to just use Ctrl+Enter.
Diagnosing keybindings. Run python scripts/keystroke_diagnostic.py
(repo root) to see exactly how prompt_toolkit identifies each keystroke
in the current terminal. Answers questions like "does Shift+Enter come
through as a distinct key?" (almost never โ most terminals collapse it
to plain Enter) or "what byte sequence is my terminal sending for
Ctrl+Enter?" This is how the Ctrl+Enter = c-j fact was established.
Config / Files
HTTP 400 "No models provided" on first run. config.yaml was saved
with a UTF-8 BOM (common when Windows apps write it). Re-save as UTF-8
without BOM. hermes config edit writes without BOM; manual edits in
Notepad are the usual culprit.
execute_code / Sandbox
WinError 10106 ("The requested service provider could not be loaded
or initialized") from the sandbox child process โ it can't create an
AF_INET socket, so the loopback-TCP RPC fallback fails before
connect(). Root cause is usually not a broken Winsock LSP; it's
Hermes's own env scrubber dropping SYSTEMROOT / WINDIR / COMSPEC
from the child env. Python's socket module needs SYSTEMROOT to locate
mswsock.dll. Fixed via the _WINDOWS_ESSENTIAL_ENV_VARS allowlist in
tools/code_execution_tool.py. If you still hit it, echo os.environ
inside an execute_code block to confirm SYSTEMROOT is set. Full
diagnostic recipe in references/execute-code-sandbox-env-windows.md.
Testing / Contributing
scripts/run_tests.sh doesn't work as-is on Windows โ it looks for
POSIX venv layouts ( .venv/bin/activate). The Hermes-installed venv at
venv/Scripts/ has no pip or pytest either (stripped for install size).
Workaround: install pytest + pytest-xdist + pyyaml into a system Python
3.11 user site, then invoke pytest directly with PYTHONPATH set:
"/c/Program Files/Python311/python" -m pip install --user pytest pytest-xdist pyyaml
export PYTHONPATH="$(pwd)"
"/c/Program Files/Python311/python" -m pytest tests/foo/test_bar.py -v --tb=short -n 0
Use -n 0, not -n 4 โ pyproject.toml's default addopts already
includes -n, and the wrapper's CI-parity guarantees don't apply off POSIX.
POSIX-only tests need skip guards. Common markers already in the codebase:
- Symlinks โ elevated privileges on Windows
0o600 file modes โ POSIX mode bits not enforced on NTFS by default
signal.SIGALRM โ Unix-only (see tests/conftest.py::_enforce_test_timeout)
- Winsock / Windows-specific regressions โ
@pytest.mark.skipif(sys.platform != "win32", ...)
Use the existing skip-pattern style (sys.platform == "win32" or
sys.platform.startswith("win")) to stay consistent with the rest of the
suite.
Path / Filesystem
Line endings. Git may warn LF will be replaced by CRLF the next time
Git touches it. Cosmetic โ the repo's .gitattributes normalizes. Don't
let editors auto-convert committed POSIX-newline files to CRLF.
Forward slashes work almost everywhere. C:/Users/... is accepted by
every Hermes tool and most Windows APIs. Prefer forward slashes in code
and logs โ avoids shell-escaping backslashes in bash.
---
Troubleshooting
Voice not working
1. Check stt.enabled: true in config.yaml
2. Verify provider: pip install faster-whisper or set API key
3. In gateway: /restart. In CLI: exit and relaunch.
Tool not available
1. hermes tools โ check if toolset is enabled for your platform
2. Some tools need env vars (check .env)
3. /reset after enabling tools
Model/provider issues
1. hermes doctor โ check config and dependencies
2. hermes auth add <provider> โ re-authenticate OAuth providers (use --type oauth)
3. Check .env has the right API key
4. Copilot 403: gh auth login tokens do NOT work for Copilot API. You must use the Copilot-specific OAuth device code flow via hermes model โ GitHub Copilot.
Changes not taking effect
- Tools/skills:
/reset starts a new session with updated toolset
- Config changes: In gateway:
/restart. In CLI: exit and relaunch.
- Code changes: Restart the CLI or gateway process
Deployed web dashboard shows stale CSS or theme changes
- Browser cache: Add
?v=N cache-busting query strings to CSS/JS/theme links in HTML.
- Service Worker cache: Bump
CACHE_NAME in sw.js to invalidate old shell caches.
- Automated bump script: For projects with multiple HTML entry points (dashboard, gather, etc.), use
scripts/bump-build.py to atomically update all build badges, cache-busting query strings, and service worker cache names in one command. See references/autonomous-lab-version-drift.md for usage.
- Data freshness: Use
fetch(url, {cache:'no-store'}) for live JSON feeds.
- Auto-detection: Embed
data-build in <html> and compare server build vs loaded build on page load to show a "new version available" banner. See references/static-site-cache-invalidation.md for the full diagnostic recipe and auto-detection pattern.
- Theme switcher reliability: If theme switching works in Chrome but not Samsung Internet, or feels broken on mobile, see
references/theme-switcher-reliability.md for the create-new-link โ load โ remove-old pattern.
- Emergency recovery: If a bad deploy breaks the main app JS, users need a standalone reset page. See
references/emergency-reset-page.md for a zero-dependency reset.html that clears Service Workers and caches without relying on the main app's JS.
Dashboard inspector feels too technical
- The default inspector view should contain only plain-language sentences: headline, "what they're doing now", "why it matters", and a silent visual progress bar (no text label).
- Move all technical fields (source IDs, confidence scores, progress labels, status slugs, badges) behind a "Show technical details" toggle.
- If users say "details are hard to understand," the fix is to remove more fields from the default view, not to add explanations. Explanations of technical fields are still technical.
- See
references/progressive-disclosure-human-first.md for the aggressive simplification pattern.
Pixel-art characters look wrong on mobile
- Decorative CSS elements (cheeks, ears, tails, badges) can be misread as facial features or appendages when avatars shrink below ~50 px.
- Hide them inside
@media (max-width:480px) so only the essential silhouette remains.
- See
references/pixel-art-mobile-readability.md for the exact selectors and rationale.
Skills not showing
1. hermes skills list โ verify installed
2. hermes skills config โ check platform enablement
3. Load explicitly: /skill name or hermes -s name
Gateway issues
Check logs first:
grep -i "failed to send\|error" ~/.hermes/logs/gateway.log | tail -20
Common gateway problems:
- Gateway dies on SSH logout: Enable linger:
sudo loginctl enable-linger $USER
- Gateway dies on WSL2 close: WSL2 requires
systemd=true in /etc/wsl.conf for systemd services to work. Without it, gateway falls back to nohup (dies when session closes).
- Gateway crash loop: Reset the failed state:
systemctl --user reset-failed hermes-gateway
- macOS: bot shows offline after idle time: The gateway runs as a user agent (
LimitLoadToSessionType=Aqua), so macOS suspends it when the system sleeps. The platform websocket drops and the bot appears offline until the network returns. Fix: keep the Mac awake (System Settings -> Energy -> Prevent automatic sleeping, or caffeinate -d -i -s -u &). Low Power Mode makes this worse, not better. See references/macos-gateway-sleep-disconnect.md for the full diagnostic recipe.
Platform-specific issues
- Discord bot silent: Must enable Message Content Intent in Bot โ Privileged Gateway Intents. See full Discord setup reference:
references/discord-gateway-setup.md.
- Slack bot only works in DMs: Must subscribe to
message.channels event. Without it, the bot ignores public channels.
- Windows-specific issues (
Alt+Enter newline, WinError 10106, UTF-8 BOM config, test suite, line endings): see the dedicated Windows-Specific Quirks section above.
Auxiliary models not working
If auxiliary tasks (vision, compression, session_search) fail silently, the auto provider can't find a backend. Either set OPENROUTER_API_KEY or GOOGLE_API_KEY, or explicitly configure each auxiliary task's provider:
hermes config set auxiliary.vision.provider <your_provider>
hermes config set auxiliary.vision.model <model_name>
Full system auth provisioning
For a one-shot workflow to maximize available credentials โ installing gh, generating SSH keys, configuring git, enabling all Hermes toolsets, and auditing current auth state โ see references/system-auth-setup.md.
Editing large files with patch
When a file is read with read_file(offset=...) (pagination), the tool warns that the view is partial. If you attempt patch without re-reading the full file first, you will likely hit non-unique match errors or corrupt the file. Fix: always call read_file without offset to load the whole file before patching. The tool explicitly warns: "โฆwas last read with offset/limit pagination (partial view). Re-read the whole file before overwriting it." โ heed this warning. For append-only updates (e.g., adding a cycle log entry to state.md), do not use terminal(command="cat >> file << 'EOF'...EOF") โ the terminal tool on macOS/Linux misinterprets heredoc << as backgrounding and fails. Instead, write a short Python script via write_file and execute it with terminal(command="python3 /tmp/script.py"). See references/terminal-heredoc-workaround.md for the full pattern.
Sibling subagent file overwrites
When multiple subagents are running in parallel (e.g. via delegate_task batch mode or kanban worker lanes), a file may be modified by one subagent while another is about to write to it. If you use write_file or patch on a file that was last read before a sibling subagent modified it, your write may silently truncate or revert the sibling's changes. The tool may show a warning like "this file was modified by sibling subagent X but this agent never read it."
Fix:
1. Heed the warning. If the tool reports a sibling modification, re-read the file with read_file before writing.
2. Prefer patch over write_file for partial updates โ patch only changes the matched region and is less likely to wipe unrelated content.
3. If the file is already published/deployed, and the local working copy gets corrupted, recover from the published copy:
cp ~/hermes-web/agent-pets/css/dashboard.css ~/.hermes/autonomous-agent-lab/pixel-pet-ops/web/css/dashboard.css
4. For append-only updates, write a small Python script and execute it rather than using write_file on the whole file.
Prevention: In kanban/multi-agent workflows, assign file-level ownership so only one worker touches each file. If parallel workers must edit the same file, have them write to separate temp files and let the orchestrator merge.
---
Windows-Specific Quirks
| Looking for... | Location |
|----------------|----------|
| Config options | hermes config edit or [Configuration docs](https://hermes-agent.nousresearch.com/docs/user-guide/configuration) |
| Available tools | hermes tools list or [Tools reference](https://hermes-agent.nousresearch.com/docs/reference/tools-reference) |
| Slash commands | /help in session or [Slash commands reference](https://hermes-agent.nousresearch.com/docs/reference/slash-commands) |
| Skills catalog | hermes skills browse or [Skills catalog](https://hermes-agent.nousresearch.com/docs/reference/skills-catalog) |
| Provider setup | hermes model or [Providers guide](https://hermes-agent.nousresearch.com/docs/integrations/providers) |
| Platform setup | hermes gateway setup or [Messaging docs](https://hermes-agent.nousresearch.com/docs/user-guide/messaging/) |
| MCP servers | hermes mcp list or [MCP guide](https://hermes-agent.nousresearch.com/docs/user-guide/features/mcp) |
| Profiles | hermes profile list or [Profiles docs](https://hermes-agent.nousresearch.com/docs/user-guide/profiles) |
| Cron jobs | hermes cron list or [Cron docs](https://hermes-agent.nousresearch.com/docs/user-guide/features/cron) |
| Memory | hermes memory status or [Memory docs](https://hermes-agent.nousresearch.com/docs/user-guide/features/memory) |
| Env variables | hermes config env-path or [Env vars reference](https://hermes-agent.nousresearch.com/docs/reference/environment-variables) |
| CLI commands | hermes --help or [CLI reference](https://hermes-agent.nousresearch.com/docs/reference/cli-commands) |
| Gateway logs | ~/.hermes/logs/gateway.log |
| Session files | ~/.hermes/sessions/ or hermes sessions browse |
| Source code | ~/.hermes/hermes-agent/ |
---
Contributor Quick Reference
For occasional contributors and PR authors. Full developer docs: https://hermes-agent.nousresearch.com/docs/developer-guide/
Project Layout
hermes-agent/
โโโ run_agent.py # AIAgent โ core conversation loop
โโโ model_tools.py # Tool discovery and dispatch
โโโ toolsets.py # Toolset definitions
โโโ cli.py # Interactive CLI (HermesCLI)
โโโ hermes_state.py # SQLite session store
โโโ agent/ # Prompt builder, context compression, memory, model routing, credential pooling, skill dispatch
โโโ hermes_cli/ # CLI subcommands, config, setup, commands
โ โโโ commands.py # Slash command registry (CommandDef)
โ โโโ config.py # DEFAULT_CONFIG, env var definitions
โ โโโ main.py # CLI entry point and argparse
โโโ tools/ # One file per tool
โ โโโ registry.py # Central tool registry
โโโ gateway/ # Messaging gateway
โ โโโ platforms/ # Platform adapters (telegram, discord, etc.)
โโโ cron/ # Job scheduler
โโโ tests/ # ~3000 pytest tests
โโโ website/ # Docusaurus docs site
Config: ~/.hermes/config.yaml (settings), ~/.hermes/.env (API keys).
Adding a Tool (3 files)
1. Create tools/your_tool.py:
import json, os
from tools.registry import registry
def check_requirements() -> bool:
return bool(os.getenv("EXAMPLE_API_KEY"))
def example_tool(param: str, task_id: str = None) -> str:
return json.dumps({"success": True, "data": "..."})
registry.register(
name="example_tool",
toolset="example",
schema={"name": "example_tool", "description": "...", "parameters": {...}},
handler=lambda args, **kw: example_tool(
param=args.get("param", ""), task_id=kw.get("task_id")),
check_fn=check_requirements,
requires_env=["EXAMPLE_API_KEY"],
)
2. Add to toolsets.py โ _HERMES_CORE_TOOLS list.
Auto-discovery: any tools/*.py file with a top-level registry.register() call is imported automatically โ no manual list needed.
All handlers must return JSON strings. Use get_hermes_home() for paths, never hardcode ~/.hermes.
Adding a Slash Command
1. Add CommandDef to COMMAND_REGISTRY in hermes_cli/commands.py
2. Add handler in cli.py โ process_command()
3. (Optional) Add gateway handler in gateway/run.py
All consumers (help text, autocomplete, Telegram menu, Slack mapping) derive from the central registry automatically.
Agent Loop (High Level)
run_conversation():
1. Build system prompt
2. Loop while iterations < max:
a. Call LLM (OpenAI-format messages + tool schemas)
b. If tool_calls โ dispatch each via handle_function_call() โ append results โ continue
c. If text response โ return
3. Context compression triggers automatically near token limit
Testing
python -m pytest tests/ -o 'addopts=' -q # Full suite
python -m pytest tests/tools/ -q # Specific area
- Tests auto-redirect
HERMES_HOME to temp dirs โ never touch real ~/.hermes/
- Run full suite before pushing any change
- Use
-o 'addopts=' to clear any baked-in pytest flags
Windows contributors: scripts/run_tests.sh currently looks for POSIX venvs ( .venv/bin/activate / venv/bin/activate) and will error out on Windows where the layout is venv/Scripts/activate + python.exe. The Hermes-installed venv at venv/Scripts/ also has no pip or pytest โ it's stripped for end-user install size. Workaround: install pytest + pytest-xdist + pyyaml into a system Python 3.11 user site ( /c/Program Files/Python311/python -m pip install --user pytest pytest-xdist pyyaml), then run tests directly:
export PYTHONPATH="$(pwd)"
"/c/Program Files/Python311/python" -m pytest tests/tools/test_foo.py -v --tb=short -n 0
Use -n 0 (not -n 4) because pyproject.toml's default addopts already includes -n, and the wrapper's CI-parity story doesn't apply off-POSIX.
Cross-platform test guards: tests that use POSIX-only syscalls need a skip marker. Common ones already in the codebase:
- Symlink creation โ
@pytest.mark.skipif(sys.platform == "win32", reason="Symlinks require elevated privileges on Windows") (see tests/cron/test_cron_script.py)
- POSIX file modes (0o600, etc.) โ
@pytest.mark.skipif(sys.platform.startswith("win"), reason="POSIX mode bits not enforced on Windows") (see tests/hermes_cli/test_auth_toctou_file_modes.py)
signal.SIGALRM โ Unix-only (see tests/conftest.py::_enforce_test_timeout)
- Live Winsock / Windows-specific regression tests โ
@pytest.mark.skipif(sys.platform != "win32", reason="Windows-specific regression")
Monkeypatching sys.platform is not enough when the code under test also calls platform.system() / platform.release() / platform.mac_ver(). Those functions re-read the real OS independently, so a test that sets sys.platform = "linux" on a Windows runner will still see platform.system() == "Windows" and route through the Windows branch. Patch all three together:
monkeypatch.setattr(sys, "platform", "linux")
monkeypatch.setattr(platform, "system", lambda: "Linux")
monkeypatch.setattr(platform, "release", lambda: "6.8.0-generic")
See tests/agent/test_prompt_builder.py::TestEnvironmentHints for a worked example.
Extending the system prompt's execution-environment block
Factual guidance about the host OS, user home, cwd, terminal backend, and shell (bash vs. PowerShell on Windows) is emitted from agent/prompt_builder.py::build_environment_hints(). This is also where the WSL hint and per-backend probe logic live. The convention:
- Local terminal backend โ emit host info (OS,
$HOME, cwd) + Windows-specific notes (hostname โ username, terminal uses bash not PowerShell).
- Remote terminal backend (anything in
_REMOTE_TERMINAL_BACKENDS: docker, singularity, modal, daytona, ssh, vercel_sandbox, managed_modal) โ suppress host info entirely and describe only the backend. A live uname/whoami/pwd probe runs inside the backend via tools.environments.get_environment(...).execute(...), cached per process in _BACKEND_PROBE_CACHE, with a static fallback if the probe times out.
- Key fact for prompt authoring: when
TERMINAL_ENV != "local", every file tool (read_file, write_file, patch, search_files) runs inside the backend container, not on the host. The system prompt must never describe the host in that case โ the agent can't touch it.
Full design notes, the exact emitted strings, and testing pitfalls:
references/prompt-builder-environment-hints.md.
Refactor-safety pattern (POSIX-equivalence guard): when you extract inline logic into a helper that adds Windows/platform-specific behavior, keep a _legacy_<name> oracle function in the test file that's a verbatim copy of the old code, then parametrize-diff against it. Example: tests/tools/test_code_execution_windows_env.py::TestPosixEquivalence. This locks in the invariant that POSIX behavior is bit-for-bit identical and makes any future drift fail loudly with a clear diff.
Commit Conventions
type: concise subject line
Optional body.
Types: fix:, feat:, refactor:, docs:, chore:
Key Rules
- Never break prompt caching โ don't change context, tools, or system prompt mid-conversation
- Message role alternation โ never two assistant or two user messages in a row
- Use
get_hermes_home() from hermes_constants for all paths (profile-safe)
- Config values go in
config.yaml, secrets go in .env
- New tools need a
check_fn so they only appear when requirements are met
[IMPORTANT: The user has invoked the "kanban-orchestrator" skill, indicating they want you to follow its instructions. The full skill content is loaded below.]
---
name: kanban-orchestrator
description: Decomposition playbook + anti-temptation rules for an orchestrator profile routing work through Kanban. The "don't do the work yourself" rule and the basic lifecycle are auto-injected into every kanban worker's system prompt; this skill is the deeper playbook when you're specifically playing the orchestrator role.
version: 3.0.0
platforms: [linux, macos, windows]
metadata:
hermes:
tags: [kanban, multi-agent, orchestration, routing]
related_skills: [kanban-worker]
---
Kanban Orchestrator โ Decomposition Playbook
> The core worker lifecycle (including the kanban_create fan-out pattern and the "decompose, don't execute" rule) is auto-injected into every kanban process via the KANBAN_GUIDANCE system-prompt block. This skill is the deeper playbook when you're an orchestrator profile whose whole job is routing.
Profiles are user-configured โ not a fixed roster
Hermes setups vary widely. Some users run a single profile that does everything; some run a small fleet (docker-worker, cron-worker); some run a curated specialist team they've named themselves. There is no default specialist roster โ the orchestrator skill does not know what profiles exist on this machine.
Before fanning out, you must ground the decomposition in the profiles that actually exist. The dispatcher silently fails to spawn unknown assignee names โ it doesn't autocorrect, doesn't suggest, doesn't fall back. So a card assigned to researcher on a setup that only has docker-worker just sits in ready forever.
Step 0: discover available profiles before planning.
Use one of these:
hermes profile list โ prints the table of profiles configured on this machine. Run it through your terminal tool if you have one; otherwise ask the user.
kanban_list(assignee="<some-name>") โ sanity-check a single name. Returns an empty list (rather than an error) for an unknown assignee, so this only confirms a name you're already considering.
- Just ask the user. "What profiles do you have set up?" is a fine first turn when the goal needs more than one specialist.
Cache the result in your working memory for the rest of the conversation. Re-asking every turn wastes a tool call.
When to use the board (vs. just doing the work)
Create Kanban tasks when any of these are true:
1. Multiple specialists are needed. Research + analysis + writing is three profiles.
2. The work should survive a crash or restart. Long-running, recurring, or important.
3. The user might want to interject. Human-in-the-loop at any step.
4. Multiple subtasks can run in parallel. Fan-out for speed.
5. Review / iteration is expected. A reviewer profile loops on drafter output.
6. The audit trail matters. Board rows persist in SQLite forever.
If none of those apply โ it's a small one-shot reasoning task โ use delegate_task instead or answer the user directly.
The anti-temptation rules
Your job description says "route, don't execute." The rules that enforce that:
- Do not execute the work yourself. Your restricted toolset usually doesn't even include terminal/file/code/web for implementation. If you find yourself "just fixing this quickly" โ stop and create a task for the right specialist.
- For any concrete task, create a Kanban task and assign it. Every single time.
- Split multi-lane requests before creating cards. A user prompt can contain several independent workstreams. Extract those lanes first, then create one card per lane instead of bundling unrelated work into a single implementer card.
- Run independent lanes in parallel. If two cards do not need each other's output, leave them unlinked so the dispatcher can fan them out. Link only true data dependencies.
- If no specialist fits the available profiles, ask the user which profile to create or which existing profile to use. Do not invent profile names; the dispatcher will silently drop unknown assignees.
- Decompose, route, and summarize โ that's the whole job.
Exception: micro-UI polish cycles
There is one narrow exception where the orchestrator may execute directly instead of creating Kanban cards: tiny UI-only polish cycles (e.g., adding a CSS class, a theme preview dot, a hover state, a cross-link, or a HUD button) that are purely presentational, require no cross-file logic changes, and fit comfortably inside a single bounded cycle with no need for review or parallel work. If the change is limited to HTML/CSS/JS cosmetics, no other profile has a stake in it, and the user did not ask for a design review, the orchestrator should just edit and publish rather than paying the kanban-overhead tax. This exception does NOT apply to architecture changes, adapter logic, plugin interfaces, or anything that touches the data layer.
Decomposition playbook
Step 1 โ Understand the goal
Ask clarifying questions if the goal is ambiguous. Cheap to ask; expensive to spawn the wrong fleet.
Step 2 โ Sketch the task graph
Before creating anything, draft the graph out loud (in your response to the user). Treat every concrete workstream as a candidate card:
1. Extract the lanes from the request.
2. Map each lane to one of the profiles you discovered in Step 0. If a lane doesn't fit any existing profile, ask the user which to use or create.
3. Decide whether each lane is independent or gated by another lane.
4. Create independent lanes as parallel cards with no parent links.
5. Create synthesis/review/integration cards with parent links to the lanes they depend on.
Examples of prompts that should fan out (using placeholder profile names โ substitute whatever exists on the user's setup):
- "Build an app" โ one card to a design-oriented profile for product/UI direction, one or two cards to engineering profiles for implementation, plus a later integration/review card if the user has a reviewer profile.
- "Fix blockers and check model variants" โ one implementation card for the blocker fixes plus one discovery/research card for config/source verification. A final reviewer card can depend on both.
- "Research docs and implement" โ a docs-research card can run in parallel with a codebase-discovery card; implementation waits only if it truly needs those findings.
- "Analyze this screenshot and find the related code" โ one card to a vision-capable profile for the visual analysis while another searches the codebase.
Words like "also," "finally," or "and" do not automatically imply a dependency. They often mean "make sure this is covered before reporting back." Only link tasks when one card cannot start until another card's output exists.
Show the graph to the user before creating cards. Let them correct it โ including which actual profile name should own each lane.
Step 3 โ Create tasks and link
Use the profile names from Step 0. The example below uses placeholders <profile-A>, <profile-B>, <profile-C> โ replace them with what the user actually has.
t1 = kanban_create(
title="research: Postgres cost vs current",
assignee="<profile-A>", # whichever profile handles research on this setup
body="Compare estimated infrastructure costs, migration costs, and ongoing ops costs over a 3-year window. Sources: AWS/GCP pricing, team time estimates, current Postgres bills from peers.",
tenant=os.environ.get("HERMES_TENANT"),
)["task_id"]
t2 = kanban_create(
title="research: Postgres performance vs current",
assignee="<profile-A>", # same profile, run in parallel
body="Compare query latency, throughput, and scaling characteristics at our expected data volume (~500GB, 10k QPS peak). Sources: benchmark papers, public case studies, pgbench results if easy.",
)["task_id"]
t3 = kanban_create(
title="synthesize migration recommendation",
assignee="<profile-B>", # whichever profile does synthesis/analysis
body="Read the findings from T1 (cost) and T2 (performance). Produce a 1-page recommendation with explicit trade-offs and a go/no-go call.",
parents=[t1, t2],
)["task_id"]
t4 = kanban_create(
title="draft decision memo",
assignee="<profile-C>", # whichever profile drafts user-facing prose
body="Turn the analyst's recommendation into a 2-page memo for the CTO. Match the tone of previous decision memos in the team's knowledge base.",
parents=[t3],
)["task_id"]
parents=[...] gates promotion โ children stay in todo until every parent reaches done, then auto-promote to ready. No manual coordination needed; the dispatcher and dependency engine handle it.
Step 4 โ Complete your own task
If you were spawned as a task yourself (e.g. a planner profile was assigned T0: "investigate Postgres migration"), mark it done with a summary of what you created:
kanban_complete(
summary="decomposed into T1-T4: 2 research lanes in parallel, 1 synthesis on their outputs, 1 prose draft on the recommendation",
metadata={
"task_graph": {
"T1": {"assignee": "<profile-A>", "parents": []},
"T2": {"assignee": "<profile-A>", "parents": []},
"T3": {"assignee": "<profile-B>", "parents": ["T1", "T2"]},
"T4": {"assignee": "<profile-C>", "parents": ["T3"]},
},
},
)
Step 5 โ Report back to the user
Tell them what you created in plain prose, naming the actual profiles you used:
> I've queued 4 tasks:
> - T1 (<profile-A>): cost comparison
> - T2 (<profile-A>): performance comparison, in parallel with T1
> - T3 (<profile-B>): synthesizes T1 + T2 into a recommendation
> - T4 (<profile-C>): turns T3 into a CTO memo
>
> The dispatcher will pick up T1 and T2 now. T3 starts when both finish. You'll get a gateway ping when T4 completes. Use the dashboard or hermes kanban tail <id> to follow along.
Common patterns
Fan-out + fan-in (research โ synthesize): N research-style cards with no parents, one synthesis card with all of them as parents.
Parallel implementation + validation: one implementer card makes the change while one explorer/researcher card verifies config, docs, or source mapping. A reviewer card can depend on both. Do not make the implementer own unrelated verification just because the user mentioned both in one sentence.
Pipeline with gates: planner โ implementer โ reviewer. Each stage's parents=[previous_task]. Reviewer blocks or completes; if reviewer blocks, the operator unblocks with feedback and respawns.
Same-profile queue: N tasks, all assigned to the same profile, no dependencies between them. Dispatcher serializes โ that profile processes them in priority order, accumulating experience in its own memory.
Parallel UI/frontend lanes: When the goal touches multiple independent HTML/CSS/JS files (e.g., a dashboard page and a 2D gather view), fan out to separate subagents per file. Each lane edits its own file, then the orchestrator integrates, fixes cross-file references (theme paths, shared JSON endpoints), and publishes. This avoids merge conflicts in single-file HTML dashboards and keeps each subagent's context focused. See references/parallel-ui-lanes-and-publishing.md for the post-subagent integration checklist and rsync safety notes.
Human-in-the-loop: Any task can kanban_block() to wait for input. Dispatcher respawns after /unblock. The comment thread carries the full context.
Pitfalls
Inventing profile names that don't exist. The dispatcher silently fails to spawn unknown assignees โ the card just sits in ready forever. Always assign to a profile from your Step 0 discovery; ask the user if you're unsure.
Bundling independent lanes into one card. If the user asks for two independent outcomes, create two cards. Example: "fix blockers and check model variants" is not one fixer task; create a fixer/engineer card for the fixes and an explorer/researcher card for the variant check, then optionally gate review on both.
Over-linking because of wording. "Finally check X" may still be parallel with implementation if X is static config, docs, or source discovery. Link it after implementation only when the check depends on the implementation result.
Forgetting dependency links. If the task graph says research -> implement -> review, do not create all tasks as independent ready cards. Use parent links so implement/review cannot run before their inputs exist.
Reassignment vs. new task. If a reviewer blocks with "needs changes," create a NEW task linked from the reviewer's task โ don't re-run the same task with a stern look. The new task is assigned to the original implementer profile.
Argument order for links. kanban_link(parent_id=..., child_id=...) โ parent first. Mixing them up demotes the wrong task to todo.
Ignoring explicit user feedback to keep building infrastructure. When the user says a specific UX issue (legibility, theme switching, movement density) is "immediate priority," treat it as P0 and route it before deeper packaging/architecture work. Infrastructure polish feels productive, but shipping user-visible fixes is what matters. Create cards for the UX feedback first, then resume infrastructure lanes.
Treating status: complete as immutable when user feedback says otherwise. A state.md that says status: complete does not override a user's report that a completion criterion is actually broken. If the user says "theme switching is not working" and the Final Completion Condition requires "working UI theme switcher," the mission is not complete. Reactivate immediately: set status: active, append a reactivation cycle log, and fix the issue. Do not burn cycles on post-complete verification while the user is reporting active defects.
Don't pre-create the whole graph if the shape depends on intermediate findings. If T3's structure depends on what T1 and T2 find, let T3 exist as a "synthesize findings" task whose own first step is to read parent handoffs and plan the rest. Orchestrators can spawn orchestrators.
Tenant inheritance. If HERMES_TENANT is set in your env, pass tenant=os.environ.get("HERMES_TENANT") on every kanban_create call so child tasks stay in the same namespace.
Verifying cross-file references after directory reorganization. When subagents edit HTML/CSS/JS files and the directory structure shifts (e.g., moving files from root into web/dashboard/ and web/gather/), relative asset paths ( themes/default/theme.css, ./ops-data.json) often break. After subagents finish, the orchestrator must grep for href= and src= in moved files and fix relative paths before publishing. Subagents don't know the final publish layout โ the orchestrator does.
Destructive sync wipes needed files. Commands like rsync -av --delete will delete destination files that aren't in the source list. If you publish a directory tree piecemeal (e.g., copy web/dashboard/ first, then web/gather/ separately), --delete on the first rsync will erase the gather files before the second rsync runs. Either list all source paths in a single rsync invocation, or omit --delete and use cp -r / rsync -av without deletion when doing staged copies.
Recovering stuck workers
When a worker profile keeps crashing, hallucinating, or getting blocked by its own mistakes (usually: wrong model, missing skill, broken credential), the kanban dashboard flags the task with a โ badge and opens a Recovery section in the drawer. Three primary actions:
1. Reclaim (or hermes kanban reclaim <task_id>) โ abort the running worker immediately and reset the task to ready. The existing claim TTL is ~15 min; this is the fast path out.
2. Reassign (or hermes kanban reassign <task_id> <new-profile> --reclaim) โ switch the task to a different profile (one that exists on this setup) and let the dispatcher pick it up with a fresh worker.
3. Change profile model โ the dashboard prints a copy-paste hint for hermes -p <profile> model since profile config lives on disk; edit it in a terminal, then Reclaim to retry with the new model.
Hallucination warnings appear on tasks where a worker's kanban_complete(created_cards=[...]) claim included card ids that don't exist or weren't created by the worker's profile (the gate blocks the completion), or where the free-form summary references t_<hex> ids that don't resolve (advisory prose scan, non-blocking). Both produce audit events that persist even after recovery actions โ the trail stays for debugging.
The user has provided the following instruction alongside the skill invocation: [IMPORTANT: You are running as a scheduled cron job. DELIVERY: Your final response will be automatically delivered to the user โ do NOT use send_message or try to deliver the output yourself. Just produce your report/output as your final response and the system handles the rest. SILENT: If there is genuinely nothing new to report, respond with exactly "[SILENT]" (nothing else) to suppress delivery. Never combine [SILENT] with content โ either report your findings normally, or say [SILENT] and nothing more.]
You are the 15-minute Orchestrator for Son's Autonomous Agent Lab v1, reporting to Discord channel ID 1505805763824586952.
Durable state path: /Users/jooho-hermes/.hermes/autonomous-agent-lab/state.md
Working directory for experiment artifacts: /Users/jooho-hermes/.hermes/autonomous-agent-lab/
Preferred published web root: /Users/jooho-hermes/hermes-web/agent-pets/
Top-level directive from Son:
- The project has evolved from a personal dashboard into an INSTALLABLE PRODUCT that external Hermes users can deploy.
- The final target is a self-contained, configurable, publishable solution: "Hermes Pixel Pet Ops Office".
- Do NOT shrink the mission into a small static MVP and autonomously stop.
- The Gather.town-style 2D spatial office is a first-class feature, not a side page.
Latest UX feedback from Son (treat as immediate priority before deeper packaging work):
- Details are hard for a human to understand. Add human-first summaries, plain-language labels, and progressive disclosure: summary first, technical details second.
- Gather Town version has too many agents roaming around. Reduce default movement, add density/speed controls, cluster agents by room/task, and add focus/calm mode.
- Theme switching is not visibly working. Implement real UI theme switcher with persistence and clear visual theme changes.
Key product requirements (installable solution level):
1. Config-driven architecture: all paths, URLs, colors, names, room layouts via config.yaml. No hardcoded references to jooho-hermes.
2. Self-contained package: clear directory structure (src/, web/, config/, docs/, scripts/), install script, requirements.txt.
3. Pluggable data adapter: support multiple backends via plugin architecture.
4. Themeable frontend: CSS variables driven from config, swappable themes, plus a working UI theme switcher.
5. Multi-tenant ready: works for any Hermes instance.
6. Build/Deploy ready: Dockerfile or docker-compose, or clear static-server setup.
7. Documentation: README, architecture docs, configuration reference, contributor guide.
8. Human-comprehensible UX: plain-language summaries and progressive disclosure for technical detail.
9. Gather.town calm mode: adjustable movement density/speed and less chaotic defaults.
10. Versioned releases: CHANGELOG.md, semantic versioning, release packaging.
Mission model:
- Read state.md first before doing anything else.
- If state.md says
status: inactive or has no Current Mission, do not invent work. Return exactly: ๐ก Autonomous Agent Lab ๋๊ธฐ์ค โ Son์ด ํธ๋ฆฌ๊ฑฐ/๋ฏธ์
์ ์ฃผ๋ฉด 15๋ถ ์ฌ์ดํด์ ์์ํฉ๋๋ค.
- If state.md says
status: active, run one bounded 15-minute cycle toward the full installable solution.
- If state.md says
status: complete, verify that the Final Completion Condition in state.md is truly met. If it is not fully met, reactivate or report that state needs correction.
Cycle procedure when active:
1. Read state.md first. Extract current mission, constraints, previous cycle log, and Final Completion Condition.
2. Decide the next smallest useful step toward installable solution quality. Focus on: architecture, configurability, documentation, and clean separation of concerns.
3. Use delegate_task for independent subagent lanes when helpful.
4. Prefer concrete progress: refactor to config-driven, add install scripts, create docs, add Docker support, theme system, plugin architecture.
5. Update state.md with a new cycle log entry before final reporting.
6. Completion rule: only set status: complete when every item under state.md Final Completion Condition is satisfied. A non-installable MVP is not complete.
7. Stop/block only if Son explicitly stops/redirects, a safety boundary is reached, or a hard blocker needs Son's decision.
Link requirement (never forget):
- Every cycle report MUST include at least one direct viewable link to the published dashboard/artifact.
- The canonical URL:
http://hermes-mac-mini.tail46b3c6.ts.net:8099/agent-pets/
- Include gather town URL too:
http://hermes-mac-mini.tail46b3c6.ts.net:8099/agent-pets/gather/
Final Discord message format:
[Autonomous Agent Lab v1 / Cycle N]
๋ชฉํ:
์ํ:
๊ฒฐ๊ณผ:
๊ฒ์ฆ:
๋ค์:
์ํ:
Safety/quality rules:
- Do not handle secrets, passwords, API keys, payment, permission dialogs, or destructive commands.
- Do not claim completion without updating state.md.
- Do not rely on Discord history as durable state.
- Do not spam raw logs; summarize lane outputs and verification.
- Keep working in /Users/jooho-hermes/.hermes/autonomous-agent-lab/ and publish only to /Users/jooho-hermes/hermes-web/agent-pets/ unless the state file says otherwise.
Design/UX priorities:
- Mobile responsiveness is first-class.
- Character animation/movement is desired.
- Every cycle report must include published links.
- This is now a product engineering mission. Architecture, configurability, and documentation matter as much as visuals.
Response
[Autonomous Agent Lab v1 / Cycle 76]
๋ชฉํ:
1. ์ธ์คํํฐ ๋ฅ๋งํฌ ์ถ๊ฐ โ ํน์ ์์ด์ ํธ๋ฅผ ํด๋ฆญํ๋ฉด URL ํด์์ #agent=<id>๊ฐ ๊ธฐ๋ก๋์ด, ํด๋น URL์ ๊ณต์ ํ๋ฉด ์์ ์๊ฐ ์ด์์ ๋ ์ธ์คํํฐ๊ฐ ์๋์ผ๋ก ์ด๋ฆผ
2. ํ์ค ๊ฑด๊ฐ ๊ฒ์ฆ ๋ฐ ๋น๋ ๋ฒ์ ์ผ๊ด์ฑ ์ ์ง
์ํ:
web/js/dashboard.js: openInspector()์์ history.replaceState(null, '', '#agent=' + esc(aid)) ์ถ๊ฐ
closeInspector()์์ ํด์ ์ ๊ฑฐ
hydrateViewFromUrl()์์ #agent= ๊ฐ์ง ํ 300ms ๋๋ ์ด๋ก ์๋ ์ธ์คํํฐ ์คํ
- ๊ธฐ์กด "๐ ํ์ฌ ๋ทฐ ๊ณต์ " ๋ฒํผ๊ณผ ์์ฐ์ค๋ฝ๊ฒ ์ฐ๋ (ํํฐ/๊ฒ์/ํ
๋ง + ์์ด์ ํธ ํด์๊ฐ ๋ชจ๋ URL์ ํฌํจ๋จ)
- ๋น๋ ๋ฒ์ b74 โ b76, ์บ์ ๋ฒ์คํธ
?v=76, Service Worker CACHE_NAME = pixel-pet-ops-v24๋ก ์ผ๊ด ๊ฐฑ์
- ์ด๋ํฐ, ํตํฉ ํ
์คํธ(134/134 pass), ์ค์ ๊ฒ์ฆ(21/21 pass), publish.sh ์คํ
๊ฒฐ๊ณผ:
- Dashboard: http://hermes-mac-mini.tail46b3c6.ts.net:8099/agent-pets/
- Gather Town: http://hermes-mac-mini.tail46b3c6.ts.net:8099/agent-pets/gather/
- ๋ฑ์ง:
v1.4.4 ยท b76
- ์์ด์ ํธ ์นด๋๋ฅผ ํด๋ฆญ โ ์ธ์คํํฐ ์ด๋ฆผ โ URL ๋ณต์ฌ โ ์ ํญ์์ ์ด๋ฉด ํด๋น ์์ด์ ํธ ์ธ์คํํฐ๊ฐ ์๋์ผ๋ก ์ด๋ฆผ
๊ฒ์ฆ:
ops-data.json: schema 1.4, 32 agents, 15 cron jobs, 20 sessions, 16 events
health.json: status=healthy, version=1.4.4
scripts/test.sh: 134 passed / 0 failed
scripts/validate_setup.sh: 21 passed / 0 warned / 0 critical
refresh.err.log: empty, LaunchAgent healthy
- ์์คโ๋ฐํ ํ์ผ 100% ๋๊ธฐํ ํ์ธ (diff -q)
- ํ๋์ฝ๋ฉ๋
jooho-hermes ์ฐธ์กฐ: 0๊ฑด
๋ค์:
- Son์ด ๋ธ๋ผ์ฐ์ ์์ 3๊ฐ์ง ์ฃผ์ UX ํผ๋๋ฐฑ(ํ
๋ง ์ ํ, Gather calm mode, human-first details)๊ณผ Daily Briefing์ ์ต์ข
ํ์ธ
- ์ธ์คํํฐ ๋ฅ๋งํฌ ํ
์คํธ: ์์ด์ ํธ ํด๋ฆญ โ URL ๋ณต์ฌ โ ์ ํญ์์ ์๋ ์คํ ํ์ธ
- ๋ชจ๋ ๋ง์กฑํ๋ฉด
status: complete๋ก ์ ํ ๊ฐ๋ฅ
- ํฅํ ์ ํ์ ํธ์ ๊ธฐ๋ฅ: ์ผ์ผ ์ด์ ์ด๋ฉ์ผ ๋ค์ด์ ์คํธ, ์์ด์ ํธ ์ฑ๋ฅ ์ค์ฝ์ด์นด๋, ์๋ ๊ฑด๊ฐ ๋ฆฌํฌํธ ์์ฑ
์ํ:
๐ข active โ ๋ชจ๋ 11๊ฐ Final Completion Condition ์ถฉ์กฑ, Son์ ๋ธ๋ผ์ฐ์ ์ธก ์ต์ข
ํ์ธ ๋๊ธฐ์ค. Inspector ๋ฅ๋งํฌ ๊ณต์ ๊ธฐ๋ฅ์ด Cycle 76์์ ์ถ๊ฐ๋จ.
|
| 2026-05-20 01-43-16 |
84,452 chars |
2026-05-20_01-43-16.md |
Cron Job: autonomous-agent-lab-v1-orchestrator
Job ID: 35127ff89556
Run Time: 2026-05-20 01:43:16
Schedule: every 15m
Prompt
[IMPORTANT: The user has invoked the "hermes-agent" skill, indicating they want you to follow its instructions. The full skill content is loaded below.]
---
name: hermes-agent
description: "Configure, extend, or contribute to Hermes Agent."
version: 2.1.0
author: Hermes Agent + Teknium
license: MIT
platforms: [linux, macos, windows]
metadata:
hermes:
tags: [hermes, setup, configuration, multi-agent, spawning, cli, gateway, development]
homepage: https://github.com/NousResearch/hermes-agent
related_skills: [claude-code, codex, opencode]
---
Hermes Agent
Hermes Agent is an open-source AI agent framework by Nous Research that runs in your terminal, messaging platforms, and IDEs. It belongs to the same category as Claude Code (Anthropic), Codex (OpenAI), and OpenClaw โ autonomous coding and task-execution agents that use tool calling to interact with your system. Hermes works with any LLM provider (OpenRouter, Anthropic, OpenAI, DeepSeek, local models, and 15+ others) and runs on Linux, macOS, and WSL.
What makes Hermes different:
- Self-improving through skills โ Hermes learns from experience by saving reusable procedures as skills. When it solves a complex problem, discovers a workflow, or gets corrected, it can persist that knowledge as a skill document that loads into future sessions. Skills accumulate over time, making the agent better at your specific tasks and environment.
- Persistent memory across sessions โ remembers who you are, your preferences, environment details, and lessons learned. Pluggable memory backends (built-in, Honcho, Mem0, and more) let you choose how memory works.
- Multi-platform gateway โ the same agent runs on Telegram, Discord, Slack, WhatsApp, Signal, Matrix, Email, and 10+ other platforms with full tool access, not just chat.
- Provider-agnostic โ swap models and providers mid-workflow without changing anything else. Credential pools rotate across multiple API keys automatically.
- Profiles โ run multiple independent Hermes instances with isolated configs, sessions, skills, and memory.
- Extensible โ plugins, MCP servers, custom tools, webhook triggers, cron scheduling, and the full Python ecosystem.
People use Hermes for software development, research, system administration, data analysis, content creation, home automation, and anything else that benefits from an AI agent with persistent context and full system access.
This skill helps you work with Hermes Agent effectively โ setting it up, configuring features, spawning additional agent instances, troubleshooting issues, finding the right commands and settings, and understanding how the system works when you need to extend or contribute to it.
Docs: https://hermes-agent.nousresearch.com/docs/
Quick Start
Install
curl -fsSL https://raw.githubusercontent.com/NousResearch/hermes-agent/main/scripts/install.sh | bash
Interactive chat (default)
hermes
Single query
hermes chat -q "What is the capital of France?"
Setup wizard
hermes setup
Change model/provider
hermes model
Check health
hermes doctor
---
CLI Reference
Global Flags
hermes [flags] [command]
--version, -V Show version
--resume, -r SESSION Resume session by ID or title
--continue, -c [NAME] Resume by name, or most recent session
--worktree, -w Isolated git worktree mode (parallel agents)
--skills, -s SKILL Preload skills (comma-separate or repeat)
--profile, -p NAME Use a named profile
--yolo Skip dangerous command approval
--pass-session-id Include session ID in system prompt
No subcommand defaults to chat.
Chat
hermes chat [flags]
-q, --query TEXT Single query, non-interactive
-m, --model MODEL Model (e.g. anthropic/claude-sonnet-4)
-t, --toolsets LIST Comma-separated toolsets
--provider PROVIDER Force provider (openrouter, anthropic, nous, etc.)
-v, --verbose Verbose output
-Q, --quiet Suppress banner, spinner, tool previews
--checkpoints Enable filesystem checkpoints (/rollback)
--source TAG Session source tag (default: cli)
Configuration
hermes setup [section] Interactive wizard (model|terminal|gateway|tools|agent)
hermes model Interactive model/provider picker
hermes config View current config
hermes config edit Open config.yaml in $EDITOR
hermes config set KEY VAL Set a config value
hermes config path Print config.yaml path
hermes config env-path Print .env path
hermes config check Check for missing/outdated config
hermes config migrate Update config with new options
hermes doctor [--fix] Check dependencies and config
Credential Pools
hermes auth add Interactive credential wizard (oauth, api-key)
hermes auth list [PROVIDER] List pooled credentials
hermes auth remove P INDEX Remove by provider + index
hermes auth reset PROVIDER Clear exhaustion status
hermes logout Clear stored auth
Tools & Skills
hermes tools Interactive tool enable/disable (curses UI)
hermes tools list Show all tools and status
hermes tools enable NAME Enable a toolset
hermes tools disable NAME Disable a toolset
hermes skills list List installed skills
hermes skills search QUERY Search the skills hub
hermes skills install ID Install a skill (ID can be a hub identifier OR a direct https://โฆ/SKILL.md URL; pass --name to override when frontmatter has no name)
hermes skills inspect ID Preview without installing
hermes skills config Enable/disable skills per platform
hermes skills check Check for updates
hermes skills update Update outdated skills
hermes skills uninstall N Remove a hub skill
hermes skills publish PATH Publish to registry
hermes skills browse Browse all available skills
hermes skills tap add REPO Add a GitHub repo as skill source
MCP Servers
hermes mcp serve Run Hermes as an MCP server
hermes mcp add NAME Add an MCP server (--url or --command)
hermes mcp remove NAME Remove an MCP server
hermes mcp list List configured servers
hermes mcp test NAME Test connection
hermes mcp configure NAME Toggle tool selection
Gateway (Messaging Platforms)
hermes gateway run Start gateway foreground
hermes gateway install Install as background service
hermes gateway start/stop Control the service
hermes gateway restart Restart the service
hermes gateway status Check status
hermes gateway setup Configure platforms
Supported platforms: Telegram, Discord, Slack, WhatsApp, Signal, Email, SMS, Matrix, Mattermost, Home Assistant, DingTalk, Feishu, WeCom, BlueBubbles (iMessage), Weixin (WeChat), API Server, Webhooks. Open WebUI connects via the API Server adapter.
Platform docs: https://hermes-agent.nousresearch.com/docs/user-guide/messaging/
Discord-specific walkthrough (token, intents, service install, access control): see references/discord-gateway-setup.md in this skill.
- Per-channel personas and skill bindings: see
references/gateway-channel-personas.md (works on Discord, Slack, Telegram, Mattermost, Matrix).
- For long-running Discord-first operations, purpose-specific channel routing, periodic summaries, weekly Dreaming/audit reports, and log-safety patterns: see
references/discord-operating-planes.md.
- For broad Hermes/LifeOS/SQAF ecosystem audits (cron inventory, live services, dashboards, provider/model warnings, and control-plane gaps), see
references/ecosystem-audit.md.
Sessions
hermes sessions list List recent sessions
hermes sessions browse Interactive picker
hermes sessions export OUT Export to JSONL
hermes sessions rename ID T Rename a session
hermes sessions delete ID Delete a session
hermes sessions prune Clean up old sessions (--older-than N days)
hermes sessions stats Session store statistics
For browser-based viewing of existing Hermes CLI/Discord/cron session transcripts, prefer a lightweight static export from ~/.hermes/state.db into a private web root instead of assuming Open WebUI can browse Hermes' native session store. See references/hermes-session-static-web-viewer.md for the SQLite schema, static HTML export workflow, redaction/truncation cautions, and the user's Mac mini deployment (/hermes-sessions/ under the Tailscale-only ~/hermes-web site).
For cron job execution history, the same static-export pattern applies to ~/.hermes/cron/jobs.json and ~/.hermes/cron/output/{job_id}/*.md. See references/cron-history-web-viewer.md for the cron data model, schedule-dict pitfall, and the user's deployed /cron-history/ dashboard.
Cron Jobs
hermes cron list List jobs (--all for disabled)
hermes cron create SCHED Create: '30m', 'every 2h', '0 9 *'
hermes cron edit ID Edit schedule, prompt, delivery
hermes cron pause/resume ID Control job state
hermes cron run ID Trigger on next tick
hermes cron remove ID Delete a job
hermes cron status Scheduler status
For bounded autonomous lab/orchestrator cron jobs that use file-based state, subagent lanes, artifact publishing, and status transitions (active โ complete/blocked/inactive), see references/autonomous-agent-lab-cron-cycle.md. A reusable verification script template lives at scripts/verify-completion-template.py.
For a worked example of evolving an autonomous lab into a config-driven, themeable, Docker-ready installable product, see references/autonomous-lab-product-architecture.md. For CI, integration testing, pluggable adapter architecture, bounded cycle orchestration, and post-productization patterns, see references/product-maturity-patterns.md.
For the final completion verification checklist โ the explicit audit pattern to run before marking status: complete on an installable-solution mission, see references/autonomous-lab-completion-verification.md.
For the reactivation protocol when a completed lab receives new P0 feedback or the user contradicts a completion claim, see references/autonomous-lab-reactivation-protocol.md.
For the config/CHANGELOG version drift pitfall that occurs when autonomous labs evolve over many cycles, and for the related source vs. published file drift problem where the live web root diverges from the project source, see references/autonomous-lab-version-drift.md.
For adding historical trend tracking (SQLite-backed agent status transitions + vanilla JS SVG sparklines) to an autonomous lab dashboard, see references/history-tracking-sparkline-pattern.md.
For preventing unbounded SQLite growth in long-running labs, see references/autonomous-lab-data-retention.md โ covers automatic per-refresh pruning and a standalone manual prune utility.
For reusable dashboard UX patterns (onboarding tours, data freshness badges, keyboard shortcuts, progressive disclosure inspectors, cross-linking between views), see references/dashboard-ux-patterns.md.
For the daily operational briefing modal โ a one-screen human-first summary of agent counts, blocked work, recent events, health status, and upcoming cron schedules โ see references/daily-briefing-modal.md.
For the aggressive human-first inspector refinement โ when users report that details are hard to understand and the fix is to strip technical labels from the default view โ see references/progressive-disclosure-human-first.md.
For programmatic verification of CSS custom-property theme systems โ catching scoping bugs, confirming theme distinctness, and validating JS switching logic โ see references/theme-system-verification.md.
- For Son's Discord-first autonomous experiments where a channel hosts a repeated multi-agent loop, use the Autonomous Discord Agent Lab pattern: create file-based durable state, a paused cron orchestrator delivered to
discord:<channel_id>, then activate it from a user mission trigger. See references/autonomous-discord-agent-lab.md.
- For verifying that a release package (
tar.gz) is actually installable by third parties and contains no stale artifacts or hardcoded references, see references/release-package-verification.md and the reusable script at scripts/release-verify.sh.
Webhooks
hermes webhook subscribe N Create route at /webhooks/<name>
hermes webhook list List subscriptions
hermes webhook remove NAME Remove a subscription
hermes webhook test NAME Send a test POST
Profiles
hermes profile list List all profiles
hermes profile create NAME Create (--clone, --clone-all, --clone-from)
hermes profile use NAME Set sticky default
hermes profile delete NAME Delete a profile
hermes profile show NAME Show details
hermes profile alias NAME Manage wrapper scripts
hermes profile rename A B Rename a profile
hermes profile export NAME Export to tar.gz
hermes profile import FILE Import from archive
Credential Pools
hermes auth add Interactive credential wizard
hermes auth list [PROVIDER] List pooled credentials
hermes auth remove P INDEX Remove by provider + index
hermes auth reset PROVIDER Clear exhaustion status
Other
hermes insights [--days N] Usage analytics
hermes update Update to latest version
hermes pairing list/approve/revoke DM authorization
hermes plugins list/install/remove Plugin management
hermes honcho setup/status Honcho memory integration (requires honcho plugin)
hermes memory setup/status/off Memory provider config
hermes completion bash|zsh Shell completions
hermes acp ACP server (IDE integration)
hermes claw migrate Migrate from OpenClaw
hermes uninstall Uninstall Hermes
---
Slash Commands (In-Session)
Type these during an interactive chat session. New commands land fairly
often; if something below looks stale, run /help in-session for the
authoritative list or see the [live slash commands reference](https://hermes-agent.nousresearch.com/docs/reference/slash-commands).
The registry of record is hermes_cli/commands.py โ every consumer
(autocomplete, Telegram menu, Slack mapping, /help) derives from it.
Session Control
/new (/reset) Fresh session
/clear Clear screen + new session (CLI)
/retry Resend last message
/undo Remove last exchange
/title [name] Name the session
/compress Manually compress context
/stop Kill background processes
/rollback [N] Restore filesystem checkpoint
/snapshot [sub] Create or restore state snapshots of Hermes config/state (CLI)
/background <prompt> Run prompt in background
/queue <prompt> Queue for next turn
/steer <prompt> Inject a message after the next tool call without interrupting
/agents (/tasks) Show active agents and running tasks
/resume [name] Resume a named session
/goal [text|sub] Set a standing goal Hermes works on across turns until achieved
(subcommands: status, pause, resume, clear)
/redraw Force a full UI repaint (CLI)
Configuration
/config Show config (CLI)
/model [name] Show or change model
/personality [name] Set personality
/reasoning [level] Set reasoning (none|minimal|low|medium|high|xhigh|show|hide)
/verbose Cycle: off โ new โ all โ verbose
/voice [on|off|tts] Voice mode
/yolo Toggle approval bypass
/busy [sub] Control what Enter does while Hermes is working (CLI)
(subcommands: queue, steer, interrupt, status)
/indicator [style] Pick the TUI busy-indicator style (CLI)
(styles: kaomoji, emoji, unicode, ascii)
/footer [on|off] Toggle gateway runtime-metadata footer on final replies
/skin [name] Change theme (CLI)
/statusbar Toggle status bar (CLI)
Tools & Skills
/tools Manage tools (CLI)
/toolsets List toolsets (CLI)
/skills Search/install skills (CLI)
/skill <name> Load a skill into session
/reload-skills Re-scan ~/.hermes/skills/ for added/removed skills
/reload Reload .env variables into the running session (CLI)
/reload-mcp Reload MCP servers
/cron Manage cron jobs (CLI)
/curator [sub] Background skill maintenance (status, run, pin, archive, โฆ)
/kanban [sub] Multi-profile collaboration board (tasks, links, comments)
/plugins List plugins (CLI)
Gateway
/approve Approve a pending command (gateway)
/deny Deny a pending command (gateway)
/restart Restart gateway (gateway)
/sethome Set current chat as home channel (gateway)
/update Update Hermes to latest (gateway)
/topic [sub] Enable or inspect Telegram DM topic sessions (gateway)
/platforms (/gateway) Show platform connection status (gateway)
Utility
/branch (/fork) Branch the current session
/fast Toggle priority/fast processing
/browser Open CDP browser connection
/history Show conversation history (CLI)
/save Save conversation to file (CLI)
/copy [N] Copy the last assistant response to clipboard (CLI)
/paste Attach clipboard image (CLI)
/image Attach local image file (CLI)
Info
/help Show commands
/commands [page] Browse all commands (gateway)
/usage Token usage
/insights [days] Usage analytics
/gquota Show Google Gemini Code Assist quota usage (CLI)
/status Session info (gateway)
/profile Active profile info
/debug Upload debug report (system info + logs) and get shareable links
Exit
/quit (/exit, /q) Exit CLI
---
Key Paths & Config
~/.hermes/config.yaml Main configuration
~/.hermes/.env API keys and secrets
$HERMES_HOME/skills/ Installed skills
~/.hermes/sessions/ Session transcripts
~/.hermes/logs/ Gateway and error logs
~/.hermes/auth.json OAuth tokens and credential pools
~/.hermes/hermes-agent/ Source code (if git-installed)
Profiles use ~/.hermes/profiles/<name>/ with the same layout.
Config Sections
Edit with hermes config edit or hermes config set section.key value.
| Section | Key options |
|---------|-------------|
| model | default, provider, base_url, api_key, context_length |
| agent | max_turns (90), tool_use_enforcement |
| terminal | backend (local/docker/ssh/modal), cwd, timeout (180) |
| compression | enabled, threshold (0.50), target_ratio (0.20) |
| display | skin, tool_progress, show_reasoning, show_cost |
| stt | enabled, provider (local/groq/openai/mistral) |
| tts | provider (edge/elevenlabs/openai/minimax/mistral/neutts) |
| memory | memory_enabled, user_profile_enabled, provider |
| security | tirith_enabled, website_blocklist |
| delegation | model, provider, base_url, api_key, max_iterations (50), reasoning_effort |
| checkpoints | enabled, max_snapshots (50) |
| fallback_model | provider, model, base_url, key_env |
Fallback Providers
Hermes can automatically fail over to a backup provider:model when the primary is unavailable. This is turn-scoped โ each new user message starts with the primary restored; fallback only activates mid-turn when the primary fails.
Configuration ( ~/.hermes/config.yaml):
fallback_model:
provider: opencode-go
model: kimi-k2.6
Or use the interactive manager:
hermes fallback add # interactive picker
hermes fallback list # show fallback chain
hermes fallback remove # remove by index
Legacy note: fallback_model (singular) is the legacy single-fallback key. fallback_providers (list) supports multiple ordered fallbacks. When both exist, fallback_providers takes priority.
Trigger conditions (after exhausting retries where applicable):
- Rate limits (HTTP 429)
- Server errors (HTTP 500, 502, 503)
- Auth failures (HTTP 401, 403) โ immediately
- Not found (HTTP 404) โ immediately
- Invalid / empty responses repeatedly
Supported providers include all standard providers (OpenRouter, Anthropic, OpenCode Go/ Zen, Kimi, etc.) plus custom endpoints with base_url + key_env. Full provider docs: https://hermes-agent.nousresearch.com/docs/integrations/providers
Limitations:
- Subagent delegation does not inherit fallback config
- Cron jobs do not use fallback (use per-job provider/model overrides)
- Auxiliary tasks (vision, compression, etc.) use their own
auxiliary.* provider chain
For a deep-dive with worked examples and model lists, see references/fallback-providers.md.
Full config reference: https://hermes-agent.nousresearch.com/docs/user-guide/configuration
Providers
20+ providers supported. Set via hermes model or hermes setup.
| Provider | Auth | Key env var |
|----------|------|-------------|
| OpenRouter | API key | OPENROUTER_API_KEY |
| Anthropic | API key | ANTHROPIC_API_KEY |
| Nous Portal | OAuth | hermes auth |
| OpenAI Codex | OAuth | hermes auth |
| GitHub Copilot | Token | COPILOT_GITHUB_TOKEN |
| Google Gemini | API key | GOOGLE_API_KEY or GEMINI_API_KEY |
| DeepSeek | API key | DEEPSEEK_API_KEY |
| xAI / Grok | API key | XAI_API_KEY |
| Hugging Face | Token | HF_TOKEN |
| Z.AI / GLM | API key | GLM_API_KEY |
| MiniMax | API key | MINIMAX_API_KEY |
| MiniMax CN | API key | MINIMAX_CN_API_KEY |
| Kimi / Moonshot | API key | KIMI_API_KEY |
| Alibaba / DashScope | API key | DASHSCOPE_API_KEY |
| Xiaomi MiMo | API key | XIAOMI_API_KEY |
| Kilo Code | API key | KILOCODE_API_KEY |
| AI Gateway (Vercel) | API key | AI_GATEWAY_API_KEY |
| OpenCode Zen | API key | OPENCODE_ZEN_API_KEY |
| OpenCode Go | API key | OPENCODE_GO_API_KEY |
| Qwen OAuth | OAuth | hermes auth add qwen-oauth |
| Custom endpoint | Config | model.base_url + model.api_key in config.yaml |
| GitHub Copilot ACP | External | COPILOT_CLI_PATH or Copilot CLI |
Full provider docs: https://hermes-agent.nousresearch.com/docs/integrations/providers
Toolsets
Enable/disable via hermes tools (interactive) or hermes tools enable/disable NAME.
| Toolset | What it provides |
|---------|-----------------|
| web | Web search and content extraction |
| search | Web search only (subset of web) |
| browser | Browser automation (Browserbase, Camofox, or local Chromium) |
| terminal | Shell commands and process management |
| file | File read/write/search/patch |
| code_execution | Sandboxed Python execution |
| vision | Image analysis |
| image_gen | AI image generation |
| video | Video analysis and generation |
| tts | Text-to-speech |
| skills | Skill browsing and management |
| memory | Persistent cross-session memory |
| session_search | Search past conversations |
| delegation | Subagent task delegation |
| cronjob | Scheduled task management |
| clarify | Ask user clarifying questions |
| messaging | Cross-platform message sending |
| todo | In-session task planning and tracking |
| kanban | Multi-agent work-queue tools (gated to workers) |
| debugging | Extra introspection/debug tools (off by default) |
| safe | Minimal, low-risk toolset for locked-down sessions |
| spotify | Spotify playback and playlist control |
| homeassistant | Smart home control (off by default) |
| discord | Discord integration tools |
| discord_admin | Discord admin/moderation tools |
| feishu_doc | Feishu (Lark) document tools |
| feishu_drive | Feishu (Lark) drive tools |
| yuanbao | Yuanbao integration tools |
| rl | Reinforcement learning tools (off by default) |
| moa | Mixture of Agents (off by default) |
Full enumeration lives in toolsets.py as the TOOLSETS dict; _HERMES_CORE_TOOLS is the default bundle most platforms inherit from.
Tool changes take effect on /reset (new session). They do NOT apply mid-conversation to preserve prompt caching.
---
Security & Privacy Toggles
Common "why is Hermes doing X to my output / tool calls / commands?" toggles โ and the exact commands to change them. Most of these need a fresh session (/reset in chat, or start a new hermes invocation) because they're read once at startup.
Secret redaction in tool output
Secret redaction is off by default โ tool output (terminal stdout, read_file, web content, subagent summaries, etc.) passes through unmodified. If the user wants Hermes to auto-mask strings that look like API keys, tokens, and secrets before they enter the conversation context and logs:
hermes config set security.redact_secrets true # enable globally
Restart required. security.redact_secrets is snapshotted at import time โ toggling it mid-session (e.g. via export HERMES_REDACT_SECRETS=true from a tool call) will NOT take effect for the running process. Tell the user to run hermes config set security.redact_secrets true in a terminal, then start a new session. This is deliberate โ it prevents an LLM from flipping the toggle on itself mid-task.
Disable again with:
hermes config set security.redact_secrets false
PII redaction in gateway messages
Separate from secret redaction. When enabled, the gateway hashes user IDs and strips phone numbers from the session context before it reaches the model:
hermes config set privacy.redact_pii true # enable
hermes config set privacy.redact_pii false # disable (default)
Command approval prompts
By default (approvals.mode: manual), Hermes prompts the user before running shell commands flagged as destructive (rm -rf, git reset --hard, etc.). The modes are:
manual โ always prompt (default)
smart โ use an auxiliary LLM to auto-approve low-risk commands, prompt on high-risk
off โ skip all approval prompts (equivalent to --yolo)
hermes config set approvals.mode smart # recommended middle ground
hermes config set approvals.mode off # bypass everything (not recommended)
Per-invocation bypass without changing config:
hermes --yolo โฆ
export HERMES_YOLO_MODE=1
Note: YOLO / approvals.mode: off does NOT turn off secret redaction. They are independent.
Shell hooks allowlist
Some shell-hook integrations require explicit allowlisting before they fire. Managed via ~/.hermes/shell-hooks-allowlist.json โ prompted interactively the first time a hook wants to run.
Disabling the web/browser/image-gen tools
To keep the model away from network or media tools entirely, open hermes tools and toggle per-platform. Takes effect on next session (/reset). See the Tools & Skills section above.
---
Voice & Transcription
STT (Voice โ Text)
Voice messages from messaging platforms are auto-transcribed.
Provider priority (auto-detected):
1. Local faster-whisper โ free, no API key: pip install faster-whisper
2. Groq Whisper โ free tier: set GROQ_API_KEY
3. OpenAI Whisper โ paid: set VOICE_TOOLS_OPENAI_KEY
4. Mistral Voxtral โ set MISTRAL_API_KEY
Config:
stt:
enabled: true
provider: local # local, groq, openai, mistral
local:
model: base # tiny, base, small, medium, large-v3
TTS (Text โ Voice)
| Provider | Env var | Free? |
|----------|---------|-------|
| Edge TTS | None | Yes (default) |
| ElevenLabs | ELEVENLABS_API_KEY | Free tier |
| OpenAI | VOICE_TOOLS_OPENAI_KEY | Paid |
| MiniMax | MINIMAX_API_KEY | Paid |
| Mistral (Voxtral) | MISTRAL_API_KEY | Paid |
| NeuTTS (local) | None (pip install neutts[all] + espeak-ng) | Free |
Voice commands: /voice on (voice-to-voice), /voice tts (always voice), /voice off.
---
Spawning Additional Hermes Instances
Run additional Hermes processes as fully independent subprocesses โ separate sessions, tools, and environments.
When to Use This vs delegate_task
| | delegate_task | Spawning hermes process |
|-|-----------------|--------------------------|
| Isolation | Separate conversation, shared process | Fully independent process |
| Duration | Minutes (bounded by parent loop) | Hours/days |
| Tool access | Subset of parent's tools | Full tool access |
| Interactive | No | Yes (PTY mode) |
| Use case | Quick parallel subtasks | Long autonomous missions |
One-Shot Mode
terminal(command="hermes chat -q 'Research GRPO papers and write summary to ~/research/grpo.md'", timeout=300)
Background for long tasks:
terminal(command="hermes chat -q 'Set up CI/CD for ~/myapp'", background=true)
Interactive PTY Mode (via tmux)
Hermes uses prompt_toolkit, which requires a real terminal. Use tmux for interactive spawning:
Start
terminal(command="tmux new-session -d -s agent1 -x 120 -y 40 'hermes'", timeout=10)
Wait for startup, then send a message
terminal(command="sleep 8 && tmux send-keys -t agent1 'Build a FastAPI auth service' Enter", timeout=15)
Read output
terminal(command="sleep 20 && tmux capture-pane -t agent1 -p", timeout=5)
Send follow-up
terminal(command="tmux send-keys -t agent1 'Add rate limiting middleware' Enter", timeout=5)
Exit
terminal(command="tmux send-keys -t agent1 '/exit' Enter && sleep 2 && tmux kill-session -t agent1", timeout=10)
Multi-Agent Coordination
Agent A: backend
terminal(command="tmux new-session -d -s backend -x 120 -y 40 'hermes -w'", timeout=10)
terminal(command="sleep 8 && tmux send-keys -t backend 'Build REST API for user management' Enter", timeout=15)
Agent B: frontend
terminal(command="tmux new-session -d -s frontend -x 120 -y 40 'hermes -w'", timeout=10)
terminal(command="sleep 8 && tmux send-keys -t frontend 'Build React dashboard for user management' Enter", timeout=15)
Check progress, relay context between them
terminal(command="tmux capture-pane -t backend -p | tail -30", timeout=5)
terminal(command="tmux send-keys -t frontend 'Here is the API schema from the backend agent: ...' Enter", timeout=5)
Session Resume
Resume most recent session
terminal(command="tmux new-session -d -s resumed 'hermes --continue'", timeout=10)
Resume specific session
terminal(command="tmux new-session -d -s resumed 'hermes --resume 20260225_143052_a1b2c3'", timeout=10)
Tips
- Prefer
delegate_task for quick subtasks โ less overhead than spawning a full process
- Use
-w (worktree mode) when spawning agents that edit code โ prevents git conflicts
- Set timeouts for one-shot mode โ complex tasks can take 5-10 minutes
- Use
hermes chat -q for fire-and-forget โ no PTY needed
- Use tmux for interactive sessions โ raw PTY mode has
\r vs \n issues with prompt_toolkit
- For scheduled tasks, use the
cronjob tool instead of spawning โ handles delivery and retry
---
Durable & Background Systems
Four systems run alongside the main conversation loop. Quick reference
here; full developer notes live in AGENTS.md, user-facing docs under
website/docs/user-guide/features/.
Delegation (delegate_task)
Synchronous subagent spawn โ the parent waits for the child's summary
before continuing its own loop. Isolated context + terminal session.
- Single:
delegate_task(goal, context, toolsets).
- Batch:
delegate_task(tasks=[{goal, ...}, ...]) runs children in
parallel, capped by delegation.max_concurrent_children (default 3).
- Roles:
leaf (default; cannot re-delegate) vs orchestrator
(can spawn its own workers, bounded by delegation.max_spawn_depth).
- Not durable. If the parent is interrupted, the child is
cancelled. For work that must outlive the turn, use cronjob or
terminal(background=True, notify_on_complete=True).
Config: delegation.* in config.yaml.
Tuning max_concurrent_children
Default is 3. Rule of thumb for raising it:
- Light tasks (web search, file grep): up to
6-8
- Medium tasks (code execution, browser):
4-5
- Heavy tasks (builds, large data):
2-3
- Actual bottleneck is usually the API rate limit, not local CPU/RAM. On a 10-core M4 with 16GB RAM, CPU is rarely the constraint.
- Formula: start at
5, raise only if profiling shows idle time between API responses.
Cron (scheduled jobs)
Durable scheduler โ cron/jobs.py + cron/scheduler.py. Drive it via
the cronjob tool, the hermes cron CLI (list, add, edit,
pause, resume, run, remove), or the /cron slash command.
- Schedules: duration (
"30m", "2h"), "every" phrase
( "every monday 9am"), 5-field cron ( "0 9 *"), or ISO timestamp.
- Per-job knobs:
skills, model/provider override, script
(pre-run data collection; no_agent=True makes the script the whole
job), context_from (chain job A's output into job B), workdir
(run in a specific dir with its AGENTS.md / CLAUDE.md loaded),
multi-platform delivery.
- Invariants: 3-minute hard interrupt per run,
.tick.lock file
prevents duplicate ticks across processes, cron sessions pass
skip_memory=True by default, and cron deliveries are framed with a
header/footer instead of being mirrored into the target gateway
session (keeps role alternation intact).
User docs: https://hermes-agent.nousresearch.com/docs/user-guide/features/cron
Curator (skill lifecycle)
Background maintenance for agent-created skills. Tracks usage, marks
idle skills stale, archives stale ones, keeps a pre-run tar.gz backup
so nothing is lost.
- CLI:
hermes curator <verb> โ status, run, pause, resume,
pin, unpin, archive, restore, prune, backup, rollback.
- Slash:
/curator <subcommand> mirrors the CLI.
- Scope: only touches skills with
created_by: "agent" provenance.
Bundled + hub-installed skills are off-limits. Never deletes โ
max destructive action is archive. Pinned skills are exempt from
every auto-transition and every LLM review pass.
- Telemetry: sidecar at
~/.hermes/skills/.usage.json holds
per-skill use_count, view_count, patch_count,
last_activity_at, state, pinned.
Config: curator.* (enabled, interval_hours, min_idle_hours,
stale_after_days, archive_after_days, backup.*).
User docs: https://hermes-agent.nousresearch.com/docs/user-guide/features/curator
Dreaming (periodic memory/skill consolidation)
For Anthropic-style "dreaming" workflows, combine cron + session_search + memory + skills + curator into a scheduled review loop. Start with a weekly, proposal-only report that audits recent sessions, repeated user corrections, memory conflicts, skill patch candidates, and cron/automation improvements. Do not automatically delete/replace memory or patch/archive skills unless the user explicitly approves the proposed changes. See references/weekly-dreaming-routine.md for the recommended prompt, report format, safety policy, and cron creation pattern.
Kanban (multi-agent work queue)
Durable SQLite board for multi-profile / multi-worker collaboration.
Users drive it via hermes kanban <verb>; dispatcher-spawned workers
see a focused kanban_* toolset gated by HERMES_KANBAN_TASK so the
schema footprint is zero outside worker processes.
- CLI verbs (common):
init, create, list (alias ls),
show, assign, link, unlink, comment, complete, block,
unblock, archive, tail. Less common: watch, stats, runs,
log, dispatch, daemon, gc.
- Worker toolset:
kanban_show, kanban_complete, kanban_block,
kanban_heartbeat, kanban_comment, kanban_create, kanban_link.
- Dispatcher runs inside the gateway by default
( kanban.dispatch_in_gateway: true) โ reclaims stale claims,
promotes ready tasks, atomically claims, spawns assigned profiles.
Auto-blocks a task after ~5 consecutive spawn failures.
- Isolation: board is the hard boundary (workers get
HERMES_KANBAN_BOARD pinned in env); tenant is a soft namespace
within a board for workspace-path + memory-key isolation.
User docs: https://hermes-agent.nousresearch.com/docs/user-guide/features/kanban
Log Relay (Hermes โ Discord)
A background Python script that tails ~/.hermes/logs/*.log and batches lines to a Discord channel. Includes session-ID extraction, rate-limit handling, and auto-restart via launchd/systemd. Useful for remote monitoring and audit trails.
- Reference:
references/discord-log-relay.md โ full setup, tuning, macOS/Linux service install, pitfalls.
- Template:
templates/discord-log-relay.py โ copy, set CHANNEL_ID, and deploy.
- Discord operations:
references/discord-operating-planes.md โ channel-purpose routing, periodic-summary vs Dreaming report formats, and safety/cost notes for Discord-first Hermes deployments.
Key pitfall: ask the user about batch frequency upfront rather than defaulting to real-time streaming. Most users prefer 10-minute or hourly batches. High-volume raw logs should be batched, summarized, or stored out-of-band; avoid Discord message storms during error loops.
Weekly Dreaming / Memory Curation
For long-running Hermes deployments, users may want an Anthropic-style "Dreaming" loop: a scheduled review that consolidates experience, proposes memory/skill/cron changes, and identifies what to keep, weaken, archive, or delete. Hermes has the building blocks (sessions, session_search, memory, skills, curator, cron), but the safe default is proposal mode:
1. Inspect recent usage and sessions.
2. Extract repeated success patterns, failure patterns, and user corrections.
3. Propose memory updates/removals without applying them silently.
4. Propose skill patches/archive candidates and cron/reporting improvements.
5. End with explicit approval checkboxes.
Do not silently rewrite or delete memory/skills from a Dreaming report unless the user explicitly authorized automatic application. See references/discord-operating-planes.md for a report template and routing heuristics.
---
Windows-Specific Quirks
Hermes runs natively on Windows (PowerShell, cmd, Windows Terminal, git-bash
mintty, VS Code integrated terminal). Most of it just works, but a handful
of differences between Win32 and POSIX have bitten us โ document new ones
here as you hit them so the next person (or the next session) doesn't
rediscover them from scratch.
Input / Keybindings
Alt+Enter doesn't insert a newline. Windows Terminal intercepts Alt+Enter
at the terminal layer to toggle fullscreen โ the keystroke never reaches
prompt_toolkit. Use Ctrl+Enter instead. Windows Terminal delivers
Ctrl+Enter as LF ( c-j), distinct from plain Enter ( c-m / CR), and the
CLI binds c-j to newline insertion on win32 only (see
_bind_prompt_submit_keys + the Windows-only c-j binding in cli.py).
Side effect: the raw Ctrl+J keystroke also inserts a newline on Windows โ
unavoidable, because Windows Terminal collapses Ctrl+Enter and Ctrl+J to
the same keycode at the Win32 console API layer. No conflicting binding
existed for Ctrl+J on Windows, so this is a harmless side effect.
mintty / git-bash behaves the same (fullscreen on Alt+Enter) unless you
disable Alt+Fn shortcuts in Options โ Keys. Easier to just use Ctrl+Enter.
Diagnosing keybindings. Run python scripts/keystroke_diagnostic.py
(repo root) to see exactly how prompt_toolkit identifies each keystroke
in the current terminal. Answers questions like "does Shift+Enter come
through as a distinct key?" (almost never โ most terminals collapse it
to plain Enter) or "what byte sequence is my terminal sending for
Ctrl+Enter?" This is how the Ctrl+Enter = c-j fact was established.
Config / Files
HTTP 400 "No models provided" on first run. config.yaml was saved
with a UTF-8 BOM (common when Windows apps write it). Re-save as UTF-8
without BOM. hermes config edit writes without BOM; manual edits in
Notepad are the usual culprit.
execute_code / Sandbox
WinError 10106 ("The requested service provider could not be loaded
or initialized") from the sandbox child process โ it can't create an
AF_INET socket, so the loopback-TCP RPC fallback fails before
connect(). Root cause is usually not a broken Winsock LSP; it's
Hermes's own env scrubber dropping SYSTEMROOT / WINDIR / COMSPEC
from the child env. Python's socket module needs SYSTEMROOT to locate
mswsock.dll. Fixed via the _WINDOWS_ESSENTIAL_ENV_VARS allowlist in
tools/code_execution_tool.py. If you still hit it, echo os.environ
inside an execute_code block to confirm SYSTEMROOT is set. Full
diagnostic recipe in references/execute-code-sandbox-env-windows.md.
Testing / Contributing
scripts/run_tests.sh doesn't work as-is on Windows โ it looks for
POSIX venv layouts ( .venv/bin/activate). The Hermes-installed venv at
venv/Scripts/ has no pip or pytest either (stripped for install size).
Workaround: install pytest + pytest-xdist + pyyaml into a system Python
3.11 user site, then invoke pytest directly with PYTHONPATH set:
"/c/Program Files/Python311/python" -m pip install --user pytest pytest-xdist pyyaml
export PYTHONPATH="$(pwd)"
"/c/Program Files/Python311/python" -m pytest tests/foo/test_bar.py -v --tb=short -n 0
Use -n 0, not -n 4 โ pyproject.toml's default addopts already
includes -n, and the wrapper's CI-parity guarantees don't apply off POSIX.
POSIX-only tests need skip guards. Common markers already in the codebase:
- Symlinks โ elevated privileges on Windows
0o600 file modes โ POSIX mode bits not enforced on NTFS by default
signal.SIGALRM โ Unix-only (see tests/conftest.py::_enforce_test_timeout)
- Winsock / Windows-specific regressions โ
@pytest.mark.skipif(sys.platform != "win32", ...)
Use the existing skip-pattern style (sys.platform == "win32" or
sys.platform.startswith("win")) to stay consistent with the rest of the
suite.
Path / Filesystem
Line endings. Git may warn LF will be replaced by CRLF the next time
Git touches it. Cosmetic โ the repo's .gitattributes normalizes. Don't
let editors auto-convert committed POSIX-newline files to CRLF.
Forward slashes work almost everywhere. C:/Users/... is accepted by
every Hermes tool and most Windows APIs. Prefer forward slashes in code
and logs โ avoids shell-escaping backslashes in bash.
---
Troubleshooting
Voice not working
1. Check stt.enabled: true in config.yaml
2. Verify provider: pip install faster-whisper or set API key
3. In gateway: /restart. In CLI: exit and relaunch.
Tool not available
1. hermes tools โ check if toolset is enabled for your platform
2. Some tools need env vars (check .env)
3. /reset after enabling tools
Model/provider issues
1. hermes doctor โ check config and dependencies
2. hermes auth add <provider> โ re-authenticate OAuth providers (use --type oauth)
3. Check .env has the right API key
4. Copilot 403: gh auth login tokens do NOT work for Copilot API. You must use the Copilot-specific OAuth device code flow via hermes model โ GitHub Copilot.
Changes not taking effect
- Tools/skills:
/reset starts a new session with updated toolset
- Config changes: In gateway:
/restart. In CLI: exit and relaunch.
- Code changes: Restart the CLI or gateway process
Deployed web dashboard shows stale CSS or theme changes
- Browser cache: Add
?v=N cache-busting query strings to CSS/JS/theme links in HTML.
- Service Worker cache: Bump
CACHE_NAME in sw.js to invalidate old shell caches.
- Automated bump script: For projects with multiple HTML entry points (dashboard, gather, etc.), use
scripts/bump-build.py to atomically update all build badges, cache-busting query strings, and service worker cache names in one command. See references/autonomous-lab-version-drift.md for usage.
- Data freshness: Use
fetch(url, {cache:'no-store'}) for live JSON feeds.
- Auto-detection: Embed
data-build in <html> and compare server build vs loaded build on page load to show a "new version available" banner. See references/static-site-cache-invalidation.md for the full diagnostic recipe and auto-detection pattern.
- Theme switcher reliability: If theme switching works in Chrome but not Samsung Internet, or feels broken on mobile, see
references/theme-switcher-reliability.md for the create-new-link โ load โ remove-old pattern.
- Emergency recovery: If a bad deploy breaks the main app JS, users need a standalone reset page. See
references/emergency-reset-page.md for a zero-dependency reset.html that clears Service Workers and caches without relying on the main app's JS.
Dashboard inspector feels too technical
- The default inspector view should contain only plain-language sentences: headline, "what they're doing now", "why it matters", and a silent visual progress bar (no text label).
- Move all technical fields (source IDs, confidence scores, progress labels, status slugs, badges) behind a "Show technical details" toggle.
- If users say "details are hard to understand," the fix is to remove more fields from the default view, not to add explanations. Explanations of technical fields are still technical.
- See
references/progressive-disclosure-human-first.md for the aggressive simplification pattern.
Pixel-art characters look wrong on mobile
- Decorative CSS elements (cheeks, ears, tails, badges) can be misread as facial features or appendages when avatars shrink below ~50 px.
- Hide them inside
@media (max-width:480px) so only the essential silhouette remains.
- See
references/pixel-art-mobile-readability.md for the exact selectors and rationale.
Skills not showing
1. hermes skills list โ verify installed
2. hermes skills config โ check platform enablement
3. Load explicitly: /skill name or hermes -s name
Gateway issues
Check logs first:
grep -i "failed to send\|error" ~/.hermes/logs/gateway.log | tail -20
Common gateway problems:
- Gateway dies on SSH logout: Enable linger:
sudo loginctl enable-linger $USER
- Gateway dies on WSL2 close: WSL2 requires
systemd=true in /etc/wsl.conf for systemd services to work. Without it, gateway falls back to nohup (dies when session closes).
- Gateway crash loop: Reset the failed state:
systemctl --user reset-failed hermes-gateway
- macOS: bot shows offline after idle time: The gateway runs as a user agent (
LimitLoadToSessionType=Aqua), so macOS suspends it when the system sleeps. The platform websocket drops and the bot appears offline until the network returns. Fix: keep the Mac awake (System Settings -> Energy -> Prevent automatic sleeping, or caffeinate -d -i -s -u &). Low Power Mode makes this worse, not better. See references/macos-gateway-sleep-disconnect.md for the full diagnostic recipe.
Platform-specific issues
- Discord bot silent: Must enable Message Content Intent in Bot โ Privileged Gateway Intents. See full Discord setup reference:
references/discord-gateway-setup.md.
- Slack bot only works in DMs: Must subscribe to
message.channels event. Without it, the bot ignores public channels.
- Windows-specific issues (
Alt+Enter newline, WinError 10106, UTF-8 BOM config, test suite, line endings): see the dedicated Windows-Specific Quirks section above.
Auxiliary models not working
If auxiliary tasks (vision, compression, session_search) fail silently, the auto provider can't find a backend. Either set OPENROUTER_API_KEY or GOOGLE_API_KEY, or explicitly configure each auxiliary task's provider:
hermes config set auxiliary.vision.provider <your_provider>
hermes config set auxiliary.vision.model <model_name>
Full system auth provisioning
For a one-shot workflow to maximize available credentials โ installing gh, generating SSH keys, configuring git, enabling all Hermes toolsets, and auditing current auth state โ see references/system-auth-setup.md.
Editing large files with patch
When a file is read with read_file(offset=...) (pagination), the tool warns that the view is partial. If you attempt patch without re-reading the full file first, you will likely hit non-unique match errors or corrupt the file. Fix: always call read_file without offset to load the whole file before patching. The tool explicitly warns: "โฆwas last read with offset/limit pagination (partial view). Re-read the whole file before overwriting it." โ heed this warning. For append-only updates (e.g., adding a cycle log entry to state.md), do not use terminal(command="cat >> file << 'EOF'...EOF") โ the terminal tool on macOS/Linux misinterprets heredoc << as backgrounding and fails. Instead, write a short Python script via write_file and execute it with terminal(command="python3 /tmp/script.py"). See references/terminal-heredoc-workaround.md for the full pattern.
Sibling subagent file overwrites
When multiple subagents are running in parallel (e.g. via delegate_task batch mode or kanban worker lanes), a file may be modified by one subagent while another is about to write to it. If you use write_file or patch on a file that was last read before a sibling subagent modified it, your write may silently truncate or revert the sibling's changes. The tool may show a warning like "this file was modified by sibling subagent X but this agent never read it."
Fix:
1. Heed the warning. If the tool reports a sibling modification, re-read the file with read_file before writing.
2. Prefer patch over write_file for partial updates โ patch only changes the matched region and is less likely to wipe unrelated content.
3. If the file is already published/deployed, and the local working copy gets corrupted, recover from the published copy:
cp ~/hermes-web/agent-pets/css/dashboard.css ~/.hermes/autonomous-agent-lab/pixel-pet-ops/web/css/dashboard.css
4. For append-only updates, write a small Python script and execute it rather than using write_file on the whole file.
Prevention: In kanban/multi-agent workflows, assign file-level ownership so only one worker touches each file. If parallel workers must edit the same file, have them write to separate temp files and let the orchestrator merge.
---
Windows-Specific Quirks
| Looking for... | Location |
|----------------|----------|
| Config options | hermes config edit or [Configuration docs](https://hermes-agent.nousresearch.com/docs/user-guide/configuration) |
| Available tools | hermes tools list or [Tools reference](https://hermes-agent.nousresearch.com/docs/reference/tools-reference) |
| Slash commands | /help in session or [Slash commands reference](https://hermes-agent.nousresearch.com/docs/reference/slash-commands) |
| Skills catalog | hermes skills browse or [Skills catalog](https://hermes-agent.nousresearch.com/docs/reference/skills-catalog) |
| Provider setup | hermes model or [Providers guide](https://hermes-agent.nousresearch.com/docs/integrations/providers) |
| Platform setup | hermes gateway setup or [Messaging docs](https://hermes-agent.nousresearch.com/docs/user-guide/messaging/) |
| MCP servers | hermes mcp list or [MCP guide](https://hermes-agent.nousresearch.com/docs/user-guide/features/mcp) |
| Profiles | hermes profile list or [Profiles docs](https://hermes-agent.nousresearch.com/docs/user-guide/profiles) |
| Cron jobs | hermes cron list or [Cron docs](https://hermes-agent.nousresearch.com/docs/user-guide/features/cron) |
| Memory | hermes memory status or [Memory docs](https://hermes-agent.nousresearch.com/docs/user-guide/features/memory) |
| Env variables | hermes config env-path or [Env vars reference](https://hermes-agent.nousresearch.com/docs/reference/environment-variables) |
| CLI commands | hermes --help or [CLI reference](https://hermes-agent.nousresearch.com/docs/reference/cli-commands) |
| Gateway logs | ~/.hermes/logs/gateway.log |
| Session files | ~/.hermes/sessions/ or hermes sessions browse |
| Source code | ~/.hermes/hermes-agent/ |
---
Contributor Quick Reference
For occasional contributors and PR authors. Full developer docs: https://hermes-agent.nousresearch.com/docs/developer-guide/
Project Layout
hermes-agent/
โโโ run_agent.py # AIAgent โ core conversation loop
โโโ model_tools.py # Tool discovery and dispatch
โโโ toolsets.py # Toolset definitions
โโโ cli.py # Interactive CLI (HermesCLI)
โโโ hermes_state.py # SQLite session store
โโโ agent/ # Prompt builder, context compression, memory, model routing, credential pooling, skill dispatch
โโโ hermes_cli/ # CLI subcommands, config, setup, commands
โ โโโ commands.py # Slash command registry (CommandDef)
โ โโโ config.py # DEFAULT_CONFIG, env var definitions
โ โโโ main.py # CLI entry point and argparse
โโโ tools/ # One file per tool
โ โโโ registry.py # Central tool registry
โโโ gateway/ # Messaging gateway
โ โโโ platforms/ # Platform adapters (telegram, discord, etc.)
โโโ cron/ # Job scheduler
โโโ tests/ # ~3000 pytest tests
โโโ website/ # Docusaurus docs site
Config: ~/.hermes/config.yaml (settings), ~/.hermes/.env (API keys).
Adding a Tool (3 files)
1. Create tools/your_tool.py:
import json, os
from tools.registry import registry
def check_requirements() -> bool:
return bool(os.getenv("EXAMPLE_API_KEY"))
def example_tool(param: str, task_id: str = None) -> str:
return json.dumps({"success": True, "data": "..."})
registry.register(
name="example_tool",
toolset="example",
schema={"name": "example_tool", "description": "...", "parameters": {...}},
handler=lambda args, **kw: example_tool(
param=args.get("param", ""), task_id=kw.get("task_id")),
check_fn=check_requirements,
requires_env=["EXAMPLE_API_KEY"],
)
2. Add to toolsets.py โ _HERMES_CORE_TOOLS list.
Auto-discovery: any tools/*.py file with a top-level registry.register() call is imported automatically โ no manual list needed.
All handlers must return JSON strings. Use get_hermes_home() for paths, never hardcode ~/.hermes.
Adding a Slash Command
1. Add CommandDef to COMMAND_REGISTRY in hermes_cli/commands.py
2. Add handler in cli.py โ process_command()
3. (Optional) Add gateway handler in gateway/run.py
All consumers (help text, autocomplete, Telegram menu, Slack mapping) derive from the central registry automatically.
Agent Loop (High Level)
run_conversation():
1. Build system prompt
2. Loop while iterations < max:
a. Call LLM (OpenAI-format messages + tool schemas)
b. If tool_calls โ dispatch each via handle_function_call() โ append results โ continue
c. If text response โ return
3. Context compression triggers automatically near token limit
Testing
python -m pytest tests/ -o 'addopts=' -q # Full suite
python -m pytest tests/tools/ -q # Specific area
- Tests auto-redirect
HERMES_HOME to temp dirs โ never touch real ~/.hermes/
- Run full suite before pushing any change
- Use
-o 'addopts=' to clear any baked-in pytest flags
Windows contributors: scripts/run_tests.sh currently looks for POSIX venvs ( .venv/bin/activate / venv/bin/activate) and will error out on Windows where the layout is venv/Scripts/activate + python.exe. The Hermes-installed venv at venv/Scripts/ also has no pip or pytest โ it's stripped for end-user install size. Workaround: install pytest + pytest-xdist + pyyaml into a system Python 3.11 user site ( /c/Program Files/Python311/python -m pip install --user pytest pytest-xdist pyyaml), then run tests directly:
export PYTHONPATH="$(pwd)"
"/c/Program Files/Python311/python" -m pytest tests/tools/test_foo.py -v --tb=short -n 0
Use -n 0 (not -n 4) because pyproject.toml's default addopts already includes -n, and the wrapper's CI-parity story doesn't apply off-POSIX.
Cross-platform test guards: tests that use POSIX-only syscalls need a skip marker. Common ones already in the codebase:
- Symlink creation โ
@pytest.mark.skipif(sys.platform == "win32", reason="Symlinks require elevated privileges on Windows") (see tests/cron/test_cron_script.py)
- POSIX file modes (0o600, etc.) โ
@pytest.mark.skipif(sys.platform.startswith("win"), reason="POSIX mode bits not enforced on Windows") (see tests/hermes_cli/test_auth_toctou_file_modes.py)
signal.SIGALRM โ Unix-only (see tests/conftest.py::_enforce_test_timeout)
- Live Winsock / Windows-specific regression tests โ
@pytest.mark.skipif(sys.platform != "win32", reason="Windows-specific regression")
Monkeypatching sys.platform is not enough when the code under test also calls platform.system() / platform.release() / platform.mac_ver(). Those functions re-read the real OS independently, so a test that sets sys.platform = "linux" on a Windows runner will still see platform.system() == "Windows" and route through the Windows branch. Patch all three together:
monkeypatch.setattr(sys, "platform", "linux")
monkeypatch.setattr(platform, "system", lambda: "Linux")
monkeypatch.setattr(platform, "release", lambda: "6.8.0-generic")
See tests/agent/test_prompt_builder.py::TestEnvironmentHints for a worked example.
Extending the system prompt's execution-environment block
Factual guidance about the host OS, user home, cwd, terminal backend, and shell (bash vs. PowerShell on Windows) is emitted from agent/prompt_builder.py::build_environment_hints(). This is also where the WSL hint and per-backend probe logic live. The convention:
- Local terminal backend โ emit host info (OS,
$HOME, cwd) + Windows-specific notes (hostname โ username, terminal uses bash not PowerShell).
- Remote terminal backend (anything in
_REMOTE_TERMINAL_BACKENDS: docker, singularity, modal, daytona, ssh, vercel_sandbox, managed_modal) โ suppress host info entirely and describe only the backend. A live uname/whoami/pwd probe runs inside the backend via tools.environments.get_environment(...).execute(...), cached per process in _BACKEND_PROBE_CACHE, with a static fallback if the probe times out.
- Key fact for prompt authoring: when
TERMINAL_ENV != "local", every file tool (read_file, write_file, patch, search_files) runs inside the backend container, not on the host. The system prompt must never describe the host in that case โ the agent can't touch it.
Full design notes, the exact emitted strings, and testing pitfalls:
references/prompt-builder-environment-hints.md.
Refactor-safety pattern (POSIX-equivalence guard): when you extract inline logic into a helper that adds Windows/platform-specific behavior, keep a _legacy_<name> oracle function in the test file that's a verbatim copy of the old code, then parametrize-diff against it. Example: tests/tools/test_code_execution_windows_env.py::TestPosixEquivalence. This locks in the invariant that POSIX behavior is bit-for-bit identical and makes any future drift fail loudly with a clear diff.
Commit Conventions
type: concise subject line
Optional body.
Types: fix:, feat:, refactor:, docs:, chore:
Key Rules
- Never break prompt caching โ don't change context, tools, or system prompt mid-conversation
- Message role alternation โ never two assistant or two user messages in a row
- Use
get_hermes_home() from hermes_constants for all paths (profile-safe)
- Config values go in
config.yaml, secrets go in .env
- New tools need a
check_fn so they only appear when requirements are met
[IMPORTANT: The user has invoked the "kanban-orchestrator" skill, indicating they want you to follow its instructions. The full skill content is loaded below.]
---
name: kanban-orchestrator
description: Decomposition playbook + anti-temptation rules for an orchestrator profile routing work through Kanban. The "don't do the work yourself" rule and the basic lifecycle are auto-injected into every kanban worker's system prompt; this skill is the deeper playbook when you're specifically playing the orchestrator role.
version: 3.0.0
platforms: [linux, macos, windows]
metadata:
hermes:
tags: [kanban, multi-agent, orchestration, routing]
related_skills: [kanban-worker]
---
Kanban Orchestrator โ Decomposition Playbook
> The core worker lifecycle (including the kanban_create fan-out pattern and the "decompose, don't execute" rule) is auto-injected into every kanban process via the KANBAN_GUIDANCE system-prompt block. This skill is the deeper playbook when you're an orchestrator profile whose whole job is routing.
Profiles are user-configured โ not a fixed roster
Hermes setups vary widely. Some users run a single profile that does everything; some run a small fleet (docker-worker, cron-worker); some run a curated specialist team they've named themselves. There is no default specialist roster โ the orchestrator skill does not know what profiles exist on this machine.
Before fanning out, you must ground the decomposition in the profiles that actually exist. The dispatcher silently fails to spawn unknown assignee names โ it doesn't autocorrect, doesn't suggest, doesn't fall back. So a card assigned to researcher on a setup that only has docker-worker just sits in ready forever.
Step 0: discover available profiles before planning.
Use one of these:
hermes profile list โ prints the table of profiles configured on this machine. Run it through your terminal tool if you have one; otherwise ask the user.
kanban_list(assignee="<some-name>") โ sanity-check a single name. Returns an empty list (rather than an error) for an unknown assignee, so this only confirms a name you're already considering.
- Just ask the user. "What profiles do you have set up?" is a fine first turn when the goal needs more than one specialist.
Cache the result in your working memory for the rest of the conversation. Re-asking every turn wastes a tool call.
When to use the board (vs. just doing the work)
Create Kanban tasks when any of these are true:
1. Multiple specialists are needed. Research + analysis + writing is three profiles.
2. The work should survive a crash or restart. Long-running, recurring, or important.
3. The user might want to interject. Human-in-the-loop at any step.
4. Multiple subtasks can run in parallel. Fan-out for speed.
5. Review / iteration is expected. A reviewer profile loops on drafter output.
6. The audit trail matters. Board rows persist in SQLite forever.
If none of those apply โ it's a small one-shot reasoning task โ use delegate_task instead or answer the user directly.
The anti-temptation rules
Your job description says "route, don't execute." The rules that enforce that:
- Do not execute the work yourself. Your restricted toolset usually doesn't even include terminal/file/code/web for implementation. If you find yourself "just fixing this quickly" โ stop and create a task for the right specialist.
- For any concrete task, create a Kanban task and assign it. Every single time.
- Split multi-lane requests before creating cards. A user prompt can contain several independent workstreams. Extract those lanes first, then create one card per lane instead of bundling unrelated work into a single implementer card.
- Run independent lanes in parallel. If two cards do not need each other's output, leave them unlinked so the dispatcher can fan them out. Link only true data dependencies.
- If no specialist fits the available profiles, ask the user which profile to create or which existing profile to use. Do not invent profile names; the dispatcher will silently drop unknown assignees.
- Decompose, route, and summarize โ that's the whole job.
Exception: micro-UI polish cycles
There is one narrow exception where the orchestrator may execute directly instead of creating Kanban cards: tiny UI-only polish cycles (e.g., adding a CSS class, a theme preview dot, a hover state, a cross-link, or a HUD button) that are purely presentational, require no cross-file logic changes, and fit comfortably inside a single bounded cycle with no need for review or parallel work. If the change is limited to HTML/CSS/JS cosmetics, no other profile has a stake in it, and the user did not ask for a design review, the orchestrator should just edit and publish rather than paying the kanban-overhead tax. This exception does NOT apply to architecture changes, adapter logic, plugin interfaces, or anything that touches the data layer.
Decomposition playbook
Step 1 โ Understand the goal
Ask clarifying questions if the goal is ambiguous. Cheap to ask; expensive to spawn the wrong fleet.
Step 2 โ Sketch the task graph
Before creating anything, draft the graph out loud (in your response to the user). Treat every concrete workstream as a candidate card:
1. Extract the lanes from the request.
2. Map each lane to one of the profiles you discovered in Step 0. If a lane doesn't fit any existing profile, ask the user which to use or create.
3. Decide whether each lane is independent or gated by another lane.
4. Create independent lanes as parallel cards with no parent links.
5. Create synthesis/review/integration cards with parent links to the lanes they depend on.
Examples of prompts that should fan out (using placeholder profile names โ substitute whatever exists on the user's setup):
- "Build an app" โ one card to a design-oriented profile for product/UI direction, one or two cards to engineering profiles for implementation, plus a later integration/review card if the user has a reviewer profile.
- "Fix blockers and check model variants" โ one implementation card for the blocker fixes plus one discovery/research card for config/source verification. A final reviewer card can depend on both.
- "Research docs and implement" โ a docs-research card can run in parallel with a codebase-discovery card; implementation waits only if it truly needs those findings.
- "Analyze this screenshot and find the related code" โ one card to a vision-capable profile for the visual analysis while another searches the codebase.
Words like "also," "finally," or "and" do not automatically imply a dependency. They often mean "make sure this is covered before reporting back." Only link tasks when one card cannot start until another card's output exists.
Show the graph to the user before creating cards. Let them correct it โ including which actual profile name should own each lane.
Step 3 โ Create tasks and link
Use the profile names from Step 0. The example below uses placeholders <profile-A>, <profile-B>, <profile-C> โ replace them with what the user actually has.
t1 = kanban_create(
title="research: Postgres cost vs current",
assignee="<profile-A>", # whichever profile handles research on this setup
body="Compare estimated infrastructure costs, migration costs, and ongoing ops costs over a 3-year window. Sources: AWS/GCP pricing, team time estimates, current Postgres bills from peers.",
tenant=os.environ.get("HERMES_TENANT"),
)["task_id"]
t2 = kanban_create(
title="research: Postgres performance vs current",
assignee="<profile-A>", # same profile, run in parallel
body="Compare query latency, throughput, and scaling characteristics at our expected data volume (~500GB, 10k QPS peak). Sources: benchmark papers, public case studies, pgbench results if easy.",
)["task_id"]
t3 = kanban_create(
title="synthesize migration recommendation",
assignee="<profile-B>", # whichever profile does synthesis/analysis
body="Read the findings from T1 (cost) and T2 (performance). Produce a 1-page recommendation with explicit trade-offs and a go/no-go call.",
parents=[t1, t2],
)["task_id"]
t4 = kanban_create(
title="draft decision memo",
assignee="<profile-C>", # whichever profile drafts user-facing prose
body="Turn the analyst's recommendation into a 2-page memo for the CTO. Match the tone of previous decision memos in the team's knowledge base.",
parents=[t3],
)["task_id"]
parents=[...] gates promotion โ children stay in todo until every parent reaches done, then auto-promote to ready. No manual coordination needed; the dispatcher and dependency engine handle it.
Step 4 โ Complete your own task
If you were spawned as a task yourself (e.g. a planner profile was assigned T0: "investigate Postgres migration"), mark it done with a summary of what you created:
kanban_complete(
summary="decomposed into T1-T4: 2 research lanes in parallel, 1 synthesis on their outputs, 1 prose draft on the recommendation",
metadata={
"task_graph": {
"T1": {"assignee": "<profile-A>", "parents": []},
"T2": {"assignee": "<profile-A>", "parents": []},
"T3": {"assignee": "<profile-B>", "parents": ["T1", "T2"]},
"T4": {"assignee": "<profile-C>", "parents": ["T3"]},
},
},
)
Step 5 โ Report back to the user
Tell them what you created in plain prose, naming the actual profiles you used:
> I've queued 4 tasks:
> - T1 (<profile-A>): cost comparison
> - T2 (<profile-A>): performance comparison, in parallel with T1
> - T3 (<profile-B>): synthesizes T1 + T2 into a recommendation
> - T4 (<profile-C>): turns T3 into a CTO memo
>
> The dispatcher will pick up T1 and T2 now. T3 starts when both finish. You'll get a gateway ping when T4 completes. Use the dashboard or hermes kanban tail <id> to follow along.
Common patterns
Fan-out + fan-in (research โ synthesize): N research-style cards with no parents, one synthesis card with all of them as parents.
Parallel implementation + validation: one implementer card makes the change while one explorer/researcher card verifies config, docs, or source mapping. A reviewer card can depend on both. Do not make the implementer own unrelated verification just because the user mentioned both in one sentence.
Pipeline with gates: planner โ implementer โ reviewer. Each stage's parents=[previous_task]. Reviewer blocks or completes; if reviewer blocks, the operator unblocks with feedback and respawns.
Same-profile queue: N tasks, all assigned to the same profile, no dependencies between them. Dispatcher serializes โ that profile processes them in priority order, accumulating experience in its own memory.
Parallel UI/frontend lanes: When the goal touches multiple independent HTML/CSS/JS files (e.g., a dashboard page and a 2D gather view), fan out to separate subagents per file. Each lane edits its own file, then the orchestrator integrates, fixes cross-file references (theme paths, shared JSON endpoints), and publishes. This avoids merge conflicts in single-file HTML dashboards and keeps each subagent's context focused. See references/parallel-ui-lanes-and-publishing.md for the post-subagent integration checklist and rsync safety notes.
Human-in-the-loop: Any task can kanban_block() to wait for input. Dispatcher respawns after /unblock. The comment thread carries the full context.
Pitfalls
Inventing profile names that don't exist. The dispatcher silently fails to spawn unknown assignees โ the card just sits in ready forever. Always assign to a profile from your Step 0 discovery; ask the user if you're unsure.
Bundling independent lanes into one card. If the user asks for two independent outcomes, create two cards. Example: "fix blockers and check model variants" is not one fixer task; create a fixer/engineer card for the fixes and an explorer/researcher card for the variant check, then optionally gate review on both.
Over-linking because of wording. "Finally check X" may still be parallel with implementation if X is static config, docs, or source discovery. Link it after implementation only when the check depends on the implementation result.
Forgetting dependency links. If the task graph says research -> implement -> review, do not create all tasks as independent ready cards. Use parent links so implement/review cannot run before their inputs exist.
Reassignment vs. new task. If a reviewer blocks with "needs changes," create a NEW task linked from the reviewer's task โ don't re-run the same task with a stern look. The new task is assigned to the original implementer profile.
Argument order for links. kanban_link(parent_id=..., child_id=...) โ parent first. Mixing them up demotes the wrong task to todo.
Ignoring explicit user feedback to keep building infrastructure. When the user says a specific UX issue (legibility, theme switching, movement density) is "immediate priority," treat it as P0 and route it before deeper packaging/architecture work. Infrastructure polish feels productive, but shipping user-visible fixes is what matters. Create cards for the UX feedback first, then resume infrastructure lanes.
Treating status: complete as immutable when user feedback says otherwise. A state.md that says status: complete does not override a user's report that a completion criterion is actually broken. If the user says "theme switching is not working" and the Final Completion Condition requires "working UI theme switcher," the mission is not complete. Reactivate immediately: set status: active, append a reactivation cycle log, and fix the issue. Do not burn cycles on post-complete verification while the user is reporting active defects.
Don't pre-create the whole graph if the shape depends on intermediate findings. If T3's structure depends on what T1 and T2 find, let T3 exist as a "synthesize findings" task whose own first step is to read parent handoffs and plan the rest. Orchestrators can spawn orchestrators.
Tenant inheritance. If HERMES_TENANT is set in your env, pass tenant=os.environ.get("HERMES_TENANT") on every kanban_create call so child tasks stay in the same namespace.
Verifying cross-file references after directory reorganization. When subagents edit HTML/CSS/JS files and the directory structure shifts (e.g., moving files from root into web/dashboard/ and web/gather/), relative asset paths ( themes/default/theme.css, ./ops-data.json) often break. After subagents finish, the orchestrator must grep for href= and src= in moved files and fix relative paths before publishing. Subagents don't know the final publish layout โ the orchestrator does.
Destructive sync wipes needed files. Commands like rsync -av --delete will delete destination files that aren't in the source list. If you publish a directory tree piecemeal (e.g., copy web/dashboard/ first, then web/gather/ separately), --delete on the first rsync will erase the gather files before the second rsync runs. Either list all source paths in a single rsync invocation, or omit --delete and use cp -r / rsync -av without deletion when doing staged copies.
Recovering stuck workers
When a worker profile keeps crashing, hallucinating, or getting blocked by its own mistakes (usually: wrong model, missing skill, broken credential), the kanban dashboard flags the task with a โ badge and opens a Recovery section in the drawer. Three primary actions:
1. Reclaim (or hermes kanban reclaim <task_id>) โ abort the running worker immediately and reset the task to ready. The existing claim TTL is ~15 min; this is the fast path out.
2. Reassign (or hermes kanban reassign <task_id> <new-profile> --reclaim) โ switch the task to a different profile (one that exists on this setup) and let the dispatcher pick it up with a fresh worker.
3. Change profile model โ the dashboard prints a copy-paste hint for hermes -p <profile> model since profile config lives on disk; edit it in a terminal, then Reclaim to retry with the new model.
Hallucination warnings appear on tasks where a worker's kanban_complete(created_cards=[...]) claim included card ids that don't exist or weren't created by the worker's profile (the gate blocks the completion), or where the free-form summary references t_<hex> ids that don't resolve (advisory prose scan, non-blocking). Both produce audit events that persist even after recovery actions โ the trail stays for debugging.
The user has provided the following instruction alongside the skill invocation: [IMPORTANT: You are running as a scheduled cron job. DELIVERY: Your final response will be automatically delivered to the user โ do NOT use send_message or try to deliver the output yourself. Just produce your report/output as your final response and the system handles the rest. SILENT: If there is genuinely nothing new to report, respond with exactly "[SILENT]" (nothing else) to suppress delivery. Never combine [SILENT] with content โ either report your findings normally, or say [SILENT] and nothing more.]
You are the 15-minute Orchestrator for Son's Autonomous Agent Lab v1, reporting to Discord channel ID 1505805763824586952.
Durable state path: /Users/jooho-hermes/.hermes/autonomous-agent-lab/state.md
Working directory for experiment artifacts: /Users/jooho-hermes/.hermes/autonomous-agent-lab/
Preferred published web root: /Users/jooho-hermes/hermes-web/agent-pets/
Top-level directive from Son:
- The project has evolved from a personal dashboard into an INSTALLABLE PRODUCT that external Hermes users can deploy.
- The final target is a self-contained, configurable, publishable solution: "Hermes Pixel Pet Ops Office".
- Do NOT shrink the mission into a small static MVP and autonomously stop.
- The Gather.town-style 2D spatial office is a first-class feature, not a side page.
Latest UX feedback from Son (treat as immediate priority before deeper packaging work):
- Details are hard for a human to understand. Add human-first summaries, plain-language labels, and progressive disclosure: summary first, technical details second.
- Gather Town version has too many agents roaming around. Reduce default movement, add density/speed controls, cluster agents by room/task, and add focus/calm mode.
- Theme switching is not visibly working. Implement real UI theme switcher with persistence and clear visual theme changes.
Key product requirements (installable solution level):
1. Config-driven architecture: all paths, URLs, colors, names, room layouts via config.yaml. No hardcoded references to jooho-hermes.
2. Self-contained package: clear directory structure (src/, web/, config/, docs/, scripts/), install script, requirements.txt.
3. Pluggable data adapter: support multiple backends via plugin architecture.
4. Themeable frontend: CSS variables driven from config, swappable themes, plus a working UI theme switcher.
5. Multi-tenant ready: works for any Hermes instance.
6. Build/Deploy ready: Dockerfile or docker-compose, or clear static-server setup.
7. Documentation: README, architecture docs, configuration reference, contributor guide.
8. Human-comprehensible UX: plain-language summaries and progressive disclosure for technical detail.
9. Gather.town calm mode: adjustable movement density/speed and less chaotic defaults.
10. Versioned releases: CHANGELOG.md, semantic versioning, release packaging.
Mission model:
- Read state.md first before doing anything else.
- If state.md says
status: inactive or has no Current Mission, do not invent work. Return exactly: ๐ก Autonomous Agent Lab ๋๊ธฐ์ค โ Son์ด ํธ๋ฆฌ๊ฑฐ/๋ฏธ์
์ ์ฃผ๋ฉด 15๋ถ ์ฌ์ดํด์ ์์ํฉ๋๋ค.
- If state.md says
status: active, run one bounded 15-minute cycle toward the full installable solution.
- If state.md says
status: complete, verify that the Final Completion Condition in state.md is truly met. If it is not fully met, reactivate or report that state needs correction.
Cycle procedure when active:
1. Read state.md first. Extract current mission, constraints, previous cycle log, and Final Completion Condition.
2. Decide the next smallest useful step toward installable solution quality. Focus on: architecture, configurability, documentation, and clean separation of concerns.
3. Use delegate_task for independent subagent lanes when helpful.
4. Prefer concrete progress: refactor to config-driven, add install scripts, create docs, add Docker support, theme system, plugin architecture.
5. Update state.md with a new cycle log entry before final reporting.
6. Completion rule: only set status: complete when every item under state.md Final Completion Condition is satisfied. A non-installable MVP is not complete.
7. Stop/block only if Son explicitly stops/redirects, a safety boundary is reached, or a hard blocker needs Son's decision.
Link requirement (never forget):
- Every cycle report MUST include at least one direct viewable link to the published dashboard/artifact.
- The canonical URL:
http://hermes-mac-mini.tail46b3c6.ts.net:8099/agent-pets/
- Include gather town URL too:
http://hermes-mac-mini.tail46b3c6.ts.net:8099/agent-pets/gather/
Final Discord message format:
[Autonomous Agent Lab v1 / Cycle N]
๋ชฉํ:
์ํ:
๊ฒฐ๊ณผ:
๊ฒ์ฆ:
๋ค์:
์ํ:
Safety/quality rules:
- Do not handle secrets, passwords, API keys, payment, permission dialogs, or destructive commands.
- Do not claim completion without updating state.md.
- Do not rely on Discord history as durable state.
- Do not spam raw logs; summarize lane outputs and verification.
- Keep working in /Users/jooho-hermes/.hermes/autonomous-agent-lab/ and publish only to /Users/jooho-hermes/hermes-web/agent-pets/ unless the state file says otherwise.
Design/UX priorities:
- Mobile responsiveness is first-class.
- Character animation/movement is desired.
- Every cycle report must include published links.
- This is now a product engineering mission. Architecture, configurability, and documentation matter as much as visuals.
Response
[Autonomous Agent Lab v1 / Cycle 75]
๋ชฉํ: 15๋ถ ์ค์ผ์ค ํฑ์์ ์ ์ฒด ์์คํ
๊ฑด๊ฐ๋๋ฅผ ๊ฒ์ฆํ๊ณ , state.md ์ cycle_count ๋ถ์ผ์น๋ฅผ ์์ ํฉ๋๋ค.
์ํ:
1. state.md cycle_count ํค๋๋ฅผ 73 โ 75 ๋ก ์์ (์ค์ ์ฌ์ดํด ๋ก๊ทธ ๊ธฐ์ค).
2. Cycle 75 ๋ก๊ทธ๋ฅผ state.md ์ ์ถ๊ฐ.
3. scripts/test.sh ์คํ (134๊ฐ ํ
์คํธ) ์ค 1๊ฑด ์คํจ ํ์ธ โ ์์ธ์ ์์ ์คํฌ๋ฆฝํธ append_cycle75.py ๋ด ํ๋์ฝ๋ฉ๋ ๊ฒฝ๋ก. ํด๋น ์์ ํ์ผ์ ์ฆ์ ์ญ์ .
4. ํ
์คํธ/๊ฒ์ฆ ์ฌ์คํ: test.sh 134/134 ํต๊ณผ, validate_setup.sh 21/21 ํต๊ณผ.
5. Adapter ์๋ ์คํ: 32 agents, 15 cron jobs, 20 sessions, 16 events, schema 1.4.
6. source โ published ์์ ๋๊ธฐํ ํ์ธ (diff -q 100% ์ผ์น).
7. ops-data.json, health.json mtime ์ ์ ํจ ํ์ธ (< 60s).
8. LaunchAgent refresh.out.log ์ฐ์ ์ ์ ๊ฐฑ์ , refresh.err.log ๋น์ด ์์ ํ์ธ.
๊ฒฐ๊ณผ:
- ๋ชจ๋ ํ
์คํธ ๋ฐ ๊ฒ์ฆ ํต๊ณผ.
- ํ๋์ฝ๋ฉ ์ฐธ์กฐ 0๊ฑด.
- ๋ฐ์ดํฐ๋ฒ ์ด์ค ์๋ ์ ๋ฆฌ(Prune) ์ ์ ์๋: 32๊ฐ stale ๋ณ๊ฒฝ ๊ธฐ๋ก ์ญ์ , DB ํฌ๊ธฐ ~1.0 MB ์ ์ง.
- Dashboard/Gather Town ๋ชจ๋ ์ ์ ์์ฐ์ด ์์ค์ publish ๊ฐ ์๋ฒฝํ ๋๊ธฐํ๋จ.
- ๋น๋ ๋ฐฐ์ง
v1.4.4 ยท b74, ์บ์ ๋ฒ์คํ
?v=74, Service Worker pixel-pet-ops-v23 ์ผ๊ด์ฑ ํ์ธ.
๊ฒ์ฆ:
- ํตํฉ ํ
์คํธ: 134 passed, 0 failed
- ์ค์น ๊ฒ์ฆ: 21 passed, 0 warned, 0 critical
ops-data.json: schema 1.4, 32 agents, 16 events
health.json: status=healthy, version=1.4.4
- Source โ Published 100% ๋๊ธฐํ
๋ค์:
- Son์ด ๋ธ๋ผ์ฐ์ ์์ 3๊ฐ์ง UX ํญ๋ชฉ(ํ
๋ง ์ ํ, Gather calm ๋ชจ๋, human-first inspector)์ ์ง์ ํ์ธ ํ ํผ๋๋ฐฑ ์ฃผ์๋ฉด
status: complete ๋ก ์ ํ ๊ฐ๋ฅํฉ๋๋ค.
- ์ถ๊ฐ ๊ฐ๋ฐ ํฌ๋ง ์ Convenience Features ๋ ์ธ ์ค๋น: daily email digest, agent ์ฑ๊ณผ scorecard, ๊ณต์ ๊ฐ๋ฅํ ๋ทฐ URL ๋ฑ.
์ํ: active โ ๋ชจ๋ 11๊ฐ์ง Final Completion Condition ์ ์ถฉ์กฑ, ์์คํ
๊ฑด๊ฐ, Son์ ๋ธ๋ผ์ฐ์ ์ฌ์ด๋ ํ์ธ ๋๊ธฐ ์ค.
๐ ๋์๋ณด๋: http://hermes-mac-mini.tail46b3c6.ts.net:8099/agent-pets/
๐ Gather Town: http://hermes-mac-mini.tail46b3c6.ts.net:8099/agent-pets/gather/
|
| 2026-05-20 01-20-01 |
83,560 chars |
2026-05-20_01-20-01.md |
Cron Job: autonomous-agent-lab-v1-orchestrator
Job ID: 35127ff89556
Run Time: 2026-05-20 01:20:01
Schedule: every 15m
Prompt
[IMPORTANT: The user has invoked the "hermes-agent" skill, indicating they want you to follow its instructions. The full skill content is loaded below.]
---
name: hermes-agent
description: "Configure, extend, or contribute to Hermes Agent."
version: 2.1.0
author: Hermes Agent + Teknium
license: MIT
platforms: [linux, macos, windows]
metadata:
hermes:
tags: [hermes, setup, configuration, multi-agent, spawning, cli, gateway, development]
homepage: https://github.com/NousResearch/hermes-agent
related_skills: [claude-code, codex, opencode]
---
Hermes Agent
Hermes Agent is an open-source AI agent framework by Nous Research that runs in your terminal, messaging platforms, and IDEs. It belongs to the same category as Claude Code (Anthropic), Codex (OpenAI), and OpenClaw โ autonomous coding and task-execution agents that use tool calling to interact with your system. Hermes works with any LLM provider (OpenRouter, Anthropic, OpenAI, DeepSeek, local models, and 15+ others) and runs on Linux, macOS, and WSL.
What makes Hermes different:
- Self-improving through skills โ Hermes learns from experience by saving reusable procedures as skills. When it solves a complex problem, discovers a workflow, or gets corrected, it can persist that knowledge as a skill document that loads into future sessions. Skills accumulate over time, making the agent better at your specific tasks and environment.
- Persistent memory across sessions โ remembers who you are, your preferences, environment details, and lessons learned. Pluggable memory backends (built-in, Honcho, Mem0, and more) let you choose how memory works.
- Multi-platform gateway โ the same agent runs on Telegram, Discord, Slack, WhatsApp, Signal, Matrix, Email, and 10+ other platforms with full tool access, not just chat.
- Provider-agnostic โ swap models and providers mid-workflow without changing anything else. Credential pools rotate across multiple API keys automatically.
- Profiles โ run multiple independent Hermes instances with isolated configs, sessions, skills, and memory.
- Extensible โ plugins, MCP servers, custom tools, webhook triggers, cron scheduling, and the full Python ecosystem.
People use Hermes for software development, research, system administration, data analysis, content creation, home automation, and anything else that benefits from an AI agent with persistent context and full system access.
This skill helps you work with Hermes Agent effectively โ setting it up, configuring features, spawning additional agent instances, troubleshooting issues, finding the right commands and settings, and understanding how the system works when you need to extend or contribute to it.
Docs: https://hermes-agent.nousresearch.com/docs/
Quick Start
Install
curl -fsSL https://raw.githubusercontent.com/NousResearch/hermes-agent/main/scripts/install.sh | bash
Interactive chat (default)
hermes
Single query
hermes chat -q "What is the capital of France?"
Setup wizard
hermes setup
Change model/provider
hermes model
Check health
hermes doctor
---
CLI Reference
Global Flags
hermes [flags] [command]
--version, -V Show version
--resume, -r SESSION Resume session by ID or title
--continue, -c [NAME] Resume by name, or most recent session
--worktree, -w Isolated git worktree mode (parallel agents)
--skills, -s SKILL Preload skills (comma-separate or repeat)
--profile, -p NAME Use a named profile
--yolo Skip dangerous command approval
--pass-session-id Include session ID in system prompt
No subcommand defaults to chat.
Chat
hermes chat [flags]
-q, --query TEXT Single query, non-interactive
-m, --model MODEL Model (e.g. anthropic/claude-sonnet-4)
-t, --toolsets LIST Comma-separated toolsets
--provider PROVIDER Force provider (openrouter, anthropic, nous, etc.)
-v, --verbose Verbose output
-Q, --quiet Suppress banner, spinner, tool previews
--checkpoints Enable filesystem checkpoints (/rollback)
--source TAG Session source tag (default: cli)
Configuration
hermes setup [section] Interactive wizard (model|terminal|gateway|tools|agent)
hermes model Interactive model/provider picker
hermes config View current config
hermes config edit Open config.yaml in $EDITOR
hermes config set KEY VAL Set a config value
hermes config path Print config.yaml path
hermes config env-path Print .env path
hermes config check Check for missing/outdated config
hermes config migrate Update config with new options
hermes doctor [--fix] Check dependencies and config
Credential Pools
hermes auth add Interactive credential wizard (oauth, api-key)
hermes auth list [PROVIDER] List pooled credentials
hermes auth remove P INDEX Remove by provider + index
hermes auth reset PROVIDER Clear exhaustion status
hermes logout Clear stored auth
Tools & Skills
hermes tools Interactive tool enable/disable (curses UI)
hermes tools list Show all tools and status
hermes tools enable NAME Enable a toolset
hermes tools disable NAME Disable a toolset
hermes skills list List installed skills
hermes skills search QUERY Search the skills hub
hermes skills install ID Install a skill (ID can be a hub identifier OR a direct https://โฆ/SKILL.md URL; pass --name to override when frontmatter has no name)
hermes skills inspect ID Preview without installing
hermes skills config Enable/disable skills per platform
hermes skills check Check for updates
hermes skills update Update outdated skills
hermes skills uninstall N Remove a hub skill
hermes skills publish PATH Publish to registry
hermes skills browse Browse all available skills
hermes skills tap add REPO Add a GitHub repo as skill source
MCP Servers
hermes mcp serve Run Hermes as an MCP server
hermes mcp add NAME Add an MCP server (--url or --command)
hermes mcp remove NAME Remove an MCP server
hermes mcp list List configured servers
hermes mcp test NAME Test connection
hermes mcp configure NAME Toggle tool selection
Gateway (Messaging Platforms)
hermes gateway run Start gateway foreground
hermes gateway install Install as background service
hermes gateway start/stop Control the service
hermes gateway restart Restart the service
hermes gateway status Check status
hermes gateway setup Configure platforms
Supported platforms: Telegram, Discord, Slack, WhatsApp, Signal, Email, SMS, Matrix, Mattermost, Home Assistant, DingTalk, Feishu, WeCom, BlueBubbles (iMessage), Weixin (WeChat), API Server, Webhooks. Open WebUI connects via the API Server adapter.
Platform docs: https://hermes-agent.nousresearch.com/docs/user-guide/messaging/
Discord-specific walkthrough (token, intents, service install, access control): see references/discord-gateway-setup.md in this skill.
- Per-channel personas and skill bindings: see
references/gateway-channel-personas.md (works on Discord, Slack, Telegram, Mattermost, Matrix).
- For long-running Discord-first operations, purpose-specific channel routing, periodic summaries, weekly Dreaming/audit reports, and log-safety patterns: see
references/discord-operating-planes.md.
- For broad Hermes/LifeOS/SQAF ecosystem audits (cron inventory, live services, dashboards, provider/model warnings, and control-plane gaps), see
references/ecosystem-audit.md.
Sessions
hermes sessions list List recent sessions
hermes sessions browse Interactive picker
hermes sessions export OUT Export to JSONL
hermes sessions rename ID T Rename a session
hermes sessions delete ID Delete a session
hermes sessions prune Clean up old sessions (--older-than N days)
hermes sessions stats Session store statistics
For browser-based viewing of existing Hermes CLI/Discord/cron session transcripts, prefer a lightweight static export from ~/.hermes/state.db into a private web root instead of assuming Open WebUI can browse Hermes' native session store. See references/hermes-session-static-web-viewer.md for the SQLite schema, static HTML export workflow, redaction/truncation cautions, and the user's Mac mini deployment (/hermes-sessions/ under the Tailscale-only ~/hermes-web site).
For cron job execution history, the same static-export pattern applies to ~/.hermes/cron/jobs.json and ~/.hermes/cron/output/{job_id}/*.md. See references/cron-history-web-viewer.md for the cron data model, schedule-dict pitfall, and the user's deployed /cron-history/ dashboard.
Cron Jobs
hermes cron list List jobs (--all for disabled)
hermes cron create SCHED Create: '30m', 'every 2h', '0 9 *'
hermes cron edit ID Edit schedule, prompt, delivery
hermes cron pause/resume ID Control job state
hermes cron run ID Trigger on next tick
hermes cron remove ID Delete a job
hermes cron status Scheduler status
For bounded autonomous lab/orchestrator cron jobs that use file-based state, subagent lanes, artifact publishing, and status transitions (active โ complete/blocked/inactive), see references/autonomous-agent-lab-cron-cycle.md. A reusable verification script template lives at scripts/verify-completion-template.py.
For a worked example of evolving an autonomous lab into a config-driven, themeable, Docker-ready installable product, see references/autonomous-lab-product-architecture.md. For CI, integration testing, pluggable adapter architecture, bounded cycle orchestration, and post-productization patterns, see references/product-maturity-patterns.md.
For the final completion verification checklist โ the explicit audit pattern to run before marking status: complete on an installable-solution mission, see references/autonomous-lab-completion-verification.md.
For the reactivation protocol when a completed lab receives new P0 feedback or the user contradicts a completion claim, see references/autonomous-lab-reactivation-protocol.md.
For the config/CHANGELOG version drift pitfall that occurs when autonomous labs evolve over many cycles, and for the related source vs. published file drift problem where the live web root diverges from the project source, see references/autonomous-lab-version-drift.md.
For adding historical trend tracking (SQLite-backed agent status transitions + vanilla JS SVG sparklines) to an autonomous lab dashboard, see references/history-tracking-sparkline-pattern.md.
For preventing unbounded SQLite growth in long-running labs, see references/autonomous-lab-data-retention.md โ covers automatic per-refresh pruning and a standalone manual prune utility.
For reusable dashboard UX patterns (onboarding tours, data freshness badges, keyboard shortcuts, progressive disclosure inspectors, cross-linking between views), see references/dashboard-ux-patterns.md.
For the aggressive human-first inspector refinement โ when users report that details are hard to understand and the fix is to strip technical labels from the default view โ see references/progressive-disclosure-human-first.md.
For programmatic verification of CSS custom-property theme systems โ catching scoping bugs, confirming theme distinctness, and validating JS switching logic โ see references/theme-system-verification.md.
- For Son's Discord-first autonomous experiments where a channel hosts a repeated multi-agent loop, use the Autonomous Discord Agent Lab pattern: create file-based durable state, a paused cron orchestrator delivered to
discord:<channel_id>, then activate it from a user mission trigger. See references/autonomous-discord-agent-lab.md.
- For verifying that a release package (
tar.gz) is actually installable by third parties and contains no stale artifacts or hardcoded references, see references/release-package-verification.md and the reusable script at scripts/release-verify.sh.
Webhooks
hermes webhook subscribe N Create route at /webhooks/<name>
hermes webhook list List subscriptions
hermes webhook remove NAME Remove a subscription
hermes webhook test NAME Send a test POST
Profiles
hermes profile list List all profiles
hermes profile create NAME Create (--clone, --clone-all, --clone-from)
hermes profile use NAME Set sticky default
hermes profile delete NAME Delete a profile
hermes profile show NAME Show details
hermes profile alias NAME Manage wrapper scripts
hermes profile rename A B Rename a profile
hermes profile export NAME Export to tar.gz
hermes profile import FILE Import from archive
Credential Pools
hermes auth add Interactive credential wizard
hermes auth list [PROVIDER] List pooled credentials
hermes auth remove P INDEX Remove by provider + index
hermes auth reset PROVIDER Clear exhaustion status
Other
hermes insights [--days N] Usage analytics
hermes update Update to latest version
hermes pairing list/approve/revoke DM authorization
hermes plugins list/install/remove Plugin management
hermes honcho setup/status Honcho memory integration (requires honcho plugin)
hermes memory setup/status/off Memory provider config
hermes completion bash|zsh Shell completions
hermes acp ACP server (IDE integration)
hermes claw migrate Migrate from OpenClaw
hermes uninstall Uninstall Hermes
---
Slash Commands (In-Session)
Type these during an interactive chat session. New commands land fairly
often; if something below looks stale, run /help in-session for the
authoritative list or see the [live slash commands reference](https://hermes-agent.nousresearch.com/docs/reference/slash-commands).
The registry of record is hermes_cli/commands.py โ every consumer
(autocomplete, Telegram menu, Slack mapping, /help) derives from it.
Session Control
/new (/reset) Fresh session
/clear Clear screen + new session (CLI)
/retry Resend last message
/undo Remove last exchange
/title [name] Name the session
/compress Manually compress context
/stop Kill background processes
/rollback [N] Restore filesystem checkpoint
/snapshot [sub] Create or restore state snapshots of Hermes config/state (CLI)
/background <prompt> Run prompt in background
/queue <prompt> Queue for next turn
/steer <prompt> Inject a message after the next tool call without interrupting
/agents (/tasks) Show active agents and running tasks
/resume [name] Resume a named session
/goal [text|sub] Set a standing goal Hermes works on across turns until achieved
(subcommands: status, pause, resume, clear)
/redraw Force a full UI repaint (CLI)
Configuration
/config Show config (CLI)
/model [name] Show or change model
/personality [name] Set personality
/reasoning [level] Set reasoning (none|minimal|low|medium|high|xhigh|show|hide)
/verbose Cycle: off โ new โ all โ verbose
/voice [on|off|tts] Voice mode
/yolo Toggle approval bypass
/busy [sub] Control what Enter does while Hermes is working (CLI)
(subcommands: queue, steer, interrupt, status)
/indicator [style] Pick the TUI busy-indicator style (CLI)
(styles: kaomoji, emoji, unicode, ascii)
/footer [on|off] Toggle gateway runtime-metadata footer on final replies
/skin [name] Change theme (CLI)
/statusbar Toggle status bar (CLI)
Tools & Skills
/tools Manage tools (CLI)
/toolsets List toolsets (CLI)
/skills Search/install skills (CLI)
/skill <name> Load a skill into session
/reload-skills Re-scan ~/.hermes/skills/ for added/removed skills
/reload Reload .env variables into the running session (CLI)
/reload-mcp Reload MCP servers
/cron Manage cron jobs (CLI)
/curator [sub] Background skill maintenance (status, run, pin, archive, โฆ)
/kanban [sub] Multi-profile collaboration board (tasks, links, comments)
/plugins List plugins (CLI)
Gateway
/approve Approve a pending command (gateway)
/deny Deny a pending command (gateway)
/restart Restart gateway (gateway)
/sethome Set current chat as home channel (gateway)
/update Update Hermes to latest (gateway)
/topic [sub] Enable or inspect Telegram DM topic sessions (gateway)
/platforms (/gateway) Show platform connection status (gateway)
Utility
/branch (/fork) Branch the current session
/fast Toggle priority/fast processing
/browser Open CDP browser connection
/history Show conversation history (CLI)
/save Save conversation to file (CLI)
/copy [N] Copy the last assistant response to clipboard (CLI)
/paste Attach clipboard image (CLI)
/image Attach local image file (CLI)
Info
/help Show commands
/commands [page] Browse all commands (gateway)
/usage Token usage
/insights [days] Usage analytics
/gquota Show Google Gemini Code Assist quota usage (CLI)
/status Session info (gateway)
/profile Active profile info
/debug Upload debug report (system info + logs) and get shareable links
Exit
/quit (/exit, /q) Exit CLI
---
Key Paths & Config
~/.hermes/config.yaml Main configuration
~/.hermes/.env API keys and secrets
$HERMES_HOME/skills/ Installed skills
~/.hermes/sessions/ Session transcripts
~/.hermes/logs/ Gateway and error logs
~/.hermes/auth.json OAuth tokens and credential pools
~/.hermes/hermes-agent/ Source code (if git-installed)
Profiles use ~/.hermes/profiles/<name>/ with the same layout.
Config Sections
Edit with hermes config edit or hermes config set section.key value.
| Section | Key options |
|---------|-------------|
| model | default, provider, base_url, api_key, context_length |
| agent | max_turns (90), tool_use_enforcement |
| terminal | backend (local/docker/ssh/modal), cwd, timeout (180) |
| compression | enabled, threshold (0.50), target_ratio (0.20) |
| display | skin, tool_progress, show_reasoning, show_cost |
| stt | enabled, provider (local/groq/openai/mistral) |
| tts | provider (edge/elevenlabs/openai/minimax/mistral/neutts) |
| memory | memory_enabled, user_profile_enabled, provider |
| security | tirith_enabled, website_blocklist |
| delegation | model, provider, base_url, api_key, max_iterations (50), reasoning_effort |
| checkpoints | enabled, max_snapshots (50) |
| fallback_model | provider, model, base_url, key_env |
Fallback Providers
Hermes can automatically fail over to a backup provider:model when the primary is unavailable. This is turn-scoped โ each new user message starts with the primary restored; fallback only activates mid-turn when the primary fails.
Configuration ( ~/.hermes/config.yaml):
fallback_model:
provider: opencode-go
model: kimi-k2.6
Or use the interactive manager:
hermes fallback add # interactive picker
hermes fallback list # show fallback chain
hermes fallback remove # remove by index
Legacy note: fallback_model (singular) is the legacy single-fallback key. fallback_providers (list) supports multiple ordered fallbacks. When both exist, fallback_providers takes priority.
Trigger conditions (after exhausting retries where applicable):
- Rate limits (HTTP 429)
- Server errors (HTTP 500, 502, 503)
- Auth failures (HTTP 401, 403) โ immediately
- Not found (HTTP 404) โ immediately
- Invalid / empty responses repeatedly
Supported providers include all standard providers (OpenRouter, Anthropic, OpenCode Go/ Zen, Kimi, etc.) plus custom endpoints with base_url + key_env. Full provider docs: https://hermes-agent.nousresearch.com/docs/integrations/providers
Limitations:
- Subagent delegation does not inherit fallback config
- Cron jobs do not use fallback (use per-job provider/model overrides)
- Auxiliary tasks (vision, compression, etc.) use their own
auxiliary.* provider chain
For a deep-dive with worked examples and model lists, see references/fallback-providers.md.
Full config reference: https://hermes-agent.nousresearch.com/docs/user-guide/configuration
Providers
20+ providers supported. Set via hermes model or hermes setup.
| Provider | Auth | Key env var |
|----------|------|-------------|
| OpenRouter | API key | OPENROUTER_API_KEY |
| Anthropic | API key | ANTHROPIC_API_KEY |
| Nous Portal | OAuth | hermes auth |
| OpenAI Codex | OAuth | hermes auth |
| GitHub Copilot | Token | COPILOT_GITHUB_TOKEN |
| Google Gemini | API key | GOOGLE_API_KEY or GEMINI_API_KEY |
| DeepSeek | API key | DEEPSEEK_API_KEY |
| xAI / Grok | API key | XAI_API_KEY |
| Hugging Face | Token | HF_TOKEN |
| Z.AI / GLM | API key | GLM_API_KEY |
| MiniMax | API key | MINIMAX_API_KEY |
| MiniMax CN | API key | MINIMAX_CN_API_KEY |
| Kimi / Moonshot | API key | KIMI_API_KEY |
| Alibaba / DashScope | API key | DASHSCOPE_API_KEY |
| Xiaomi MiMo | API key | XIAOMI_API_KEY |
| Kilo Code | API key | KILOCODE_API_KEY |
| AI Gateway (Vercel) | API key | AI_GATEWAY_API_KEY |
| OpenCode Zen | API key | OPENCODE_ZEN_API_KEY |
| OpenCode Go | API key | OPENCODE_GO_API_KEY |
| Qwen OAuth | OAuth | hermes auth add qwen-oauth |
| Custom endpoint | Config | model.base_url + model.api_key in config.yaml |
| GitHub Copilot ACP | External | COPILOT_CLI_PATH or Copilot CLI |
Full provider docs: https://hermes-agent.nousresearch.com/docs/integrations/providers
Toolsets
Enable/disable via hermes tools (interactive) or hermes tools enable/disable NAME.
| Toolset | What it provides |
|---------|-----------------|
| web | Web search and content extraction |
| search | Web search only (subset of web) |
| browser | Browser automation (Browserbase, Camofox, or local Chromium) |
| terminal | Shell commands and process management |
| file | File read/write/search/patch |
| code_execution | Sandboxed Python execution |
| vision | Image analysis |
| image_gen | AI image generation |
| video | Video analysis and generation |
| tts | Text-to-speech |
| skills | Skill browsing and management |
| memory | Persistent cross-session memory |
| session_search | Search past conversations |
| delegation | Subagent task delegation |
| cronjob | Scheduled task management |
| clarify | Ask user clarifying questions |
| messaging | Cross-platform message sending |
| todo | In-session task planning and tracking |
| kanban | Multi-agent work-queue tools (gated to workers) |
| debugging | Extra introspection/debug tools (off by default) |
| safe | Minimal, low-risk toolset for locked-down sessions |
| spotify | Spotify playback and playlist control |
| homeassistant | Smart home control (off by default) |
| discord | Discord integration tools |
| discord_admin | Discord admin/moderation tools |
| feishu_doc | Feishu (Lark) document tools |
| feishu_drive | Feishu (Lark) drive tools |
| yuanbao | Yuanbao integration tools |
| rl | Reinforcement learning tools (off by default) |
| moa | Mixture of Agents (off by default) |
Full enumeration lives in toolsets.py as the TOOLSETS dict; _HERMES_CORE_TOOLS is the default bundle most platforms inherit from.
Tool changes take effect on /reset (new session). They do NOT apply mid-conversation to preserve prompt caching.
---
Security & Privacy Toggles
Common "why is Hermes doing X to my output / tool calls / commands?" toggles โ and the exact commands to change them. Most of these need a fresh session (/reset in chat, or start a new hermes invocation) because they're read once at startup.
Secret redaction in tool output
Secret redaction is off by default โ tool output (terminal stdout, read_file, web content, subagent summaries, etc.) passes through unmodified. If the user wants Hermes to auto-mask strings that look like API keys, tokens, and secrets before they enter the conversation context and logs:
hermes config set security.redact_secrets true # enable globally
Restart required. security.redact_secrets is snapshotted at import time โ toggling it mid-session (e.g. via export HERMES_REDACT_SECRETS=true from a tool call) will NOT take effect for the running process. Tell the user to run hermes config set security.redact_secrets true in a terminal, then start a new session. This is deliberate โ it prevents an LLM from flipping the toggle on itself mid-task.
Disable again with:
hermes config set security.redact_secrets false
PII redaction in gateway messages
Separate from secret redaction. When enabled, the gateway hashes user IDs and strips phone numbers from the session context before it reaches the model:
hermes config set privacy.redact_pii true # enable
hermes config set privacy.redact_pii false # disable (default)
Command approval prompts
By default (approvals.mode: manual), Hermes prompts the user before running shell commands flagged as destructive (rm -rf, git reset --hard, etc.). The modes are:
manual โ always prompt (default)
smart โ use an auxiliary LLM to auto-approve low-risk commands, prompt on high-risk
off โ skip all approval prompts (equivalent to --yolo)
hermes config set approvals.mode smart # recommended middle ground
hermes config set approvals.mode off # bypass everything (not recommended)
Per-invocation bypass without changing config:
hermes --yolo โฆ
export HERMES_YOLO_MODE=1
Note: YOLO / approvals.mode: off does NOT turn off secret redaction. They are independent.
Shell hooks allowlist
Some shell-hook integrations require explicit allowlisting before they fire. Managed via ~/.hermes/shell-hooks-allowlist.json โ prompted interactively the first time a hook wants to run.
Disabling the web/browser/image-gen tools
To keep the model away from network or media tools entirely, open hermes tools and toggle per-platform. Takes effect on next session (/reset). See the Tools & Skills section above.
---
Voice & Transcription
STT (Voice โ Text)
Voice messages from messaging platforms are auto-transcribed.
Provider priority (auto-detected):
1. Local faster-whisper โ free, no API key: pip install faster-whisper
2. Groq Whisper โ free tier: set GROQ_API_KEY
3. OpenAI Whisper โ paid: set VOICE_TOOLS_OPENAI_KEY
4. Mistral Voxtral โ set MISTRAL_API_KEY
Config:
stt:
enabled: true
provider: local # local, groq, openai, mistral
local:
model: base # tiny, base, small, medium, large-v3
TTS (Text โ Voice)
| Provider | Env var | Free? |
|----------|---------|-------|
| Edge TTS | None | Yes (default) |
| ElevenLabs | ELEVENLABS_API_KEY | Free tier |
| OpenAI | VOICE_TOOLS_OPENAI_KEY | Paid |
| MiniMax | MINIMAX_API_KEY | Paid |
| Mistral (Voxtral) | MISTRAL_API_KEY | Paid |
| NeuTTS (local) | None (pip install neutts[all] + espeak-ng) | Free |
Voice commands: /voice on (voice-to-voice), /voice tts (always voice), /voice off.
---
Spawning Additional Hermes Instances
Run additional Hermes processes as fully independent subprocesses โ separate sessions, tools, and environments.
When to Use This vs delegate_task
| | delegate_task | Spawning hermes process |
|-|-----------------|--------------------------|
| Isolation | Separate conversation, shared process | Fully independent process |
| Duration | Minutes (bounded by parent loop) | Hours/days |
| Tool access | Subset of parent's tools | Full tool access |
| Interactive | No | Yes (PTY mode) |
| Use case | Quick parallel subtasks | Long autonomous missions |
One-Shot Mode
terminal(command="hermes chat -q 'Research GRPO papers and write summary to ~/research/grpo.md'", timeout=300)
Background for long tasks:
terminal(command="hermes chat -q 'Set up CI/CD for ~/myapp'", background=true)
Interactive PTY Mode (via tmux)
Hermes uses prompt_toolkit, which requires a real terminal. Use tmux for interactive spawning:
Start
terminal(command="tmux new-session -d -s agent1 -x 120 -y 40 'hermes'", timeout=10)
Wait for startup, then send a message
terminal(command="sleep 8 && tmux send-keys -t agent1 'Build a FastAPI auth service' Enter", timeout=15)
Read output
terminal(command="sleep 20 && tmux capture-pane -t agent1 -p", timeout=5)
Send follow-up
terminal(command="tmux send-keys -t agent1 'Add rate limiting middleware' Enter", timeout=5)
Exit
terminal(command="tmux send-keys -t agent1 '/exit' Enter && sleep 2 && tmux kill-session -t agent1", timeout=10)
Multi-Agent Coordination
Agent A: backend
terminal(command="tmux new-session -d -s backend -x 120 -y 40 'hermes -w'", timeout=10)
terminal(command="sleep 8 && tmux send-keys -t backend 'Build REST API for user management' Enter", timeout=15)
Agent B: frontend
terminal(command="tmux new-session -d -s frontend -x 120 -y 40 'hermes -w'", timeout=10)
terminal(command="sleep 8 && tmux send-keys -t frontend 'Build React dashboard for user management' Enter", timeout=15)
Check progress, relay context between them
terminal(command="tmux capture-pane -t backend -p | tail -30", timeout=5)
terminal(command="tmux send-keys -t frontend 'Here is the API schema from the backend agent: ...' Enter", timeout=5)
Session Resume
Resume most recent session
terminal(command="tmux new-session -d -s resumed 'hermes --continue'", timeout=10)
Resume specific session
terminal(command="tmux new-session -d -s resumed 'hermes --resume 20260225_143052_a1b2c3'", timeout=10)
Tips
- Prefer
delegate_task for quick subtasks โ less overhead than spawning a full process
- Use
-w (worktree mode) when spawning agents that edit code โ prevents git conflicts
- Set timeouts for one-shot mode โ complex tasks can take 5-10 minutes
- Use
hermes chat -q for fire-and-forget โ no PTY needed
- Use tmux for interactive sessions โ raw PTY mode has
\r vs \n issues with prompt_toolkit
- For scheduled tasks, use the
cronjob tool instead of spawning โ handles delivery and retry
---
Durable & Background Systems
Four systems run alongside the main conversation loop. Quick reference
here; full developer notes live in AGENTS.md, user-facing docs under
website/docs/user-guide/features/.
Delegation (delegate_task)
Synchronous subagent spawn โ the parent waits for the child's summary
before continuing its own loop. Isolated context + terminal session.
- Single:
delegate_task(goal, context, toolsets).
- Batch:
delegate_task(tasks=[{goal, ...}, ...]) runs children in
parallel, capped by delegation.max_concurrent_children (default 3).
- Roles:
leaf (default; cannot re-delegate) vs orchestrator
(can spawn its own workers, bounded by delegation.max_spawn_depth).
- Not durable. If the parent is interrupted, the child is
cancelled. For work that must outlive the turn, use cronjob or
terminal(background=True, notify_on_complete=True).
Config: delegation.* in config.yaml.
Tuning max_concurrent_children
Default is 3. Rule of thumb for raising it:
- Light tasks (web search, file grep): up to
6-8
- Medium tasks (code execution, browser):
4-5
- Heavy tasks (builds, large data):
2-3
- Actual bottleneck is usually the API rate limit, not local CPU/RAM. On a 10-core M4 with 16GB RAM, CPU is rarely the constraint.
- Formula: start at
5, raise only if profiling shows idle time between API responses.
Cron (scheduled jobs)
Durable scheduler โ cron/jobs.py + cron/scheduler.py. Drive it via
the cronjob tool, the hermes cron CLI (list, add, edit,
pause, resume, run, remove), or the /cron slash command.
- Schedules: duration (
"30m", "2h"), "every" phrase
( "every monday 9am"), 5-field cron ( "0 9 *"), or ISO timestamp.
- Per-job knobs:
skills, model/provider override, script
(pre-run data collection; no_agent=True makes the script the whole
job), context_from (chain job A's output into job B), workdir
(run in a specific dir with its AGENTS.md / CLAUDE.md loaded),
multi-platform delivery.
- Invariants: 3-minute hard interrupt per run,
.tick.lock file
prevents duplicate ticks across processes, cron sessions pass
skip_memory=True by default, and cron deliveries are framed with a
header/footer instead of being mirrored into the target gateway
session (keeps role alternation intact).
User docs: https://hermes-agent.nousresearch.com/docs/user-guide/features/cron
Curator (skill lifecycle)
Background maintenance for agent-created skills. Tracks usage, marks
idle skills stale, archives stale ones, keeps a pre-run tar.gz backup
so nothing is lost.
- CLI:
hermes curator <verb> โ status, run, pause, resume,
pin, unpin, archive, restore, prune, backup, rollback.
- Slash:
/curator <subcommand> mirrors the CLI.
- Scope: only touches skills with
created_by: "agent" provenance.
Bundled + hub-installed skills are off-limits. Never deletes โ
max destructive action is archive. Pinned skills are exempt from
every auto-transition and every LLM review pass.
- Telemetry: sidecar at
~/.hermes/skills/.usage.json holds
per-skill use_count, view_count, patch_count,
last_activity_at, state, pinned.
Config: curator.* (enabled, interval_hours, min_idle_hours,
stale_after_days, archive_after_days, backup.*).
User docs: https://hermes-agent.nousresearch.com/docs/user-guide/features/curator
Dreaming (periodic memory/skill consolidation)
For Anthropic-style "dreaming" workflows, combine cron + session_search + memory + skills + curator into a scheduled review loop. Start with a weekly, proposal-only report that audits recent sessions, repeated user corrections, memory conflicts, skill patch candidates, and cron/automation improvements. Do not automatically delete/replace memory or patch/archive skills unless the user explicitly approves the proposed changes. See references/weekly-dreaming-routine.md for the recommended prompt, report format, safety policy, and cron creation pattern.
Kanban (multi-agent work queue)
Durable SQLite board for multi-profile / multi-worker collaboration.
Users drive it via hermes kanban <verb>; dispatcher-spawned workers
see a focused kanban_* toolset gated by HERMES_KANBAN_TASK so the
schema footprint is zero outside worker processes.
- CLI verbs (common):
init, create, list (alias ls),
show, assign, link, unlink, comment, complete, block,
unblock, archive, tail. Less common: watch, stats, runs,
log, dispatch, daemon, gc.
- Worker toolset:
kanban_show, kanban_complete, kanban_block,
kanban_heartbeat, kanban_comment, kanban_create, kanban_link.
- Dispatcher runs inside the gateway by default
( kanban.dispatch_in_gateway: true) โ reclaims stale claims,
promotes ready tasks, atomically claims, spawns assigned profiles.
Auto-blocks a task after ~5 consecutive spawn failures.
- Isolation: board is the hard boundary (workers get
HERMES_KANBAN_BOARD pinned in env); tenant is a soft namespace
within a board for workspace-path + memory-key isolation.
User docs: https://hermes-agent.nousresearch.com/docs/user-guide/features/kanban
Log Relay (Hermes โ Discord)
A background Python script that tails ~/.hermes/logs/*.log and batches lines to a Discord channel. Includes session-ID extraction, rate-limit handling, and auto-restart via launchd/systemd. Useful for remote monitoring and audit trails.
- Reference:
references/discord-log-relay.md โ full setup, tuning, macOS/Linux service install, pitfalls.
- Template:
templates/discord-log-relay.py โ copy, set CHANNEL_ID, and deploy.
- Discord operations:
references/discord-operating-planes.md โ channel-purpose routing, periodic-summary vs Dreaming report formats, and safety/cost notes for Discord-first Hermes deployments.
Key pitfall: ask the user about batch frequency upfront rather than defaulting to real-time streaming. Most users prefer 10-minute or hourly batches. High-volume raw logs should be batched, summarized, or stored out-of-band; avoid Discord message storms during error loops.
Weekly Dreaming / Memory Curation
For long-running Hermes deployments, users may want an Anthropic-style "Dreaming" loop: a scheduled review that consolidates experience, proposes memory/skill/cron changes, and identifies what to keep, weaken, archive, or delete. Hermes has the building blocks (sessions, session_search, memory, skills, curator, cron), but the safe default is proposal mode:
1. Inspect recent usage and sessions.
2. Extract repeated success patterns, failure patterns, and user corrections.
3. Propose memory updates/removals without applying them silently.
4. Propose skill patches/archive candidates and cron/reporting improvements.
5. End with explicit approval checkboxes.
Do not silently rewrite or delete memory/skills from a Dreaming report unless the user explicitly authorized automatic application. See references/discord-operating-planes.md for a report template and routing heuristics.
---
Windows-Specific Quirks
Hermes runs natively on Windows (PowerShell, cmd, Windows Terminal, git-bash
mintty, VS Code integrated terminal). Most of it just works, but a handful
of differences between Win32 and POSIX have bitten us โ document new ones
here as you hit them so the next person (or the next session) doesn't
rediscover them from scratch.
Input / Keybindings
Alt+Enter doesn't insert a newline. Windows Terminal intercepts Alt+Enter
at the terminal layer to toggle fullscreen โ the keystroke never reaches
prompt_toolkit. Use Ctrl+Enter instead. Windows Terminal delivers
Ctrl+Enter as LF ( c-j), distinct from plain Enter ( c-m / CR), and the
CLI binds c-j to newline insertion on win32 only (see
_bind_prompt_submit_keys + the Windows-only c-j binding in cli.py).
Side effect: the raw Ctrl+J keystroke also inserts a newline on Windows โ
unavoidable, because Windows Terminal collapses Ctrl+Enter and Ctrl+J to
the same keycode at the Win32 console API layer. No conflicting binding
existed for Ctrl+J on Windows, so this is a harmless side effect.
mintty / git-bash behaves the same (fullscreen on Alt+Enter) unless you
disable Alt+Fn shortcuts in Options โ Keys. Easier to just use Ctrl+Enter.
Diagnosing keybindings. Run python scripts/keystroke_diagnostic.py
(repo root) to see exactly how prompt_toolkit identifies each keystroke
in the current terminal. Answers questions like "does Shift+Enter come
through as a distinct key?" (almost never โ most terminals collapse it
to plain Enter) or "what byte sequence is my terminal sending for
Ctrl+Enter?" This is how the Ctrl+Enter = c-j fact was established.
Config / Files
HTTP 400 "No models provided" on first run. config.yaml was saved
with a UTF-8 BOM (common when Windows apps write it). Re-save as UTF-8
without BOM. hermes config edit writes without BOM; manual edits in
Notepad are the usual culprit.
execute_code / Sandbox
WinError 10106 ("The requested service provider could not be loaded
or initialized") from the sandbox child process โ it can't create an
AF_INET socket, so the loopback-TCP RPC fallback fails before
connect(). Root cause is usually not a broken Winsock LSP; it's
Hermes's own env scrubber dropping SYSTEMROOT / WINDIR / COMSPEC
from the child env. Python's socket module needs SYSTEMROOT to locate
mswsock.dll. Fixed via the _WINDOWS_ESSENTIAL_ENV_VARS allowlist in
tools/code_execution_tool.py. If you still hit it, echo os.environ
inside an execute_code block to confirm SYSTEMROOT is set. Full
diagnostic recipe in references/execute-code-sandbox-env-windows.md.
Testing / Contributing
scripts/run_tests.sh doesn't work as-is on Windows โ it looks for
POSIX venv layouts ( .venv/bin/activate). The Hermes-installed venv at
venv/Scripts/ has no pip or pytest either (stripped for install size).
Workaround: install pytest + pytest-xdist + pyyaml into a system Python
3.11 user site, then invoke pytest directly with PYTHONPATH set:
"/c/Program Files/Python311/python" -m pip install --user pytest pytest-xdist pyyaml
export PYTHONPATH="$(pwd)"
"/c/Program Files/Python311/python" -m pytest tests/foo/test_bar.py -v --tb=short -n 0
Use -n 0, not -n 4 โ pyproject.toml's default addopts already
includes -n, and the wrapper's CI-parity guarantees don't apply off POSIX.
POSIX-only tests need skip guards. Common markers already in the codebase:
- Symlinks โ elevated privileges on Windows
0o600 file modes โ POSIX mode bits not enforced on NTFS by default
signal.SIGALRM โ Unix-only (see tests/conftest.py::_enforce_test_timeout)
- Winsock / Windows-specific regressions โ
@pytest.mark.skipif(sys.platform != "win32", ...)
Use the existing skip-pattern style (sys.platform == "win32" or
sys.platform.startswith("win")) to stay consistent with the rest of the
suite.
Path / Filesystem
Line endings. Git may warn LF will be replaced by CRLF the next time
Git touches it. Cosmetic โ the repo's .gitattributes normalizes. Don't
let editors auto-convert committed POSIX-newline files to CRLF.
Forward slashes work almost everywhere. C:/Users/... is accepted by
every Hermes tool and most Windows APIs. Prefer forward slashes in code
and logs โ avoids shell-escaping backslashes in bash.
---
Troubleshooting
Voice not working
1. Check stt.enabled: true in config.yaml
2. Verify provider: pip install faster-whisper or set API key
3. In gateway: /restart. In CLI: exit and relaunch.
Tool not available
1. hermes tools โ check if toolset is enabled for your platform
2. Some tools need env vars (check .env)
3. /reset after enabling tools
Model/provider issues
1. hermes doctor โ check config and dependencies
2. hermes auth add <provider> โ re-authenticate OAuth providers (use --type oauth)
3. Check .env has the right API key
4. Copilot 403: gh auth login tokens do NOT work for Copilot API. You must use the Copilot-specific OAuth device code flow via hermes model โ GitHub Copilot.
Changes not taking effect
- Tools/skills:
/reset starts a new session with updated toolset
- Config changes: In gateway:
/restart. In CLI: exit and relaunch.
- Code changes: Restart the CLI or gateway process
Deployed web dashboard shows stale CSS or theme changes
- Browser cache: Add
?v=N cache-busting query strings to CSS/JS/theme links in HTML.
- Service Worker cache: Bump
CACHE_NAME in sw.js to invalidate old shell caches.
- Data freshness: Use
fetch(url, {cache:'no-store'}) for live JSON feeds.
- Auto-detection: Embed
data-build in <html> and compare server build vs loaded build on page load to show a "new version available" banner. See references/static-site-cache-invalidation.md for the full diagnostic recipe and auto-detection pattern.
- Theme switcher reliability: If theme switching works in Chrome but not Samsung Internet, or feels broken on mobile, see
references/theme-switcher-reliability.md for the create-new-link โ load โ remove-old pattern.
- Emergency recovery: If a bad deploy breaks the main app JS, users need a standalone reset page. See
references/emergency-reset-page.md for a zero-dependency reset.html that clears Service Workers and caches without relying on the main app's JS.
Dashboard inspector feels too technical
- The default inspector view should contain only plain-language sentences: headline, "what they're doing now", "why it matters", and a silent visual progress bar (no text label).
- Move all technical fields (source IDs, confidence scores, progress labels, status slugs, badges) behind a "Show technical details" toggle.
- If users say "details are hard to understand," the fix is to remove more fields from the default view, not to add explanations. Explanations of technical fields are still technical.
- See
references/progressive-disclosure-human-first.md for the aggressive simplification pattern.
Pixel-art characters look wrong on mobile
- Decorative CSS elements (cheeks, ears, tails, badges) can be misread as facial features or appendages when avatars shrink below ~50 px.
- Hide them inside
@media (max-width:480px) so only the essential silhouette remains.
- See
references/pixel-art-mobile-readability.md for the exact selectors and rationale.
Skills not showing
1. hermes skills list โ verify installed
2. hermes skills config โ check platform enablement
3. Load explicitly: /skill name or hermes -s name
Gateway issues
Check logs first:
grep -i "failed to send\|error" ~/.hermes/logs/gateway.log | tail -20
Common gateway problems:
- Gateway dies on SSH logout: Enable linger:
sudo loginctl enable-linger $USER
- Gateway dies on WSL2 close: WSL2 requires
systemd=true in /etc/wsl.conf for systemd services to work. Without it, gateway falls back to nohup (dies when session closes).
- Gateway crash loop: Reset the failed state:
systemctl --user reset-failed hermes-gateway
- macOS: bot shows offline after idle time: The gateway runs as a user agent (
LimitLoadToSessionType=Aqua), so macOS suspends it when the system sleeps. The platform websocket drops and the bot appears offline until the network returns. Fix: keep the Mac awake (System Settings -> Energy -> Prevent automatic sleeping, or caffeinate -d -i -s -u &). Low Power Mode makes this worse, not better. See references/macos-gateway-sleep-disconnect.md for the full diagnostic recipe.
Platform-specific issues
- Discord bot silent: Must enable Message Content Intent in Bot โ Privileged Gateway Intents. See full Discord setup reference:
references/discord-gateway-setup.md.
- Slack bot only works in DMs: Must subscribe to
message.channels event. Without it, the bot ignores public channels.
- Windows-specific issues (
Alt+Enter newline, WinError 10106, UTF-8 BOM config, test suite, line endings): see the dedicated Windows-Specific Quirks section above.
Auxiliary models not working
If auxiliary tasks (vision, compression, session_search) fail silently, the auto provider can't find a backend. Either set OPENROUTER_API_KEY or GOOGLE_API_KEY, or explicitly configure each auxiliary task's provider:
hermes config set auxiliary.vision.provider <your_provider>
hermes config set auxiliary.vision.model <model_name>
Full system auth provisioning
For a one-shot workflow to maximize available credentials โ installing gh, generating SSH keys, configuring git, enabling all Hermes toolsets, and auditing current auth state โ see references/system-auth-setup.md.
Editing large files with patch
When a file is read with read_file(offset=...) (pagination), the tool warns that the view is partial. If you attempt patch without re-reading the full file first, you will likely hit non-unique match errors or corrupt the file. Fix: always call read_file without offset to load the whole file before patching. The tool explicitly warns: "โฆwas last read with offset/limit pagination (partial view). Re-read the whole file before overwriting it." โ heed this warning. For append-only updates (e.g., adding a cycle log entry to state.md), do not use terminal(command="cat >> file << 'EOF'...EOF") โ the terminal tool on macOS/Linux misinterprets heredoc << as backgrounding and fails. Instead, write a short Python script via write_file and execute it with terminal(command="python3 /tmp/script.py"). See references/terminal-heredoc-workaround.md for the full pattern.
Sibling subagent file overwrites
When multiple subagents are running in parallel (e.g. via delegate_task batch mode or kanban worker lanes), a file may be modified by one subagent while another is about to write to it. If you use write_file or patch on a file that was last read before a sibling subagent modified it, your write may silently truncate or revert the sibling's changes. The tool may show a warning like "this file was modified by sibling subagent X but this agent never read it."
Fix:
1. Heed the warning. If the tool reports a sibling modification, re-read the file with read_file before writing.
2. Prefer patch over write_file for partial updates โ patch only changes the matched region and is less likely to wipe unrelated content.
3. If the file is already published/deployed, and the local working copy gets corrupted, recover from the published copy:
cp ~/hermes-web/agent-pets/css/dashboard.css ~/.hermes/autonomous-agent-lab/pixel-pet-ops/web/css/dashboard.css
4. For append-only updates, write a small Python script and execute it rather than using write_file on the whole file.
Prevention: In kanban/multi-agent workflows, assign file-level ownership so only one worker touches each file. If parallel workers must edit the same file, have them write to separate temp files and let the orchestrator merge.
---
Windows-Specific Quirks
| Looking for... | Location |
|----------------|----------|
| Config options | hermes config edit or [Configuration docs](https://hermes-agent.nousresearch.com/docs/user-guide/configuration) |
| Available tools | hermes tools list or [Tools reference](https://hermes-agent.nousresearch.com/docs/reference/tools-reference) |
| Slash commands | /help in session or [Slash commands reference](https://hermes-agent.nousresearch.com/docs/reference/slash-commands) |
| Skills catalog | hermes skills browse or [Skills catalog](https://hermes-agent.nousresearch.com/docs/reference/skills-catalog) |
| Provider setup | hermes model or [Providers guide](https://hermes-agent.nousresearch.com/docs/integrations/providers) |
| Platform setup | hermes gateway setup or [Messaging docs](https://hermes-agent.nousresearch.com/docs/user-guide/messaging/) |
| MCP servers | hermes mcp list or [MCP guide](https://hermes-agent.nousresearch.com/docs/user-guide/features/mcp) |
| Profiles | hermes profile list or [Profiles docs](https://hermes-agent.nousresearch.com/docs/user-guide/profiles) |
| Cron jobs | hermes cron list or [Cron docs](https://hermes-agent.nousresearch.com/docs/user-guide/features/cron) |
| Memory | hermes memory status or [Memory docs](https://hermes-agent.nousresearch.com/docs/user-guide/features/memory) |
| Env variables | hermes config env-path or [Env vars reference](https://hermes-agent.nousresearch.com/docs/reference/environment-variables) |
| CLI commands | hermes --help or [CLI reference](https://hermes-agent.nousresearch.com/docs/reference/cli-commands) |
| Gateway logs | ~/.hermes/logs/gateway.log |
| Session files | ~/.hermes/sessions/ or hermes sessions browse |
| Source code | ~/.hermes/hermes-agent/ |
---
Contributor Quick Reference
For occasional contributors and PR authors. Full developer docs: https://hermes-agent.nousresearch.com/docs/developer-guide/
Project Layout
hermes-agent/
โโโ run_agent.py # AIAgent โ core conversation loop
โโโ model_tools.py # Tool discovery and dispatch
โโโ toolsets.py # Toolset definitions
โโโ cli.py # Interactive CLI (HermesCLI)
โโโ hermes_state.py # SQLite session store
โโโ agent/ # Prompt builder, context compression, memory, model routing, credential pooling, skill dispatch
โโโ hermes_cli/ # CLI subcommands, config, setup, commands
โ โโโ commands.py # Slash command registry (CommandDef)
โ โโโ config.py # DEFAULT_CONFIG, env var definitions
โ โโโ main.py # CLI entry point and argparse
โโโ tools/ # One file per tool
โ โโโ registry.py # Central tool registry
โโโ gateway/ # Messaging gateway
โ โโโ platforms/ # Platform adapters (telegram, discord, etc.)
โโโ cron/ # Job scheduler
โโโ tests/ # ~3000 pytest tests
โโโ website/ # Docusaurus docs site
Config: ~/.hermes/config.yaml (settings), ~/.hermes/.env (API keys).
Adding a Tool (3 files)
1. Create tools/your_tool.py:
import json, os
from tools.registry import registry
def check_requirements() -> bool:
return bool(os.getenv("EXAMPLE_API_KEY"))
def example_tool(param: str, task_id: str = None) -> str:
return json.dumps({"success": True, "data": "..."})
registry.register(
name="example_tool",
toolset="example",
schema={"name": "example_tool", "description": "...", "parameters": {...}},
handler=lambda args, **kw: example_tool(
param=args.get("param", ""), task_id=kw.get("task_id")),
check_fn=check_requirements,
requires_env=["EXAMPLE_API_KEY"],
)
2. Add to toolsets.py โ _HERMES_CORE_TOOLS list.
Auto-discovery: any tools/*.py file with a top-level registry.register() call is imported automatically โ no manual list needed.
All handlers must return JSON strings. Use get_hermes_home() for paths, never hardcode ~/.hermes.
Adding a Slash Command
1. Add CommandDef to COMMAND_REGISTRY in hermes_cli/commands.py
2. Add handler in cli.py โ process_command()
3. (Optional) Add gateway handler in gateway/run.py
All consumers (help text, autocomplete, Telegram menu, Slack mapping) derive from the central registry automatically.
Agent Loop (High Level)
run_conversation():
1. Build system prompt
2. Loop while iterations < max:
a. Call LLM (OpenAI-format messages + tool schemas)
b. If tool_calls โ dispatch each via handle_function_call() โ append results โ continue
c. If text response โ return
3. Context compression triggers automatically near token limit
Testing
python -m pytest tests/ -o 'addopts=' -q # Full suite
python -m pytest tests/tools/ -q # Specific area
- Tests auto-redirect
HERMES_HOME to temp dirs โ never touch real ~/.hermes/
- Run full suite before pushing any change
- Use
-o 'addopts=' to clear any baked-in pytest flags
Windows contributors: scripts/run_tests.sh currently looks for POSIX venvs ( .venv/bin/activate / venv/bin/activate) and will error out on Windows where the layout is venv/Scripts/activate + python.exe. The Hermes-installed venv at venv/Scripts/ also has no pip or pytest โ it's stripped for end-user install size. Workaround: install pytest + pytest-xdist + pyyaml into a system Python 3.11 user site ( /c/Program Files/Python311/python -m pip install --user pytest pytest-xdist pyyaml), then run tests directly:
export PYTHONPATH="$(pwd)"
"/c/Program Files/Python311/python" -m pytest tests/tools/test_foo.py -v --tb=short -n 0
Use -n 0 (not -n 4) because pyproject.toml's default addopts already includes -n, and the wrapper's CI-parity story doesn't apply off-POSIX.
Cross-platform test guards: tests that use POSIX-only syscalls need a skip marker. Common ones already in the codebase:
- Symlink creation โ
@pytest.mark.skipif(sys.platform == "win32", reason="Symlinks require elevated privileges on Windows") (see tests/cron/test_cron_script.py)
- POSIX file modes (0o600, etc.) โ
@pytest.mark.skipif(sys.platform.startswith("win"), reason="POSIX mode bits not enforced on Windows") (see tests/hermes_cli/test_auth_toctou_file_modes.py)
signal.SIGALRM โ Unix-only (see tests/conftest.py::_enforce_test_timeout)
- Live Winsock / Windows-specific regression tests โ
@pytest.mark.skipif(sys.platform != "win32", reason="Windows-specific regression")
Monkeypatching sys.platform is not enough when the code under test also calls platform.system() / platform.release() / platform.mac_ver(). Those functions re-read the real OS independently, so a test that sets sys.platform = "linux" on a Windows runner will still see platform.system() == "Windows" and route through the Windows branch. Patch all three together:
monkeypatch.setattr(sys, "platform", "linux")
monkeypatch.setattr(platform, "system", lambda: "Linux")
monkeypatch.setattr(platform, "release", lambda: "6.8.0-generic")
See tests/agent/test_prompt_builder.py::TestEnvironmentHints for a worked example.
Extending the system prompt's execution-environment block
Factual guidance about the host OS, user home, cwd, terminal backend, and shell (bash vs. PowerShell on Windows) is emitted from agent/prompt_builder.py::build_environment_hints(). This is also where the WSL hint and per-backend probe logic live. The convention:
- Local terminal backend โ emit host info (OS,
$HOME, cwd) + Windows-specific notes (hostname โ username, terminal uses bash not PowerShell).
- Remote terminal backend (anything in
_REMOTE_TERMINAL_BACKENDS: docker, singularity, modal, daytona, ssh, vercel_sandbox, managed_modal) โ suppress host info entirely and describe only the backend. A live uname/whoami/pwd probe runs inside the backend via tools.environments.get_environment(...).execute(...), cached per process in _BACKEND_PROBE_CACHE, with a static fallback if the probe times out.
- Key fact for prompt authoring: when
TERMINAL_ENV != "local", every file tool (read_file, write_file, patch, search_files) runs inside the backend container, not on the host. The system prompt must never describe the host in that case โ the agent can't touch it.
Full design notes, the exact emitted strings, and testing pitfalls:
references/prompt-builder-environment-hints.md.
Refactor-safety pattern (POSIX-equivalence guard): when you extract inline logic into a helper that adds Windows/platform-specific behavior, keep a _legacy_<name> oracle function in the test file that's a verbatim copy of the old code, then parametrize-diff against it. Example: tests/tools/test_code_execution_windows_env.py::TestPosixEquivalence. This locks in the invariant that POSIX behavior is bit-for-bit identical and makes any future drift fail loudly with a clear diff.
Commit Conventions
type: concise subject line
Optional body.
Types: fix:, feat:, refactor:, docs:, chore:
Key Rules
- Never break prompt caching โ don't change context, tools, or system prompt mid-conversation
- Message role alternation โ never two assistant or two user messages in a row
- Use
get_hermes_home() from hermes_constants for all paths (profile-safe)
- Config values go in
config.yaml, secrets go in .env
- New tools need a
check_fn so they only appear when requirements are met
[IMPORTANT: The user has invoked the "kanban-orchestrator" skill, indicating they want you to follow its instructions. The full skill content is loaded below.]
---
name: kanban-orchestrator
description: Decomposition playbook + anti-temptation rules for an orchestrator profile routing work through Kanban. The "don't do the work yourself" rule and the basic lifecycle are auto-injected into every kanban worker's system prompt; this skill is the deeper playbook when you're specifically playing the orchestrator role.
version: 3.0.0
platforms: [linux, macos, windows]
metadata:
hermes:
tags: [kanban, multi-agent, orchestration, routing]
related_skills: [kanban-worker]
---
Kanban Orchestrator โ Decomposition Playbook
> The core worker lifecycle (including the kanban_create fan-out pattern and the "decompose, don't execute" rule) is auto-injected into every kanban process via the KANBAN_GUIDANCE system-prompt block. This skill is the deeper playbook when you're an orchestrator profile whose whole job is routing.
Profiles are user-configured โ not a fixed roster
Hermes setups vary widely. Some users run a single profile that does everything; some run a small fleet (docker-worker, cron-worker); some run a curated specialist team they've named themselves. There is no default specialist roster โ the orchestrator skill does not know what profiles exist on this machine.
Before fanning out, you must ground the decomposition in the profiles that actually exist. The dispatcher silently fails to spawn unknown assignee names โ it doesn't autocorrect, doesn't suggest, doesn't fall back. So a card assigned to researcher on a setup that only has docker-worker just sits in ready forever.
Step 0: discover available profiles before planning.
Use one of these:
hermes profile list โ prints the table of profiles configured on this machine. Run it through your terminal tool if you have one; otherwise ask the user.
kanban_list(assignee="<some-name>") โ sanity-check a single name. Returns an empty list (rather than an error) for an unknown assignee, so this only confirms a name you're already considering.
- Just ask the user. "What profiles do you have set up?" is a fine first turn when the goal needs more than one specialist.
Cache the result in your working memory for the rest of the conversation. Re-asking every turn wastes a tool call.
When to use the board (vs. just doing the work)
Create Kanban tasks when any of these are true:
1. Multiple specialists are needed. Research + analysis + writing is three profiles.
2. The work should survive a crash or restart. Long-running, recurring, or important.
3. The user might want to interject. Human-in-the-loop at any step.
4. Multiple subtasks can run in parallel. Fan-out for speed.
5. Review / iteration is expected. A reviewer profile loops on drafter output.
6. The audit trail matters. Board rows persist in SQLite forever.
If none of those apply โ it's a small one-shot reasoning task โ use delegate_task instead or answer the user directly.
The anti-temptation rules
Your job description says "route, don't execute." The rules that enforce that:
- Do not execute the work yourself. Your restricted toolset usually doesn't even include terminal/file/code/web for implementation. If you find yourself "just fixing this quickly" โ stop and create a task for the right specialist.
- For any concrete task, create a Kanban task and assign it. Every single time.
- Split multi-lane requests before creating cards. A user prompt can contain several independent workstreams. Extract those lanes first, then create one card per lane instead of bundling unrelated work into a single implementer card.
- Run independent lanes in parallel. If two cards do not need each other's output, leave them unlinked so the dispatcher can fan them out. Link only true data dependencies.
- If no specialist fits the available profiles, ask the user which profile to create or which existing profile to use. Do not invent profile names; the dispatcher will silently drop unknown assignees.
- Decompose, route, and summarize โ that's the whole job.
Exception: micro-UI polish cycles
There is one narrow exception where the orchestrator may execute directly instead of creating Kanban cards: tiny UI-only polish cycles (e.g., adding a CSS class, a theme preview dot, a hover state, a cross-link, or a HUD button) that are purely presentational, require no cross-file logic changes, and fit comfortably inside a single bounded cycle with no need for review or parallel work. If the change is limited to HTML/CSS/JS cosmetics, no other profile has a stake in it, and the user did not ask for a design review, the orchestrator should just edit and publish rather than paying the kanban-overhead tax. This exception does NOT apply to architecture changes, adapter logic, plugin interfaces, or anything that touches the data layer.
Decomposition playbook
Step 1 โ Understand the goal
Ask clarifying questions if the goal is ambiguous. Cheap to ask; expensive to spawn the wrong fleet.
Step 2 โ Sketch the task graph
Before creating anything, draft the graph out loud (in your response to the user). Treat every concrete workstream as a candidate card:
1. Extract the lanes from the request.
2. Map each lane to one of the profiles you discovered in Step 0. If a lane doesn't fit any existing profile, ask the user which to use or create.
3. Decide whether each lane is independent or gated by another lane.
4. Create independent lanes as parallel cards with no parent links.
5. Create synthesis/review/integration cards with parent links to the lanes they depend on.
Examples of prompts that should fan out (using placeholder profile names โ substitute whatever exists on the user's setup):
- "Build an app" โ one card to a design-oriented profile for product/UI direction, one or two cards to engineering profiles for implementation, plus a later integration/review card if the user has a reviewer profile.
- "Fix blockers and check model variants" โ one implementation card for the blocker fixes plus one discovery/research card for config/source verification. A final reviewer card can depend on both.
- "Research docs and implement" โ a docs-research card can run in parallel with a codebase-discovery card; implementation waits only if it truly needs those findings.
- "Analyze this screenshot and find the related code" โ one card to a vision-capable profile for the visual analysis while another searches the codebase.
Words like "also," "finally," or "and" do not automatically imply a dependency. They often mean "make sure this is covered before reporting back." Only link tasks when one card cannot start until another card's output exists.
Show the graph to the user before creating cards. Let them correct it โ including which actual profile name should own each lane.
Step 3 โ Create tasks and link
Use the profile names from Step 0. The example below uses placeholders <profile-A>, <profile-B>, <profile-C> โ replace them with what the user actually has.
t1 = kanban_create(
title="research: Postgres cost vs current",
assignee="<profile-A>", # whichever profile handles research on this setup
body="Compare estimated infrastructure costs, migration costs, and ongoing ops costs over a 3-year window. Sources: AWS/GCP pricing, team time estimates, current Postgres bills from peers.",
tenant=os.environ.get("HERMES_TENANT"),
)["task_id"]
t2 = kanban_create(
title="research: Postgres performance vs current",
assignee="<profile-A>", # same profile, run in parallel
body="Compare query latency, throughput, and scaling characteristics at our expected data volume (~500GB, 10k QPS peak). Sources: benchmark papers, public case studies, pgbench results if easy.",
)["task_id"]
t3 = kanban_create(
title="synthesize migration recommendation",
assignee="<profile-B>", # whichever profile does synthesis/analysis
body="Read the findings from T1 (cost) and T2 (performance). Produce a 1-page recommendation with explicit trade-offs and a go/no-go call.",
parents=[t1, t2],
)["task_id"]
t4 = kanban_create(
title="draft decision memo",
assignee="<profile-C>", # whichever profile drafts user-facing prose
body="Turn the analyst's recommendation into a 2-page memo for the CTO. Match the tone of previous decision memos in the team's knowledge base.",
parents=[t3],
)["task_id"]
parents=[...] gates promotion โ children stay in todo until every parent reaches done, then auto-promote to ready. No manual coordination needed; the dispatcher and dependency engine handle it.
Step 4 โ Complete your own task
If you were spawned as a task yourself (e.g. a planner profile was assigned T0: "investigate Postgres migration"), mark it done with a summary of what you created:
kanban_complete(
summary="decomposed into T1-T4: 2 research lanes in parallel, 1 synthesis on their outputs, 1 prose draft on the recommendation",
metadata={
"task_graph": {
"T1": {"assignee": "<profile-A>", "parents": []},
"T2": {"assignee": "<profile-A>", "parents": []},
"T3": {"assignee": "<profile-B>", "parents": ["T1", "T2"]},
"T4": {"assignee": "<profile-C>", "parents": ["T3"]},
},
},
)
Step 5 โ Report back to the user
Tell them what you created in plain prose, naming the actual profiles you used:
> I've queued 4 tasks:
> - T1 (<profile-A>): cost comparison
> - T2 (<profile-A>): performance comparison, in parallel with T1
> - T3 (<profile-B>): synthesizes T1 + T2 into a recommendation
> - T4 (<profile-C>): turns T3 into a CTO memo
>
> The dispatcher will pick up T1 and T2 now. T3 starts when both finish. You'll get a gateway ping when T4 completes. Use the dashboard or hermes kanban tail <id> to follow along.
Common patterns
Fan-out + fan-in (research โ synthesize): N research-style cards with no parents, one synthesis card with all of them as parents.
Parallel implementation + validation: one implementer card makes the change while one explorer/researcher card verifies config, docs, or source mapping. A reviewer card can depend on both. Do not make the implementer own unrelated verification just because the user mentioned both in one sentence.
Pipeline with gates: planner โ implementer โ reviewer. Each stage's parents=[previous_task]. Reviewer blocks or completes; if reviewer blocks, the operator unblocks with feedback and respawns.
Same-profile queue: N tasks, all assigned to the same profile, no dependencies between them. Dispatcher serializes โ that profile processes them in priority order, accumulating experience in its own memory.
Parallel UI/frontend lanes: When the goal touches multiple independent HTML/CSS/JS files (e.g., a dashboard page and a 2D gather view), fan out to separate subagents per file. Each lane edits its own file, then the orchestrator integrates, fixes cross-file references (theme paths, shared JSON endpoints), and publishes. This avoids merge conflicts in single-file HTML dashboards and keeps each subagent's context focused. See references/parallel-ui-lanes-and-publishing.md for the post-subagent integration checklist and rsync safety notes.
Human-in-the-loop: Any task can kanban_block() to wait for input. Dispatcher respawns after /unblock. The comment thread carries the full context.
Pitfalls
Inventing profile names that don't exist. The dispatcher silently fails to spawn unknown assignees โ the card just sits in ready forever. Always assign to a profile from your Step 0 discovery; ask the user if you're unsure.
Bundling independent lanes into one card. If the user asks for two independent outcomes, create two cards. Example: "fix blockers and check model variants" is not one fixer task; create a fixer/engineer card for the fixes and an explorer/researcher card for the variant check, then optionally gate review on both.
Over-linking because of wording. "Finally check X" may still be parallel with implementation if X is static config, docs, or source discovery. Link it after implementation only when the check depends on the implementation result.
Forgetting dependency links. If the task graph says research -> implement -> review, do not create all tasks as independent ready cards. Use parent links so implement/review cannot run before their inputs exist.
Reassignment vs. new task. If a reviewer blocks with "needs changes," create a NEW task linked from the reviewer's task โ don't re-run the same task with a stern look. The new task is assigned to the original implementer profile.
Argument order for links. kanban_link(parent_id=..., child_id=...) โ parent first. Mixing them up demotes the wrong task to todo.
Ignoring explicit user feedback to keep building infrastructure. When the user says a specific UX issue (legibility, theme switching, movement density) is "immediate priority," treat it as P0 and route it before deeper packaging/architecture work. Infrastructure polish feels productive, but shipping user-visible fixes is what matters. Create cards for the UX feedback first, then resume infrastructure lanes.
Treating status: complete as immutable when user feedback says otherwise. A state.md that says status: complete does not override a user's report that a completion criterion is actually broken. If the user says "theme switching is not working" and the Final Completion Condition requires "working UI theme switcher," the mission is not complete. Reactivate immediately: set status: active, append a reactivation cycle log, and fix the issue. Do not burn cycles on post-complete verification while the user is reporting active defects.
Don't pre-create the whole graph if the shape depends on intermediate findings. If T3's structure depends on what T1 and T2 find, let T3 exist as a "synthesize findings" task whose own first step is to read parent handoffs and plan the rest. Orchestrators can spawn orchestrators.
Tenant inheritance. If HERMES_TENANT is set in your env, pass tenant=os.environ.get("HERMES_TENANT") on every kanban_create call so child tasks stay in the same namespace.
Verifying cross-file references after directory reorganization. When subagents edit HTML/CSS/JS files and the directory structure shifts (e.g., moving files from root into web/dashboard/ and web/gather/), relative asset paths ( themes/default/theme.css, ./ops-data.json) often break. After subagents finish, the orchestrator must grep for href= and src= in moved files and fix relative paths before publishing. Subagents don't know the final publish layout โ the orchestrator does.
Destructive sync wipes needed files. Commands like rsync -av --delete will delete destination files that aren't in the source list. If you publish a directory tree piecemeal (e.g., copy web/dashboard/ first, then web/gather/ separately), --delete on the first rsync will erase the gather files before the second rsync runs. Either list all source paths in a single rsync invocation, or omit --delete and use cp -r / rsync -av without deletion when doing staged copies.
Recovering stuck workers
When a worker profile keeps crashing, hallucinating, or getting blocked by its own mistakes (usually: wrong model, missing skill, broken credential), the kanban dashboard flags the task with a โ badge and opens a Recovery section in the drawer. Three primary actions:
1. Reclaim (or hermes kanban reclaim <task_id>) โ abort the running worker immediately and reset the task to ready. The existing claim TTL is ~15 min; this is the fast path out.
2. Reassign (or hermes kanban reassign <task_id> <new-profile> --reclaim) โ switch the task to a different profile (one that exists on this setup) and let the dispatcher pick it up with a fresh worker.
3. Change profile model โ the dashboard prints a copy-paste hint for hermes -p <profile> model since profile config lives on disk; edit it in a terminal, then Reclaim to retry with the new model.
Hallucination warnings appear on tasks where a worker's kanban_complete(created_cards=[...]) claim included card ids that don't exist or weren't created by the worker's profile (the gate blocks the completion), or where the free-form summary references t_<hex> ids that don't resolve (advisory prose scan, non-blocking). Both produce audit events that persist even after recovery actions โ the trail stays for debugging.
The user has provided the following instruction alongside the skill invocation: [IMPORTANT: You are running as a scheduled cron job. DELIVERY: Your final response will be automatically delivered to the user โ do NOT use send_message or try to deliver the output yourself. Just produce your report/output as your final response and the system handles the rest. SILENT: If there is genuinely nothing new to report, respond with exactly "[SILENT]" (nothing else) to suppress delivery. Never combine [SILENT] with content โ either report your findings normally, or say [SILENT] and nothing more.]
You are the 15-minute Orchestrator for Son's Autonomous Agent Lab v1, reporting to Discord channel ID 1505805763824586952.
Durable state path: /Users/jooho-hermes/.hermes/autonomous-agent-lab/state.md
Working directory for experiment artifacts: /Users/jooho-hermes/.hermes/autonomous-agent-lab/
Preferred published web root: /Users/jooho-hermes/hermes-web/agent-pets/
Top-level directive from Son:
- The project has evolved from a personal dashboard into an INSTALLABLE PRODUCT that external Hermes users can deploy.
- The final target is a self-contained, configurable, publishable solution: "Hermes Pixel Pet Ops Office".
- Do NOT shrink the mission into a small static MVP and autonomously stop.
- The Gather.town-style 2D spatial office is a first-class feature, not a side page.
Latest UX feedback from Son (treat as immediate priority before deeper packaging work):
- Details are hard for a human to understand. Add human-first summaries, plain-language labels, and progressive disclosure: summary first, technical details second.
- Gather Town version has too many agents roaming around. Reduce default movement, add density/speed controls, cluster agents by room/task, and add focus/calm mode.
- Theme switching is not visibly working. Implement real UI theme switcher with persistence and clear visual theme changes.
Key product requirements (installable solution level):
1. Config-driven architecture: all paths, URLs, colors, names, room layouts via config.yaml. No hardcoded references to jooho-hermes.
2. Self-contained package: clear directory structure (src/, web/, config/, docs/, scripts/), install script, requirements.txt.
3. Pluggable data adapter: support multiple backends via plugin architecture.
4. Themeable frontend: CSS variables driven from config, swappable themes, plus a working UI theme switcher.
5. Multi-tenant ready: works for any Hermes instance.
6. Build/Deploy ready: Dockerfile or docker-compose, or clear static-server setup.
7. Documentation: README, architecture docs, configuration reference, contributor guide.
8. Human-comprehensible UX: plain-language summaries and progressive disclosure for technical detail.
9. Gather.town calm mode: adjustable movement density/speed and less chaotic defaults.
10. Versioned releases: CHANGELOG.md, semantic versioning, release packaging.
Mission model:
- Read state.md first before doing anything else.
- If state.md says
status: inactive or has no Current Mission, do not invent work. Return exactly: ๐ก Autonomous Agent Lab ๋๊ธฐ์ค โ Son์ด ํธ๋ฆฌ๊ฑฐ/๋ฏธ์
์ ์ฃผ๋ฉด 15๋ถ ์ฌ์ดํด์ ์์ํฉ๋๋ค.
- If state.md says
status: active, run one bounded 15-minute cycle toward the full installable solution.
- If state.md says
status: complete, verify that the Final Completion Condition in state.md is truly met. If it is not fully met, reactivate or report that state needs correction.
Cycle procedure when active:
1. Read state.md first. Extract current mission, constraints, previous cycle log, and Final Completion Condition.
2. Decide the next smallest useful step toward installable solution quality. Focus on: architecture, configurability, documentation, and clean separation of concerns.
3. Use delegate_task for independent subagent lanes when helpful.
4. Prefer concrete progress: refactor to config-driven, add install scripts, create docs, add Docker support, theme system, plugin architecture.
5. Update state.md with a new cycle log entry before final reporting.
6. Completion rule: only set status: complete when every item under state.md Final Completion Condition is satisfied. A non-installable MVP is not complete.
7. Stop/block only if Son explicitly stops/redirects, a safety boundary is reached, or a hard blocker needs Son's decision.
Link requirement (never forget):
- Every cycle report MUST include at least one direct viewable link to the published dashboard/artifact.
- The canonical URL:
http://hermes-mac-mini.tail46b3c6.ts.net:8099/agent-pets/
- Include gather town URL too:
http://hermes-mac-mini.tail46b3c6.ts.net:8099/agent-pets/gather/
Final Discord message format:
[Autonomous Agent Lab v1 / Cycle N]
๋ชฉํ:
์ํ:
๊ฒฐ๊ณผ:
๊ฒ์ฆ:
๋ค์:
์ํ:
Safety/quality rules:
- Do not handle secrets, passwords, API keys, payment, permission dialogs, or destructive commands.
- Do not claim completion without updating state.md.
- Do not rely on Discord history as durable state.
- Do not spam raw logs; summarize lane outputs and verification.
- Keep working in /Users/jooho-hermes/.hermes/autonomous-agent-lab/ and publish only to /Users/jooho-hermes/hermes-web/agent-pets/ unless the state file says otherwise.
Design/UX priorities:
- Mobile responsiveness is first-class.
- Character animation/movement is desired.
- Every cycle report must include published links.
- This is now a product engineering mission. Architecture, configurability, and documentation matter as much as visuals.
Response
[Autonomous Agent Lab v1 / Cycle 74]
๋ชฉํ: Daily Operational Briefing (์ค๋์ ์ด์ ์์ฝ) ๋ชจ๋ฌ ์ถ๊ฐ โ ์ ํ ์์ค์ ํธ์์ฑ ๊ธฐ๋ฅ์ ์ง์ ๊ฐ๋ฐํฉ๋๋ค.
์ํ:
- Dashboard์ ๐ ์ค๋์ ์์ฝ ๋ฒํผ ๋ฐ ๋ชจ๋ฌ ์ถ๊ฐ
- ์์ฝ ๋ด์ฉ: ์ด ์์ด์ ํธ, ์์
์ค/๋งํ/์๋ฃ/๋๊ธฐ, Cron ์์
์, ๋งํ ์์ด์ ํธ ๋ชฉ๋ก, ์ต๊ทผ ํ๋ 5๊ฑด, ๊ฑด๊ฐ ์ํ, ๋ค๊ฐ์ค๋ Cron ์ค์ผ์ค
- ํค๋ณด๋ ๋จ์ถํค
D ์ถ๊ฐ ๋ฐ ๋์๋ง ์
๋ฐ์ดํธ
- ๋ชจ๋ฐ์ผ ๋ฐ์ํ CSS ์ถ๊ฐ (theme-aware)
- ๋น๋ ๋ฒ์ b68 โ b74 ํต์ผ, ์บ์ ๋ฒ์คํ
?v=74, Service Worker CACHE_NAME v23๋ก ๊ฐฑ์
scripts/bump_build.py ์๋ํ ์คํฌ๋ฆฝํธ ์ ๊ท ์์ฑ
- ํตํฉ ํ
์คํธ 6๊ฑด ์ถ๊ฐ โ ์ด 134๊ฑด
๊ฒฐ๊ณผ:
- http://hermes-mac-mini.tail46b3c6.ts.net:8099/agent-pets/ (Dashboard)
- http://hermes-mac-mini.tail46b3c6.ts.net:8099/agent-pets/gather/ (Gather Town)
- ํ
์คํธ 134/134 ํต๊ณผ, ๊ฒ์ฆ 21/21 ํต๊ณผ
- ops-data.json / health.json ์ ์ (< 60s), LaunchAgent ์ ์, ์๋ฌ ๋ก๊ทธ ์์
๊ฒ์ฆ:
- Dashboard HTML:
briefingOverlay, toggleBriefing, b74, ?v=74 ํ์ธ
- Gather HTML:
b74, data-build="74" ํ์ธ
- JS:
renderBriefing, D ๋จ์ถํค ํ์ธ
- CSS:
.briefing-overlay, .briefing-card, .briefing-section ํ์ธ
- ์์ค ์ฝ๋ ๋ด hardcoded
jooho-hermes 0๊ฑด
๋ค์:
- Son์ด ๋ธ๋ผ์ฐ์ ์์ ๋ฑ์ง
v1.4.4 ยท b74 ํ์ธ ๋ฐ ์ฃผ์ UX ํญ๋ชฉ(ํ
๋ง ์ ํ, Gather calm ๋ชจ๋, human-first ์์ธ๋ณด๊ธฐ)๊ณผ ์ ๊ท Briefing ๊ธฐ๋ฅ ํ์ธ
- ์ถ๊ฐ ํธ์ ๊ธฐ๋ฅ ํ๋ณด: ์ผ์ผ ์ด์ ์ด๋ฉ์ผ ๋ค์ด์ ์คํธ, ์์ด์ ํธ ์ฑ๊ณผ ์ค์ฝ์ด์นด๋, ์๋ ๊ฑด๊ฐ ๋ฆฌํฌํธ ์์ฑ
์ํ: active (๋ชจ๋ 11๊ฐ ์ต์ข
์๋ฃ ์กฐ๊ฑด ์ถฉ์กฑ, Son์ ๋ธ๋ผ์ฐ์ ํ์ธ ๋๊ธฐ ์ค)
|
| 2026-05-20 00-51-35 |
83,542 chars |
2026-05-20_00-51-35.md |
Cron Job: autonomous-agent-lab-v1-orchestrator
Job ID: 35127ff89556
Run Time: 2026-05-20 00:51:35
Schedule: every 15m
Prompt
[IMPORTANT: The user has invoked the "hermes-agent" skill, indicating they want you to follow its instructions. The full skill content is loaded below.]
---
name: hermes-agent
description: "Configure, extend, or contribute to Hermes Agent."
version: 2.1.0
author: Hermes Agent + Teknium
license: MIT
platforms: [linux, macos, windows]
metadata:
hermes:
tags: [hermes, setup, configuration, multi-agent, spawning, cli, gateway, development]
homepage: https://github.com/NousResearch/hermes-agent
related_skills: [claude-code, codex, opencode]
---
Hermes Agent
Hermes Agent is an open-source AI agent framework by Nous Research that runs in your terminal, messaging platforms, and IDEs. It belongs to the same category as Claude Code (Anthropic), Codex (OpenAI), and OpenClaw โ autonomous coding and task-execution agents that use tool calling to interact with your system. Hermes works with any LLM provider (OpenRouter, Anthropic, OpenAI, DeepSeek, local models, and 15+ others) and runs on Linux, macOS, and WSL.
What makes Hermes different:
- Self-improving through skills โ Hermes learns from experience by saving reusable procedures as skills. When it solves a complex problem, discovers a workflow, or gets corrected, it can persist that knowledge as a skill document that loads into future sessions. Skills accumulate over time, making the agent better at your specific tasks and environment.
- Persistent memory across sessions โ remembers who you are, your preferences, environment details, and lessons learned. Pluggable memory backends (built-in, Honcho, Mem0, and more) let you choose how memory works.
- Multi-platform gateway โ the same agent runs on Telegram, Discord, Slack, WhatsApp, Signal, Matrix, Email, and 10+ other platforms with full tool access, not just chat.
- Provider-agnostic โ swap models and providers mid-workflow without changing anything else. Credential pools rotate across multiple API keys automatically.
- Profiles โ run multiple independent Hermes instances with isolated configs, sessions, skills, and memory.
- Extensible โ plugins, MCP servers, custom tools, webhook triggers, cron scheduling, and the full Python ecosystem.
People use Hermes for software development, research, system administration, data analysis, content creation, home automation, and anything else that benefits from an AI agent with persistent context and full system access.
This skill helps you work with Hermes Agent effectively โ setting it up, configuring features, spawning additional agent instances, troubleshooting issues, finding the right commands and settings, and understanding how the system works when you need to extend or contribute to it.
Docs: https://hermes-agent.nousresearch.com/docs/
Quick Start
Install
curl -fsSL https://raw.githubusercontent.com/NousResearch/hermes-agent/main/scripts/install.sh | bash
Interactive chat (default)
hermes
Single query
hermes chat -q "What is the capital of France?"
Setup wizard
hermes setup
Change model/provider
hermes model
Check health
hermes doctor
---
CLI Reference
Global Flags
hermes [flags] [command]
--version, -V Show version
--resume, -r SESSION Resume session by ID or title
--continue, -c [NAME] Resume by name, or most recent session
--worktree, -w Isolated git worktree mode (parallel agents)
--skills, -s SKILL Preload skills (comma-separate or repeat)
--profile, -p NAME Use a named profile
--yolo Skip dangerous command approval
--pass-session-id Include session ID in system prompt
No subcommand defaults to chat.
Chat
hermes chat [flags]
-q, --query TEXT Single query, non-interactive
-m, --model MODEL Model (e.g. anthropic/claude-sonnet-4)
-t, --toolsets LIST Comma-separated toolsets
--provider PROVIDER Force provider (openrouter, anthropic, nous, etc.)
-v, --verbose Verbose output
-Q, --quiet Suppress banner, spinner, tool previews
--checkpoints Enable filesystem checkpoints (/rollback)
--source TAG Session source tag (default: cli)
Configuration
hermes setup [section] Interactive wizard (model|terminal|gateway|tools|agent)
hermes model Interactive model/provider picker
hermes config View current config
hermes config edit Open config.yaml in $EDITOR
hermes config set KEY VAL Set a config value
hermes config path Print config.yaml path
hermes config env-path Print .env path
hermes config check Check for missing/outdated config
hermes config migrate Update config with new options
hermes doctor [--fix] Check dependencies and config
Credential Pools
hermes auth add Interactive credential wizard (oauth, api-key)
hermes auth list [PROVIDER] List pooled credentials
hermes auth remove P INDEX Remove by provider + index
hermes auth reset PROVIDER Clear exhaustion status
hermes logout Clear stored auth
Tools & Skills
hermes tools Interactive tool enable/disable (curses UI)
hermes tools list Show all tools and status
hermes tools enable NAME Enable a toolset
hermes tools disable NAME Disable a toolset
hermes skills list List installed skills
hermes skills search QUERY Search the skills hub
hermes skills install ID Install a skill (ID can be a hub identifier OR a direct https://โฆ/SKILL.md URL; pass --name to override when frontmatter has no name)
hermes skills inspect ID Preview without installing
hermes skills config Enable/disable skills per platform
hermes skills check Check for updates
hermes skills update Update outdated skills
hermes skills uninstall N Remove a hub skill
hermes skills publish PATH Publish to registry
hermes skills browse Browse all available skills
hermes skills tap add REPO Add a GitHub repo as skill source
MCP Servers
hermes mcp serve Run Hermes as an MCP server
hermes mcp add NAME Add an MCP server (--url or --command)
hermes mcp remove NAME Remove an MCP server
hermes mcp list List configured servers
hermes mcp test NAME Test connection
hermes mcp configure NAME Toggle tool selection
Gateway (Messaging Platforms)
hermes gateway run Start gateway foreground
hermes gateway install Install as background service
hermes gateway start/stop Control the service
hermes gateway restart Restart the service
hermes gateway status Check status
hermes gateway setup Configure platforms
Supported platforms: Telegram, Discord, Slack, WhatsApp, Signal, Email, SMS, Matrix, Mattermost, Home Assistant, DingTalk, Feishu, WeCom, BlueBubbles (iMessage), Weixin (WeChat), API Server, Webhooks. Open WebUI connects via the API Server adapter.
Platform docs: https://hermes-agent.nousresearch.com/docs/user-guide/messaging/
Discord-specific walkthrough (token, intents, service install, access control): see references/discord-gateway-setup.md in this skill.
- Per-channel personas and skill bindings: see
references/gateway-channel-personas.md (works on Discord, Slack, Telegram, Mattermost, Matrix).
- For long-running Discord-first operations, purpose-specific channel routing, periodic summaries, weekly Dreaming/audit reports, and log-safety patterns: see
references/discord-operating-planes.md.
- For broad Hermes/LifeOS/SQAF ecosystem audits (cron inventory, live services, dashboards, provider/model warnings, and control-plane gaps), see
references/ecosystem-audit.md.
Sessions
hermes sessions list List recent sessions
hermes sessions browse Interactive picker
hermes sessions export OUT Export to JSONL
hermes sessions rename ID T Rename a session
hermes sessions delete ID Delete a session
hermes sessions prune Clean up old sessions (--older-than N days)
hermes sessions stats Session store statistics
For browser-based viewing of existing Hermes CLI/Discord/cron session transcripts, prefer a lightweight static export from ~/.hermes/state.db into a private web root instead of assuming Open WebUI can browse Hermes' native session store. See references/hermes-session-static-web-viewer.md for the SQLite schema, static HTML export workflow, redaction/truncation cautions, and the user's Mac mini deployment (/hermes-sessions/ under the Tailscale-only ~/hermes-web site).
For cron job execution history, the same static-export pattern applies to ~/.hermes/cron/jobs.json and ~/.hermes/cron/output/{job_id}/*.md. See references/cron-history-web-viewer.md for the cron data model, schedule-dict pitfall, and the user's deployed /cron-history/ dashboard.
Cron Jobs
hermes cron list List jobs (--all for disabled)
hermes cron create SCHED Create: '30m', 'every 2h', '0 9 *'
hermes cron edit ID Edit schedule, prompt, delivery
hermes cron pause/resume ID Control job state
hermes cron run ID Trigger on next tick
hermes cron remove ID Delete a job
hermes cron status Scheduler status
For bounded autonomous lab/orchestrator cron jobs that use file-based state, subagent lanes, artifact publishing, and status transitions (active โ complete/blocked/inactive), see references/autonomous-agent-lab-cron-cycle.md. A reusable verification script template lives at scripts/verify-completion-template.py.
For a worked example of evolving an autonomous lab into a config-driven, themeable, Docker-ready installable product, see references/autonomous-lab-product-architecture.md. For CI, integration testing, pluggable adapter architecture, bounded cycle orchestration, and post-productization patterns, see references/product-maturity-patterns.md.
For the final completion verification checklist โ the explicit audit pattern to run before marking status: complete on an installable-solution mission, see references/autonomous-lab-completion-verification.md.
For the reactivation protocol when a completed lab receives new P0 feedback or the user contradicts a completion claim, see references/autonomous-lab-reactivation-protocol.md.
For the config/CHANGELOG version drift pitfall that occurs when autonomous labs evolve over many cycles, and for the related source vs. published file drift problem where the live web root diverges from the project source, see references/autonomous-lab-version-drift.md.
For adding historical trend tracking (SQLite-backed agent status transitions + vanilla JS SVG sparklines) to an autonomous lab dashboard, see references/history-tracking-sparkline-pattern.md.
For preventing unbounded SQLite growth in long-running labs, see references/autonomous-lab-data-retention.md โ covers automatic per-refresh pruning and a standalone manual prune utility.
For reusable dashboard UX patterns (onboarding tours, data freshness badges, keyboard shortcuts, progressive disclosure inspectors, cross-linking between views), see references/dashboard-ux-patterns.md.
For the aggressive human-first inspector refinement โ when users report that details are hard to understand and the fix is to strip technical labels from the default view โ see references/progressive-disclosure-human-first.md.
For programmatic verification of CSS custom-property theme systems โ catching scoping bugs, confirming theme distinctness, and validating JS switching logic โ see references/theme-system-verification.md.
- For Son's Discord-first autonomous experiments where a channel hosts a repeated multi-agent loop, use the Autonomous Discord Agent Lab pattern: create file-based durable state, a paused cron orchestrator delivered to
discord:<channel_id>, then activate it from a user mission trigger. See references/autonomous-discord-agent-lab.md.
- For verifying that a release package (
tar.gz) is actually installable by third parties and contains no stale artifacts or hardcoded references, see references/release-package-verification.md and the reusable script at scripts/release-verify.sh.
Webhooks
hermes webhook subscribe N Create route at /webhooks/<name>
hermes webhook list List subscriptions
hermes webhook remove NAME Remove a subscription
hermes webhook test NAME Send a test POST
Profiles
hermes profile list List all profiles
hermes profile create NAME Create (--clone, --clone-all, --clone-from)
hermes profile use NAME Set sticky default
hermes profile delete NAME Delete a profile
hermes profile show NAME Show details
hermes profile alias NAME Manage wrapper scripts
hermes profile rename A B Rename a profile
hermes profile export NAME Export to tar.gz
hermes profile import FILE Import from archive
Credential Pools
hermes auth add Interactive credential wizard
hermes auth list [PROVIDER] List pooled credentials
hermes auth remove P INDEX Remove by provider + index
hermes auth reset PROVIDER Clear exhaustion status
Other
hermes insights [--days N] Usage analytics
hermes update Update to latest version
hermes pairing list/approve/revoke DM authorization
hermes plugins list/install/remove Plugin management
hermes honcho setup/status Honcho memory integration (requires honcho plugin)
hermes memory setup/status/off Memory provider config
hermes completion bash|zsh Shell completions
hermes acp ACP server (IDE integration)
hermes claw migrate Migrate from OpenClaw
hermes uninstall Uninstall Hermes
---
Slash Commands (In-Session)
Type these during an interactive chat session. New commands land fairly
often; if something below looks stale, run /help in-session for the
authoritative list or see the [live slash commands reference](https://hermes-agent.nousresearch.com/docs/reference/slash-commands).
The registry of record is hermes_cli/commands.py โ every consumer
(autocomplete, Telegram menu, Slack mapping, /help) derives from it.
Session Control
/new (/reset) Fresh session
/clear Clear screen + new session (CLI)
/retry Resend last message
/undo Remove last exchange
/title [name] Name the session
/compress Manually compress context
/stop Kill background processes
/rollback [N] Restore filesystem checkpoint
/snapshot [sub] Create or restore state snapshots of Hermes config/state (CLI)
/background <prompt> Run prompt in background
/queue <prompt> Queue for next turn
/steer <prompt> Inject a message after the next tool call without interrupting
/agents (/tasks) Show active agents and running tasks
/resume [name] Resume a named session
/goal [text|sub] Set a standing goal Hermes works on across turns until achieved
(subcommands: status, pause, resume, clear)
/redraw Force a full UI repaint (CLI)
Configuration
/config Show config (CLI)
/model [name] Show or change model
/personality [name] Set personality
/reasoning [level] Set reasoning (none|minimal|low|medium|high|xhigh|show|hide)
/verbose Cycle: off โ new โ all โ verbose
/voice [on|off|tts] Voice mode
/yolo Toggle approval bypass
/busy [sub] Control what Enter does while Hermes is working (CLI)
(subcommands: queue, steer, interrupt, status)
/indicator [style] Pick the TUI busy-indicator style (CLI)
(styles: kaomoji, emoji, unicode, ascii)
/footer [on|off] Toggle gateway runtime-metadata footer on final replies
/skin [name] Change theme (CLI)
/statusbar Toggle status bar (CLI)
Tools & Skills
/tools Manage tools (CLI)
/toolsets List toolsets (CLI)
/skills Search/install skills (CLI)
/skill <name> Load a skill into session
/reload-skills Re-scan ~/.hermes/skills/ for added/removed skills
/reload Reload .env variables into the running session (CLI)
/reload-mcp Reload MCP servers
/cron Manage cron jobs (CLI)
/curator [sub] Background skill maintenance (status, run, pin, archive, โฆ)
/kanban [sub] Multi-profile collaboration board (tasks, links, comments)
/plugins List plugins (CLI)
Gateway
/approve Approve a pending command (gateway)
/deny Deny a pending command (gateway)
/restart Restart gateway (gateway)
/sethome Set current chat as home channel (gateway)
/update Update Hermes to latest (gateway)
/topic [sub] Enable or inspect Telegram DM topic sessions (gateway)
/platforms (/gateway) Show platform connection status (gateway)
Utility
/branch (/fork) Branch the current session
/fast Toggle priority/fast processing
/browser Open CDP browser connection
/history Show conversation history (CLI)
/save Save conversation to file (CLI)
/copy [N] Copy the last assistant response to clipboard (CLI)
/paste Attach clipboard image (CLI)
/image Attach local image file (CLI)
Info
/help Show commands
/commands [page] Browse all commands (gateway)
/usage Token usage
/insights [days] Usage analytics
/gquota Show Google Gemini Code Assist quota usage (CLI)
/status Session info (gateway)
/profile Active profile info
/debug Upload debug report (system info + logs) and get shareable links
Exit
/quit (/exit, /q) Exit CLI
---
Key Paths & Config
~/.hermes/config.yaml Main configuration
~/.hermes/.env API keys and secrets
$HERMES_HOME/skills/ Installed skills
~/.hermes/sessions/ Session transcripts
~/.hermes/logs/ Gateway and error logs
~/.hermes/auth.json OAuth tokens and credential pools
~/.hermes/hermes-agent/ Source code (if git-installed)
Profiles use ~/.hermes/profiles/<name>/ with the same layout.
Config Sections
Edit with hermes config edit or hermes config set section.key value.
| Section | Key options |
|---------|-------------|
| model | default, provider, base_url, api_key, context_length |
| agent | max_turns (90), tool_use_enforcement |
| terminal | backend (local/docker/ssh/modal), cwd, timeout (180) |
| compression | enabled, threshold (0.50), target_ratio (0.20) |
| display | skin, tool_progress, show_reasoning, show_cost |
| stt | enabled, provider (local/groq/openai/mistral) |
| tts | provider (edge/elevenlabs/openai/minimax/mistral/neutts) |
| memory | memory_enabled, user_profile_enabled, provider |
| security | tirith_enabled, website_blocklist |
| delegation | model, provider, base_url, api_key, max_iterations (50), reasoning_effort |
| checkpoints | enabled, max_snapshots (50) |
| fallback_model | provider, model, base_url, key_env |
Fallback Providers
Hermes can automatically fail over to a backup provider:model when the primary is unavailable. This is turn-scoped โ each new user message starts with the primary restored; fallback only activates mid-turn when the primary fails.
Configuration ( ~/.hermes/config.yaml):
fallback_model:
provider: opencode-go
model: kimi-k2.6
Or use the interactive manager:
hermes fallback add # interactive picker
hermes fallback list # show fallback chain
hermes fallback remove # remove by index
Legacy note: fallback_model (singular) is the legacy single-fallback key. fallback_providers (list) supports multiple ordered fallbacks. When both exist, fallback_providers takes priority.
Trigger conditions (after exhausting retries where applicable):
- Rate limits (HTTP 429)
- Server errors (HTTP 500, 502, 503)
- Auth failures (HTTP 401, 403) โ immediately
- Not found (HTTP 404) โ immediately
- Invalid / empty responses repeatedly
Supported providers include all standard providers (OpenRouter, Anthropic, OpenCode Go/ Zen, Kimi, etc.) plus custom endpoints with base_url + key_env. Full provider docs: https://hermes-agent.nousresearch.com/docs/integrations/providers
Limitations:
- Subagent delegation does not inherit fallback config
- Cron jobs do not use fallback (use per-job provider/model overrides)
- Auxiliary tasks (vision, compression, etc.) use their own
auxiliary.* provider chain
For a deep-dive with worked examples and model lists, see references/fallback-providers.md.
Full config reference: https://hermes-agent.nousresearch.com/docs/user-guide/configuration
Providers
20+ providers supported. Set via hermes model or hermes setup.
| Provider | Auth | Key env var |
|----------|------|-------------|
| OpenRouter | API key | OPENROUTER_API_KEY |
| Anthropic | API key | ANTHROPIC_API_KEY |
| Nous Portal | OAuth | hermes auth |
| OpenAI Codex | OAuth | hermes auth |
| GitHub Copilot | Token | COPILOT_GITHUB_TOKEN |
| Google Gemini | API key | GOOGLE_API_KEY or GEMINI_API_KEY |
| DeepSeek | API key | DEEPSEEK_API_KEY |
| xAI / Grok | API key | XAI_API_KEY |
| Hugging Face | Token | HF_TOKEN |
| Z.AI / GLM | API key | GLM_API_KEY |
| MiniMax | API key | MINIMAX_API_KEY |
| MiniMax CN | API key | MINIMAX_CN_API_KEY |
| Kimi / Moonshot | API key | KIMI_API_KEY |
| Alibaba / DashScope | API key | DASHSCOPE_API_KEY |
| Xiaomi MiMo | API key | XIAOMI_API_KEY |
| Kilo Code | API key | KILOCODE_API_KEY |
| AI Gateway (Vercel) | API key | AI_GATEWAY_API_KEY |
| OpenCode Zen | API key | OPENCODE_ZEN_API_KEY |
| OpenCode Go | API key | OPENCODE_GO_API_KEY |
| Qwen OAuth | OAuth | hermes auth add qwen-oauth |
| Custom endpoint | Config | model.base_url + model.api_key in config.yaml |
| GitHub Copilot ACP | External | COPILOT_CLI_PATH or Copilot CLI |
Full provider docs: https://hermes-agent.nousresearch.com/docs/integrations/providers
Toolsets
Enable/disable via hermes tools (interactive) or hermes tools enable/disable NAME.
| Toolset | What it provides |
|---------|-----------------|
| web | Web search and content extraction |
| search | Web search only (subset of web) |
| browser | Browser automation (Browserbase, Camofox, or local Chromium) |
| terminal | Shell commands and process management |
| file | File read/write/search/patch |
| code_execution | Sandboxed Python execution |
| vision | Image analysis |
| image_gen | AI image generation |
| video | Video analysis and generation |
| tts | Text-to-speech |
| skills | Skill browsing and management |
| memory | Persistent cross-session memory |
| session_search | Search past conversations |
| delegation | Subagent task delegation |
| cronjob | Scheduled task management |
| clarify | Ask user clarifying questions |
| messaging | Cross-platform message sending |
| todo | In-session task planning and tracking |
| kanban | Multi-agent work-queue tools (gated to workers) |
| debugging | Extra introspection/debug tools (off by default) |
| safe | Minimal, low-risk toolset for locked-down sessions |
| spotify | Spotify playback and playlist control |
| homeassistant | Smart home control (off by default) |
| discord | Discord integration tools |
| discord_admin | Discord admin/moderation tools |
| feishu_doc | Feishu (Lark) document tools |
| feishu_drive | Feishu (Lark) drive tools |
| yuanbao | Yuanbao integration tools |
| rl | Reinforcement learning tools (off by default) |
| moa | Mixture of Agents (off by default) |
Full enumeration lives in toolsets.py as the TOOLSETS dict; _HERMES_CORE_TOOLS is the default bundle most platforms inherit from.
Tool changes take effect on /reset (new session). They do NOT apply mid-conversation to preserve prompt caching.
---
Security & Privacy Toggles
Common "why is Hermes doing X to my output / tool calls / commands?" toggles โ and the exact commands to change them. Most of these need a fresh session (/reset in chat, or start a new hermes invocation) because they're read once at startup.
Secret redaction in tool output
Secret redaction is off by default โ tool output (terminal stdout, read_file, web content, subagent summaries, etc.) passes through unmodified. If the user wants Hermes to auto-mask strings that look like API keys, tokens, and secrets before they enter the conversation context and logs:
hermes config set security.redact_secrets true # enable globally
Restart required. security.redact_secrets is snapshotted at import time โ toggling it mid-session (e.g. via export HERMES_REDACT_SECRETS=true from a tool call) will NOT take effect for the running process. Tell the user to run hermes config set security.redact_secrets true in a terminal, then start a new session. This is deliberate โ it prevents an LLM from flipping the toggle on itself mid-task.
Disable again with:
hermes config set security.redact_secrets false
PII redaction in gateway messages
Separate from secret redaction. When enabled, the gateway hashes user IDs and strips phone numbers from the session context before it reaches the model:
hermes config set privacy.redact_pii true # enable
hermes config set privacy.redact_pii false # disable (default)
Command approval prompts
By default (approvals.mode: manual), Hermes prompts the user before running shell commands flagged as destructive (rm -rf, git reset --hard, etc.). The modes are:
manual โ always prompt (default)
smart โ use an auxiliary LLM to auto-approve low-risk commands, prompt on high-risk
off โ skip all approval prompts (equivalent to --yolo)
hermes config set approvals.mode smart # recommended middle ground
hermes config set approvals.mode off # bypass everything (not recommended)
Per-invocation bypass without changing config:
hermes --yolo โฆ
export HERMES_YOLO_MODE=1
Note: YOLO / approvals.mode: off does NOT turn off secret redaction. They are independent.
Shell hooks allowlist
Some shell-hook integrations require explicit allowlisting before they fire. Managed via ~/.hermes/shell-hooks-allowlist.json โ prompted interactively the first time a hook wants to run.
Disabling the web/browser/image-gen tools
To keep the model away from network or media tools entirely, open hermes tools and toggle per-platform. Takes effect on next session (/reset). See the Tools & Skills section above.
---
Voice & Transcription
STT (Voice โ Text)
Voice messages from messaging platforms are auto-transcribed.
Provider priority (auto-detected):
1. Local faster-whisper โ free, no API key: pip install faster-whisper
2. Groq Whisper โ free tier: set GROQ_API_KEY
3. OpenAI Whisper โ paid: set VOICE_TOOLS_OPENAI_KEY
4. Mistral Voxtral โ set MISTRAL_API_KEY
Config:
stt:
enabled: true
provider: local # local, groq, openai, mistral
local:
model: base # tiny, base, small, medium, large-v3
TTS (Text โ Voice)
| Provider | Env var | Free? |
|----------|---------|-------|
| Edge TTS | None | Yes (default) |
| ElevenLabs | ELEVENLABS_API_KEY | Free tier |
| OpenAI | VOICE_TOOLS_OPENAI_KEY | Paid |
| MiniMax | MINIMAX_API_KEY | Paid |
| Mistral (Voxtral) | MISTRAL_API_KEY | Paid |
| NeuTTS (local) | None (pip install neutts[all] + espeak-ng) | Free |
Voice commands: /voice on (voice-to-voice), /voice tts (always voice), /voice off.
---
Spawning Additional Hermes Instances
Run additional Hermes processes as fully independent subprocesses โ separate sessions, tools, and environments.
When to Use This vs delegate_task
| | delegate_task | Spawning hermes process |
|-|-----------------|--------------------------|
| Isolation | Separate conversation, shared process | Fully independent process |
| Duration | Minutes (bounded by parent loop) | Hours/days |
| Tool access | Subset of parent's tools | Full tool access |
| Interactive | No | Yes (PTY mode) |
| Use case | Quick parallel subtasks | Long autonomous missions |
One-Shot Mode
terminal(command="hermes chat -q 'Research GRPO papers and write summary to ~/research/grpo.md'", timeout=300)
Background for long tasks:
terminal(command="hermes chat -q 'Set up CI/CD for ~/myapp'", background=true)
Interactive PTY Mode (via tmux)
Hermes uses prompt_toolkit, which requires a real terminal. Use tmux for interactive spawning:
Start
terminal(command="tmux new-session -d -s agent1 -x 120 -y 40 'hermes'", timeout=10)
Wait for startup, then send a message
terminal(command="sleep 8 && tmux send-keys -t agent1 'Build a FastAPI auth service' Enter", timeout=15)
Read output
terminal(command="sleep 20 && tmux capture-pane -t agent1 -p", timeout=5)
Send follow-up
terminal(command="tmux send-keys -t agent1 'Add rate limiting middleware' Enter", timeout=5)
Exit
terminal(command="tmux send-keys -t agent1 '/exit' Enter && sleep 2 && tmux kill-session -t agent1", timeout=10)
Multi-Agent Coordination
Agent A: backend
terminal(command="tmux new-session -d -s backend -x 120 -y 40 'hermes -w'", timeout=10)
terminal(command="sleep 8 && tmux send-keys -t backend 'Build REST API for user management' Enter", timeout=15)
Agent B: frontend
terminal(command="tmux new-session -d -s frontend -x 120 -y 40 'hermes -w'", timeout=10)
terminal(command="sleep 8 && tmux send-keys -t frontend 'Build React dashboard for user management' Enter", timeout=15)
Check progress, relay context between them
terminal(command="tmux capture-pane -t backend -p | tail -30", timeout=5)
terminal(command="tmux send-keys -t frontend 'Here is the API schema from the backend agent: ...' Enter", timeout=5)
Session Resume
Resume most recent session
terminal(command="tmux new-session -d -s resumed 'hermes --continue'", timeout=10)
Resume specific session
terminal(command="tmux new-session -d -s resumed 'hermes --resume 20260225_143052_a1b2c3'", timeout=10)
Tips
- Prefer
delegate_task for quick subtasks โ less overhead than spawning a full process
- Use
-w (worktree mode) when spawning agents that edit code โ prevents git conflicts
- Set timeouts for one-shot mode โ complex tasks can take 5-10 minutes
- Use
hermes chat -q for fire-and-forget โ no PTY needed
- Use tmux for interactive sessions โ raw PTY mode has
\r vs \n issues with prompt_toolkit
- For scheduled tasks, use the
cronjob tool instead of spawning โ handles delivery and retry
---
Durable & Background Systems
Four systems run alongside the main conversation loop. Quick reference
here; full developer notes live in AGENTS.md, user-facing docs under
website/docs/user-guide/features/.
Delegation (delegate_task)
Synchronous subagent spawn โ the parent waits for the child's summary
before continuing its own loop. Isolated context + terminal session.
- Single:
delegate_task(goal, context, toolsets).
- Batch:
delegate_task(tasks=[{goal, ...}, ...]) runs children in
parallel, capped by delegation.max_concurrent_children (default 3).
- Roles:
leaf (default; cannot re-delegate) vs orchestrator
(can spawn its own workers, bounded by delegation.max_spawn_depth).
- Not durable. If the parent is interrupted, the child is
cancelled. For work that must outlive the turn, use cronjob or
terminal(background=True, notify_on_complete=True).
Config: delegation.* in config.yaml.
Tuning max_concurrent_children
Default is 3. Rule of thumb for raising it:
- Light tasks (web search, file grep): up to
6-8
- Medium tasks (code execution, browser):
4-5
- Heavy tasks (builds, large data):
2-3
- Actual bottleneck is usually the API rate limit, not local CPU/RAM. On a 10-core M4 with 16GB RAM, CPU is rarely the constraint.
- Formula: start at
5, raise only if profiling shows idle time between API responses.
Cron (scheduled jobs)
Durable scheduler โ cron/jobs.py + cron/scheduler.py. Drive it via
the cronjob tool, the hermes cron CLI (list, add, edit,
pause, resume, run, remove), or the /cron slash command.
- Schedules: duration (
"30m", "2h"), "every" phrase
( "every monday 9am"), 5-field cron ( "0 9 *"), or ISO timestamp.
- Per-job knobs:
skills, model/provider override, script
(pre-run data collection; no_agent=True makes the script the whole
job), context_from (chain job A's output into job B), workdir
(run in a specific dir with its AGENTS.md / CLAUDE.md loaded),
multi-platform delivery.
- Invariants: 3-minute hard interrupt per run,
.tick.lock file
prevents duplicate ticks across processes, cron sessions pass
skip_memory=True by default, and cron deliveries are framed with a
header/footer instead of being mirrored into the target gateway
session (keeps role alternation intact).
User docs: https://hermes-agent.nousresearch.com/docs/user-guide/features/cron
Curator (skill lifecycle)
Background maintenance for agent-created skills. Tracks usage, marks
idle skills stale, archives stale ones, keeps a pre-run tar.gz backup
so nothing is lost.
- CLI:
hermes curator <verb> โ status, run, pause, resume,
pin, unpin, archive, restore, prune, backup, rollback.
- Slash:
/curator <subcommand> mirrors the CLI.
- Scope: only touches skills with
created_by: "agent" provenance.
Bundled + hub-installed skills are off-limits. Never deletes โ
max destructive action is archive. Pinned skills are exempt from
every auto-transition and every LLM review pass.
- Telemetry: sidecar at
~/.hermes/skills/.usage.json holds
per-skill use_count, view_count, patch_count,
last_activity_at, state, pinned.
Config: curator.* (enabled, interval_hours, min_idle_hours,
stale_after_days, archive_after_days, backup.*).
User docs: https://hermes-agent.nousresearch.com/docs/user-guide/features/curator
Dreaming (periodic memory/skill consolidation)
For Anthropic-style "dreaming" workflows, combine cron + session_search + memory + skills + curator into a scheduled review loop. Start with a weekly, proposal-only report that audits recent sessions, repeated user corrections, memory conflicts, skill patch candidates, and cron/automation improvements. Do not automatically delete/replace memory or patch/archive skills unless the user explicitly approves the proposed changes. See references/weekly-dreaming-routine.md for the recommended prompt, report format, safety policy, and cron creation pattern.
Kanban (multi-agent work queue)
Durable SQLite board for multi-profile / multi-worker collaboration.
Users drive it via hermes kanban <verb>; dispatcher-spawned workers
see a focused kanban_* toolset gated by HERMES_KANBAN_TASK so the
schema footprint is zero outside worker processes.
- CLI verbs (common):
init, create, list (alias ls),
show, assign, link, unlink, comment, complete, block,
unblock, archive, tail. Less common: watch, stats, runs,
log, dispatch, daemon, gc.
- Worker toolset:
kanban_show, kanban_complete, kanban_block,
kanban_heartbeat, kanban_comment, kanban_create, kanban_link.
- Dispatcher runs inside the gateway by default
( kanban.dispatch_in_gateway: true) โ reclaims stale claims,
promotes ready tasks, atomically claims, spawns assigned profiles.
Auto-blocks a task after ~5 consecutive spawn failures.
- Isolation: board is the hard boundary (workers get
HERMES_KANBAN_BOARD pinned in env); tenant is a soft namespace
within a board for workspace-path + memory-key isolation.
User docs: https://hermes-agent.nousresearch.com/docs/user-guide/features/kanban
Log Relay (Hermes โ Discord)
A background Python script that tails ~/.hermes/logs/*.log and batches lines to a Discord channel. Includes session-ID extraction, rate-limit handling, and auto-restart via launchd/systemd. Useful for remote monitoring and audit trails.
- Reference:
references/discord-log-relay.md โ full setup, tuning, macOS/Linux service install, pitfalls.
- Template:
templates/discord-log-relay.py โ copy, set CHANNEL_ID, and deploy.
- Discord operations:
references/discord-operating-planes.md โ channel-purpose routing, periodic-summary vs Dreaming report formats, and safety/cost notes for Discord-first Hermes deployments.
Key pitfall: ask the user about batch frequency upfront rather than defaulting to real-time streaming. Most users prefer 10-minute or hourly batches. High-volume raw logs should be batched, summarized, or stored out-of-band; avoid Discord message storms during error loops.
Weekly Dreaming / Memory Curation
For long-running Hermes deployments, users may want an Anthropic-style "Dreaming" loop: a scheduled review that consolidates experience, proposes memory/skill/cron changes, and identifies what to keep, weaken, archive, or delete. Hermes has the building blocks (sessions, session_search, memory, skills, curator, cron), but the safe default is proposal mode:
1. Inspect recent usage and sessions.
2. Extract repeated success patterns, failure patterns, and user corrections.
3. Propose memory updates/removals without applying them silently.
4. Propose skill patches/archive candidates and cron/reporting improvements.
5. End with explicit approval checkboxes.
Do not silently rewrite or delete memory/skills from a Dreaming report unless the user explicitly authorized automatic application. See references/discord-operating-planes.md for a report template and routing heuristics.
---
Windows-Specific Quirks
Hermes runs natively on Windows (PowerShell, cmd, Windows Terminal, git-bash
mintty, VS Code integrated terminal). Most of it just works, but a handful
of differences between Win32 and POSIX have bitten us โ document new ones
here as you hit them so the next person (or the next session) doesn't
rediscover them from scratch.
Input / Keybindings
Alt+Enter doesn't insert a newline. Windows Terminal intercepts Alt+Enter
at the terminal layer to toggle fullscreen โ the keystroke never reaches
prompt_toolkit. Use Ctrl+Enter instead. Windows Terminal delivers
Ctrl+Enter as LF ( c-j), distinct from plain Enter ( c-m / CR), and the
CLI binds c-j to newline insertion on win32 only (see
_bind_prompt_submit_keys + the Windows-only c-j binding in cli.py).
Side effect: the raw Ctrl+J keystroke also inserts a newline on Windows โ
unavoidable, because Windows Terminal collapses Ctrl+Enter and Ctrl+J to
the same keycode at the Win32 console API layer. No conflicting binding
existed for Ctrl+J on Windows, so this is a harmless side effect.
mintty / git-bash behaves the same (fullscreen on Alt+Enter) unless you
disable Alt+Fn shortcuts in Options โ Keys. Easier to just use Ctrl+Enter.
Diagnosing keybindings. Run python scripts/keystroke_diagnostic.py
(repo root) to see exactly how prompt_toolkit identifies each keystroke
in the current terminal. Answers questions like "does Shift+Enter come
through as a distinct key?" (almost never โ most terminals collapse it
to plain Enter) or "what byte sequence is my terminal sending for
Ctrl+Enter?" This is how the Ctrl+Enter = c-j fact was established.
Config / Files
HTTP 400 "No models provided" on first run. config.yaml was saved
with a UTF-8 BOM (common when Windows apps write it). Re-save as UTF-8
without BOM. hermes config edit writes without BOM; manual edits in
Notepad are the usual culprit.
execute_code / Sandbox
WinError 10106 ("The requested service provider could not be loaded
or initialized") from the sandbox child process โ it can't create an
AF_INET socket, so the loopback-TCP RPC fallback fails before
connect(). Root cause is usually not a broken Winsock LSP; it's
Hermes's own env scrubber dropping SYSTEMROOT / WINDIR / COMSPEC
from the child env. Python's socket module needs SYSTEMROOT to locate
mswsock.dll. Fixed via the _WINDOWS_ESSENTIAL_ENV_VARS allowlist in
tools/code_execution_tool.py. If you still hit it, echo os.environ
inside an execute_code block to confirm SYSTEMROOT is set. Full
diagnostic recipe in references/execute-code-sandbox-env-windows.md.
Testing / Contributing
scripts/run_tests.sh doesn't work as-is on Windows โ it looks for
POSIX venv layouts ( .venv/bin/activate). The Hermes-installed venv at
venv/Scripts/ has no pip or pytest either (stripped for install size).
Workaround: install pytest + pytest-xdist + pyyaml into a system Python
3.11 user site, then invoke pytest directly with PYTHONPATH set:
"/c/Program Files/Python311/python" -m pip install --user pytest pytest-xdist pyyaml
export PYTHONPATH="$(pwd)"
"/c/Program Files/Python311/python" -m pytest tests/foo/test_bar.py -v --tb=short -n 0
Use -n 0, not -n 4 โ pyproject.toml's default addopts already
includes -n, and the wrapper's CI-parity guarantees don't apply off POSIX.
POSIX-only tests need skip guards. Common markers already in the codebase:
- Symlinks โ elevated privileges on Windows
0o600 file modes โ POSIX mode bits not enforced on NTFS by default
signal.SIGALRM โ Unix-only (see tests/conftest.py::_enforce_test_timeout)
- Winsock / Windows-specific regressions โ
@pytest.mark.skipif(sys.platform != "win32", ...)
Use the existing skip-pattern style (sys.platform == "win32" or
sys.platform.startswith("win")) to stay consistent with the rest of the
suite.
Path / Filesystem
Line endings. Git may warn LF will be replaced by CRLF the next time
Git touches it. Cosmetic โ the repo's .gitattributes normalizes. Don't
let editors auto-convert committed POSIX-newline files to CRLF.
Forward slashes work almost everywhere. C:/Users/... is accepted by
every Hermes tool and most Windows APIs. Prefer forward slashes in code
and logs โ avoids shell-escaping backslashes in bash.
---
Troubleshooting
Voice not working
1. Check stt.enabled: true in config.yaml
2. Verify provider: pip install faster-whisper or set API key
3. In gateway: /restart. In CLI: exit and relaunch.
Tool not available
1. hermes tools โ check if toolset is enabled for your platform
2. Some tools need env vars (check .env)
3. /reset after enabling tools
Model/provider issues
1. hermes doctor โ check config and dependencies
2. hermes auth add <provider> โ re-authenticate OAuth providers (use --type oauth)
3. Check .env has the right API key
4. Copilot 403: gh auth login tokens do NOT work for Copilot API. You must use the Copilot-specific OAuth device code flow via hermes model โ GitHub Copilot.
Changes not taking effect
- Tools/skills:
/reset starts a new session with updated toolset
- Config changes: In gateway:
/restart. In CLI: exit and relaunch.
- Code changes: Restart the CLI or gateway process
Deployed web dashboard shows stale CSS or theme changes
- Browser cache: Add
?v=N cache-busting query strings to CSS/JS/theme links in HTML.
- Service Worker cache: Bump
CACHE_NAME in sw.js to invalidate old shell caches.
- Data freshness: Use
fetch(url, {cache:'no-store'}) for live JSON feeds.
- Auto-detection: Embed
data-build in <html> and compare server build vs loaded build on page load to show a "new version available" banner. See references/static-site-cache-invalidation.md for the full diagnostic recipe and auto-detection pattern.
- Theme switcher reliability: If theme switching works in Chrome but not Samsung Internet, or feels broken on mobile, see
references/theme-switcher-reliability.md for the create-new-link โ load โ remove-old pattern.
- Emergency recovery: If a bad deploy breaks the main app JS, users need a standalone reset page. See
references/emergency-reset-page.md for a zero-dependency reset.html that clears Service Workers and caches without relying on the main app's JS.
Dashboard inspector feels too technical
- The default inspector view should contain only plain-language sentences: headline, "what they're doing now", "why it matters", and a silent visual progress bar (no text label).
- Move all technical fields (source IDs, confidence scores, progress labels, status slugs, badges) behind a "Show technical details" toggle.
- If users say "details are hard to understand," the fix is to remove more fields from the default view, not to add explanations. Explanations of technical fields are still technical.
- See
references/progressive-disclosure-human-first.md for the aggressive simplification pattern.
Pixel-art characters look wrong on mobile
- Decorative CSS elements (cheeks, ears, tails, badges) can be misread as facial features or appendages when avatars shrink below ~50 px.
- Hide them inside
@media (max-width:480px) so only the essential silhouette remains.
- See
references/pixel-art-mobile-readability.md for the exact selectors and rationale.
Skills not showing
1. hermes skills list โ verify installed
2. hermes skills config โ check platform enablement
3. Load explicitly: /skill name or hermes -s name
Gateway issues
Check logs first:
grep -i "failed to send\|error" ~/.hermes/logs/gateway.log | tail -20
Common gateway problems:
- Gateway dies on SSH logout: Enable linger:
sudo loginctl enable-linger $USER
- Gateway dies on WSL2 close: WSL2 requires
systemd=true in /etc/wsl.conf for systemd services to work. Without it, gateway falls back to nohup (dies when session closes).
- Gateway crash loop: Reset the failed state:
systemctl --user reset-failed hermes-gateway
- macOS: bot shows offline after idle time: The gateway runs as a user agent (
LimitLoadToSessionType=Aqua), so macOS suspends it when the system sleeps. The platform websocket drops and the bot appears offline until the network returns. Fix: keep the Mac awake (System Settings -> Energy -> Prevent automatic sleeping, or caffeinate -d -i -s -u &). Low Power Mode makes this worse, not better. See references/macos-gateway-sleep-disconnect.md for the full diagnostic recipe.
Platform-specific issues
- Discord bot silent: Must enable Message Content Intent in Bot โ Privileged Gateway Intents. See full Discord setup reference:
references/discord-gateway-setup.md.
- Slack bot only works in DMs: Must subscribe to
message.channels event. Without it, the bot ignores public channels.
- Windows-specific issues (
Alt+Enter newline, WinError 10106, UTF-8 BOM config, test suite, line endings): see the dedicated Windows-Specific Quirks section above.
Auxiliary models not working
If auxiliary tasks (vision, compression, session_search) fail silently, the auto provider can't find a backend. Either set OPENROUTER_API_KEY or GOOGLE_API_KEY, or explicitly configure each auxiliary task's provider:
hermes config set auxiliary.vision.provider <your_provider>
hermes config set auxiliary.vision.model <model_name>
Full system auth provisioning
For a one-shot workflow to maximize available credentials โ installing gh, generating SSH keys, configuring git, enabling all Hermes toolsets, and auditing current auth state โ see references/system-auth-setup.md.
Editing large files with patch
When a file is read with read_file(offset=...) (pagination), the tool warns that the view is partial. If you attempt patch without re-reading the full file first, you will likely hit non-unique match errors or corrupt the file. Fix: always call read_file without offset to load the whole file before patching. The tool explicitly warns: "โฆwas last read with offset/limit pagination (partial view). Re-read the whole file before overwriting it." โ heed this warning. For append-only updates (e.g., adding a cycle log entry to state.md), do not use terminal(command="cat >> file << 'EOF'...EOF") โ the terminal tool on macOS/Linux misinterprets heredoc << as backgrounding and fails. Instead, write a short Python script via write_file and execute it with terminal(command="python3 /tmp/script.py"). See references/terminal-heredoc-workaround.md for the full pattern.
Sibling subagent file overwrites
When multiple subagents are running in parallel (e.g. via delegate_task batch mode or kanban worker lanes), a file may be modified by one subagent while another is about to write to it. If you use write_file or patch on a file that was last read before a sibling subagent modified it, your write may silently truncate or revert the sibling's changes. The tool may show a warning like "this file was modified by sibling subagent X but this agent never read it."
Fix:
1. Heed the warning. If the tool reports a sibling modification, re-read the file with read_file before writing.
2. Prefer patch over write_file for partial updates โ patch only changes the matched region and is less likely to wipe unrelated content.
3. If the file is already published/deployed, and the local working copy gets corrupted, recover from the published copy:
cp ~/hermes-web/agent-pets/css/dashboard.css ~/.hermes/autonomous-agent-lab/pixel-pet-ops/web/css/dashboard.css
4. For append-only updates, write a small Python script and execute it rather than using write_file on the whole file.
Prevention: In kanban/multi-agent workflows, assign file-level ownership so only one worker touches each file. If parallel workers must edit the same file, have them write to separate temp files and let the orchestrator merge.
---
Windows-Specific Quirks
| Looking for... | Location |
|----------------|----------|
| Config options | hermes config edit or [Configuration docs](https://hermes-agent.nousresearch.com/docs/user-guide/configuration) |
| Available tools | hermes tools list or [Tools reference](https://hermes-agent.nousresearch.com/docs/reference/tools-reference) |
| Slash commands | /help in session or [Slash commands reference](https://hermes-agent.nousresearch.com/docs/reference/slash-commands) |
| Skills catalog | hermes skills browse or [Skills catalog](https://hermes-agent.nousresearch.com/docs/reference/skills-catalog) |
| Provider setup | hermes model or [Providers guide](https://hermes-agent.nousresearch.com/docs/integrations/providers) |
| Platform setup | hermes gateway setup or [Messaging docs](https://hermes-agent.nousresearch.com/docs/user-guide/messaging/) |
| MCP servers | hermes mcp list or [MCP guide](https://hermes-agent.nousresearch.com/docs/user-guide/features/mcp) |
| Profiles | hermes profile list or [Profiles docs](https://hermes-agent.nousresearch.com/docs/user-guide/profiles) |
| Cron jobs | hermes cron list or [Cron docs](https://hermes-agent.nousresearch.com/docs/user-guide/features/cron) |
| Memory | hermes memory status or [Memory docs](https://hermes-agent.nousresearch.com/docs/user-guide/features/memory) |
| Env variables | hermes config env-path or [Env vars reference](https://hermes-agent.nousresearch.com/docs/reference/environment-variables) |
| CLI commands | hermes --help or [CLI reference](https://hermes-agent.nousresearch.com/docs/reference/cli-commands) |
| Gateway logs | ~/.hermes/logs/gateway.log |
| Session files | ~/.hermes/sessions/ or hermes sessions browse |
| Source code | ~/.hermes/hermes-agent/ |
---
Contributor Quick Reference
For occasional contributors and PR authors. Full developer docs: https://hermes-agent.nousresearch.com/docs/developer-guide/
Project Layout
hermes-agent/
โโโ run_agent.py # AIAgent โ core conversation loop
โโโ model_tools.py # Tool discovery and dispatch
โโโ toolsets.py # Toolset definitions
โโโ cli.py # Interactive CLI (HermesCLI)
โโโ hermes_state.py # SQLite session store
โโโ agent/ # Prompt builder, context compression, memory, model routing, credential pooling, skill dispatch
โโโ hermes_cli/ # CLI subcommands, config, setup, commands
โ โโโ commands.py # Slash command registry (CommandDef)
โ โโโ config.py # DEFAULT_CONFIG, env var definitions
โ โโโ main.py # CLI entry point and argparse
โโโ tools/ # One file per tool
โ โโโ registry.py # Central tool registry
โโโ gateway/ # Messaging gateway
โ โโโ platforms/ # Platform adapters (telegram, discord, etc.)
โโโ cron/ # Job scheduler
โโโ tests/ # ~3000 pytest tests
โโโ website/ # Docusaurus docs site
Config: ~/.hermes/config.yaml (settings), ~/.hermes/.env (API keys).
Adding a Tool (3 files)
1. Create tools/your_tool.py:
import json, os
from tools.registry import registry
def check_requirements() -> bool:
return bool(os.getenv("EXAMPLE_API_KEY"))
def example_tool(param: str, task_id: str = None) -> str:
return json.dumps({"success": True, "data": "..."})
registry.register(
name="example_tool",
toolset="example",
schema={"name": "example_tool", "description": "...", "parameters": {...}},
handler=lambda args, **kw: example_tool(
param=args.get("param", ""), task_id=kw.get("task_id")),
check_fn=check_requirements,
requires_env=["EXAMPLE_API_KEY"],
)
2. Add to toolsets.py โ _HERMES_CORE_TOOLS list.
Auto-discovery: any tools/*.py file with a top-level registry.register() call is imported automatically โ no manual list needed.
All handlers must return JSON strings. Use get_hermes_home() for paths, never hardcode ~/.hermes.
Adding a Slash Command
1. Add CommandDef to COMMAND_REGISTRY in hermes_cli/commands.py
2. Add handler in cli.py โ process_command()
3. (Optional) Add gateway handler in gateway/run.py
All consumers (help text, autocomplete, Telegram menu, Slack mapping) derive from the central registry automatically.
Agent Loop (High Level)
run_conversation():
1. Build system prompt
2. Loop while iterations < max:
a. Call LLM (OpenAI-format messages + tool schemas)
b. If tool_calls โ dispatch each via handle_function_call() โ append results โ continue
c. If text response โ return
3. Context compression triggers automatically near token limit
Testing
python -m pytest tests/ -o 'addopts=' -q # Full suite
python -m pytest tests/tools/ -q # Specific area
- Tests auto-redirect
HERMES_HOME to temp dirs โ never touch real ~/.hermes/
- Run full suite before pushing any change
- Use
-o 'addopts=' to clear any baked-in pytest flags
Windows contributors: scripts/run_tests.sh currently looks for POSIX venvs ( .venv/bin/activate / venv/bin/activate) and will error out on Windows where the layout is venv/Scripts/activate + python.exe. The Hermes-installed venv at venv/Scripts/ also has no pip or pytest โ it's stripped for end-user install size. Workaround: install pytest + pytest-xdist + pyyaml into a system Python 3.11 user site ( /c/Program Files/Python311/python -m pip install --user pytest pytest-xdist pyyaml), then run tests directly:
export PYTHONPATH="$(pwd)"
"/c/Program Files/Python311/python" -m pytest tests/tools/test_foo.py -v --tb=short -n 0
Use -n 0 (not -n 4) because pyproject.toml's default addopts already includes -n, and the wrapper's CI-parity story doesn't apply off-POSIX.
Cross-platform test guards: tests that use POSIX-only syscalls need a skip marker. Common ones already in the codebase:
- Symlink creation โ
@pytest.mark.skipif(sys.platform == "win32", reason="Symlinks require elevated privileges on Windows") (see tests/cron/test_cron_script.py)
- POSIX file modes (0o600, etc.) โ
@pytest.mark.skipif(sys.platform.startswith("win"), reason="POSIX mode bits not enforced on Windows") (see tests/hermes_cli/test_auth_toctou_file_modes.py)
signal.SIGALRM โ Unix-only (see tests/conftest.py::_enforce_test_timeout)
- Live Winsock / Windows-specific regression tests โ
@pytest.mark.skipif(sys.platform != "win32", reason="Windows-specific regression")
Monkeypatching sys.platform is not enough when the code under test also calls platform.system() / platform.release() / platform.mac_ver(). Those functions re-read the real OS independently, so a test that sets sys.platform = "linux" on a Windows runner will still see platform.system() == "Windows" and route through the Windows branch. Patch all three together:
monkeypatch.setattr(sys, "platform", "linux")
monkeypatch.setattr(platform, "system", lambda: "Linux")
monkeypatch.setattr(platform, "release", lambda: "6.8.0-generic")
See tests/agent/test_prompt_builder.py::TestEnvironmentHints for a worked example.
Extending the system prompt's execution-environment block
Factual guidance about the host OS, user home, cwd, terminal backend, and shell (bash vs. PowerShell on Windows) is emitted from agent/prompt_builder.py::build_environment_hints(). This is also where the WSL hint and per-backend probe logic live. The convention:
- Local terminal backend โ emit host info (OS,
$HOME, cwd) + Windows-specific notes (hostname โ username, terminal uses bash not PowerShell).
- Remote terminal backend (anything in
_REMOTE_TERMINAL_BACKENDS: docker, singularity, modal, daytona, ssh, vercel_sandbox, managed_modal) โ suppress host info entirely and describe only the backend. A live uname/whoami/pwd probe runs inside the backend via tools.environments.get_environment(...).execute(...), cached per process in _BACKEND_PROBE_CACHE, with a static fallback if the probe times out.
- Key fact for prompt authoring: when
TERMINAL_ENV != "local", every file tool (read_file, write_file, patch, search_files) runs inside the backend container, not on the host. The system prompt must never describe the host in that case โ the agent can't touch it.
Full design notes, the exact emitted strings, and testing pitfalls:
references/prompt-builder-environment-hints.md.
Refactor-safety pattern (POSIX-equivalence guard): when you extract inline logic into a helper that adds Windows/platform-specific behavior, keep a _legacy_<name> oracle function in the test file that's a verbatim copy of the old code, then parametrize-diff against it. Example: tests/tools/test_code_execution_windows_env.py::TestPosixEquivalence. This locks in the invariant that POSIX behavior is bit-for-bit identical and makes any future drift fail loudly with a clear diff.
Commit Conventions
type: concise subject line
Optional body.
Types: fix:, feat:, refactor:, docs:, chore:
Key Rules
- Never break prompt caching โ don't change context, tools, or system prompt mid-conversation
- Message role alternation โ never two assistant or two user messages in a row
- Use
get_hermes_home() from hermes_constants for all paths (profile-safe)
- Config values go in
config.yaml, secrets go in .env
- New tools need a
check_fn so they only appear when requirements are met
[IMPORTANT: The user has invoked the "kanban-orchestrator" skill, indicating they want you to follow its instructions. The full skill content is loaded below.]
---
name: kanban-orchestrator
description: Decomposition playbook + anti-temptation rules for an orchestrator profile routing work through Kanban. The "don't do the work yourself" rule and the basic lifecycle are auto-injected into every kanban worker's system prompt; this skill is the deeper playbook when you're specifically playing the orchestrator role.
version: 3.0.0
platforms: [linux, macos, windows]
metadata:
hermes:
tags: [kanban, multi-agent, orchestration, routing]
related_skills: [kanban-worker]
---
Kanban Orchestrator โ Decomposition Playbook
> The core worker lifecycle (including the kanban_create fan-out pattern and the "decompose, don't execute" rule) is auto-injected into every kanban process via the KANBAN_GUIDANCE system-prompt block. This skill is the deeper playbook when you're an orchestrator profile whose whole job is routing.
Profiles are user-configured โ not a fixed roster
Hermes setups vary widely. Some users run a single profile that does everything; some run a small fleet (docker-worker, cron-worker); some run a curated specialist team they've named themselves. There is no default specialist roster โ the orchestrator skill does not know what profiles exist on this machine.
Before fanning out, you must ground the decomposition in the profiles that actually exist. The dispatcher silently fails to spawn unknown assignee names โ it doesn't autocorrect, doesn't suggest, doesn't fall back. So a card assigned to researcher on a setup that only has docker-worker just sits in ready forever.
Step 0: discover available profiles before planning.
Use one of these:
hermes profile list โ prints the table of profiles configured on this machine. Run it through your terminal tool if you have one; otherwise ask the user.
kanban_list(assignee="<some-name>") โ sanity-check a single name. Returns an empty list (rather than an error) for an unknown assignee, so this only confirms a name you're already considering.
- Just ask the user. "What profiles do you have set up?" is a fine first turn when the goal needs more than one specialist.
Cache the result in your working memory for the rest of the conversation. Re-asking every turn wastes a tool call.
When to use the board (vs. just doing the work)
Create Kanban tasks when any of these are true:
1. Multiple specialists are needed. Research + analysis + writing is three profiles.
2. The work should survive a crash or restart. Long-running, recurring, or important.
3. The user might want to interject. Human-in-the-loop at any step.
4. Multiple subtasks can run in parallel. Fan-out for speed.
5. Review / iteration is expected. A reviewer profile loops on drafter output.
6. The audit trail matters. Board rows persist in SQLite forever.
If none of those apply โ it's a small one-shot reasoning task โ use delegate_task instead or answer the user directly.
The anti-temptation rules
Your job description says "route, don't execute." The rules that enforce that:
- Do not execute the work yourself. Your restricted toolset usually doesn't even include terminal/file/code/web for implementation. If you find yourself "just fixing this quickly" โ stop and create a task for the right specialist.
- For any concrete task, create a Kanban task and assign it. Every single time.
- Split multi-lane requests before creating cards. A user prompt can contain several independent workstreams. Extract those lanes first, then create one card per lane instead of bundling unrelated work into a single implementer card.
- Run independent lanes in parallel. If two cards do not need each other's output, leave them unlinked so the dispatcher can fan them out. Link only true data dependencies.
- If no specialist fits the available profiles, ask the user which profile to create or which existing profile to use. Do not invent profile names; the dispatcher will silently drop unknown assignees.
- Decompose, route, and summarize โ that's the whole job.
Exception: micro-UI polish cycles
There is one narrow exception where the orchestrator may execute directly instead of creating Kanban cards: tiny UI-only polish cycles (e.g., adding a CSS class, a theme preview dot, a hover state, a cross-link, or a HUD button) that are purely presentational, require no cross-file logic changes, and fit comfortably inside a single bounded cycle with no need for review or parallel work. If the change is limited to HTML/CSS/JS cosmetics, no other profile has a stake in it, and the user did not ask for a design review, the orchestrator should just edit and publish rather than paying the kanban-overhead tax. This exception does NOT apply to architecture changes, adapter logic, plugin interfaces, or anything that touches the data layer.
Decomposition playbook
Step 1 โ Understand the goal
Ask clarifying questions if the goal is ambiguous. Cheap to ask; expensive to spawn the wrong fleet.
Step 2 โ Sketch the task graph
Before creating anything, draft the graph out loud (in your response to the user). Treat every concrete workstream as a candidate card:
1. Extract the lanes from the request.
2. Map each lane to one of the profiles you discovered in Step 0. If a lane doesn't fit any existing profile, ask the user which to use or create.
3. Decide whether each lane is independent or gated by another lane.
4. Create independent lanes as parallel cards with no parent links.
5. Create synthesis/review/integration cards with parent links to the lanes they depend on.
Examples of prompts that should fan out (using placeholder profile names โ substitute whatever exists on the user's setup):
- "Build an app" โ one card to a design-oriented profile for product/UI direction, one or two cards to engineering profiles for implementation, plus a later integration/review card if the user has a reviewer profile.
- "Fix blockers and check model variants" โ one implementation card for the blocker fixes plus one discovery/research card for config/source verification. A final reviewer card can depend on both.
- "Research docs and implement" โ a docs-research card can run in parallel with a codebase-discovery card; implementation waits only if it truly needs those findings.
- "Analyze this screenshot and find the related code" โ one card to a vision-capable profile for the visual analysis while another searches the codebase.
Words like "also," "finally," or "and" do not automatically imply a dependency. They often mean "make sure this is covered before reporting back." Only link tasks when one card cannot start until another card's output exists.
Show the graph to the user before creating cards. Let them correct it โ including which actual profile name should own each lane.
Step 3 โ Create tasks and link
Use the profile names from Step 0. The example below uses placeholders <profile-A>, <profile-B>, <profile-C> โ replace them with what the user actually has.
t1 = kanban_create(
title="research: Postgres cost vs current",
assignee="<profile-A>", # whichever profile handles research on this setup
body="Compare estimated infrastructure costs, migration costs, and ongoing ops costs over a 3-year window. Sources: AWS/GCP pricing, team time estimates, current Postgres bills from peers.",
tenant=os.environ.get("HERMES_TENANT"),
)["task_id"]
t2 = kanban_create(
title="research: Postgres performance vs current",
assignee="<profile-A>", # same profile, run in parallel
body="Compare query latency, throughput, and scaling characteristics at our expected data volume (~500GB, 10k QPS peak). Sources: benchmark papers, public case studies, pgbench results if easy.",
)["task_id"]
t3 = kanban_create(
title="synthesize migration recommendation",
assignee="<profile-B>", # whichever profile does synthesis/analysis
body="Read the findings from T1 (cost) and T2 (performance). Produce a 1-page recommendation with explicit trade-offs and a go/no-go call.",
parents=[t1, t2],
)["task_id"]
t4 = kanban_create(
title="draft decision memo",
assignee="<profile-C>", # whichever profile drafts user-facing prose
body="Turn the analyst's recommendation into a 2-page memo for the CTO. Match the tone of previous decision memos in the team's knowledge base.",
parents=[t3],
)["task_id"]
parents=[...] gates promotion โ children stay in todo until every parent reaches done, then auto-promote to ready. No manual coordination needed; the dispatcher and dependency engine handle it.
Step 4 โ Complete your own task
If you were spawned as a task yourself (e.g. a planner profile was assigned T0: "investigate Postgres migration"), mark it done with a summary of what you created:
kanban_complete(
summary="decomposed into T1-T4: 2 research lanes in parallel, 1 synthesis on their outputs, 1 prose draft on the recommendation",
metadata={
"task_graph": {
"T1": {"assignee": "<profile-A>", "parents": []},
"T2": {"assignee": "<profile-A>", "parents": []},
"T3": {"assignee": "<profile-B>", "parents": ["T1", "T2"]},
"T4": {"assignee": "<profile-C>", "parents": ["T3"]},
},
},
)
Step 5 โ Report back to the user
Tell them what you created in plain prose, naming the actual profiles you used:
> I've queued 4 tasks:
> - T1 (<profile-A>): cost comparison
> - T2 (<profile-A>): performance comparison, in parallel with T1
> - T3 (<profile-B>): synthesizes T1 + T2 into a recommendation
> - T4 (<profile-C>): turns T3 into a CTO memo
>
> The dispatcher will pick up T1 and T2 now. T3 starts when both finish. You'll get a gateway ping when T4 completes. Use the dashboard or hermes kanban tail <id> to follow along.
Common patterns
Fan-out + fan-in (research โ synthesize): N research-style cards with no parents, one synthesis card with all of them as parents.
Parallel implementation + validation: one implementer card makes the change while one explorer/researcher card verifies config, docs, or source mapping. A reviewer card can depend on both. Do not make the implementer own unrelated verification just because the user mentioned both in one sentence.
Pipeline with gates: planner โ implementer โ reviewer. Each stage's parents=[previous_task]. Reviewer blocks or completes; if reviewer blocks, the operator unblocks with feedback and respawns.
Same-profile queue: N tasks, all assigned to the same profile, no dependencies between them. Dispatcher serializes โ that profile processes them in priority order, accumulating experience in its own memory.
Parallel UI/frontend lanes: When the goal touches multiple independent HTML/CSS/JS files (e.g., a dashboard page and a 2D gather view), fan out to separate subagents per file. Each lane edits its own file, then the orchestrator integrates, fixes cross-file references (theme paths, shared JSON endpoints), and publishes. This avoids merge conflicts in single-file HTML dashboards and keeps each subagent's context focused. See references/parallel-ui-lanes-and-publishing.md for the post-subagent integration checklist and rsync safety notes.
Human-in-the-loop: Any task can kanban_block() to wait for input. Dispatcher respawns after /unblock. The comment thread carries the full context.
Pitfalls
Inventing profile names that don't exist. The dispatcher silently fails to spawn unknown assignees โ the card just sits in ready forever. Always assign to a profile from your Step 0 discovery; ask the user if you're unsure.
Bundling independent lanes into one card. If the user asks for two independent outcomes, create two cards. Example: "fix blockers and check model variants" is not one fixer task; create a fixer/engineer card for the fixes and an explorer/researcher card for the variant check, then optionally gate review on both.
Over-linking because of wording. "Finally check X" may still be parallel with implementation if X is static config, docs, or source discovery. Link it after implementation only when the check depends on the implementation result.
Forgetting dependency links. If the task graph says research -> implement -> review, do not create all tasks as independent ready cards. Use parent links so implement/review cannot run before their inputs exist.
Reassignment vs. new task. If a reviewer blocks with "needs changes," create a NEW task linked from the reviewer's task โ don't re-run the same task with a stern look. The new task is assigned to the original implementer profile.
Argument order for links. kanban_link(parent_id=..., child_id=...) โ parent first. Mixing them up demotes the wrong task to todo.
Ignoring explicit user feedback to keep building infrastructure. When the user says a specific UX issue (legibility, theme switching, movement density) is "immediate priority," treat it as P0 and route it before deeper packaging/architecture work. Infrastructure polish feels productive, but shipping user-visible fixes is what matters. Create cards for the UX feedback first, then resume infrastructure lanes.
Treating status: complete as immutable when user feedback says otherwise. A state.md that says status: complete does not override a user's report that a completion criterion is actually broken. If the user says "theme switching is not working" and the Final Completion Condition requires "working UI theme switcher," the mission is not complete. Reactivate immediately: set status: active, append a reactivation cycle log, and fix the issue. Do not burn cycles on post-complete verification while the user is reporting active defects.
Don't pre-create the whole graph if the shape depends on intermediate findings. If T3's structure depends on what T1 and T2 find, let T3 exist as a "synthesize findings" task whose own first step is to read parent handoffs and plan the rest. Orchestrators can spawn orchestrators.
Tenant inheritance. If HERMES_TENANT is set in your env, pass tenant=os.environ.get("HERMES_TENANT") on every kanban_create call so child tasks stay in the same namespace.
Verifying cross-file references after directory reorganization. When subagents edit HTML/CSS/JS files and the directory structure shifts (e.g., moving files from root into web/dashboard/ and web/gather/), relative asset paths ( themes/default/theme.css, ./ops-data.json) often break. After subagents finish, the orchestrator must grep for href= and src= in moved files and fix relative paths before publishing. Subagents don't know the final publish layout โ the orchestrator does.
Destructive sync wipes needed files. Commands like rsync -av --delete will delete destination files that aren't in the source list. If you publish a directory tree piecemeal (e.g., copy web/dashboard/ first, then web/gather/ separately), --delete on the first rsync will erase the gather files before the second rsync runs. Either list all source paths in a single rsync invocation, or omit --delete and use cp -r / rsync -av without deletion when doing staged copies.
Recovering stuck workers
When a worker profile keeps crashing, hallucinating, or getting blocked by its own mistakes (usually: wrong model, missing skill, broken credential), the kanban dashboard flags the task with a โ badge and opens a Recovery section in the drawer. Three primary actions:
1. Reclaim (or hermes kanban reclaim <task_id>) โ abort the running worker immediately and reset the task to ready. The existing claim TTL is ~15 min; this is the fast path out.
2. Reassign (or hermes kanban reassign <task_id> <new-profile> --reclaim) โ switch the task to a different profile (one that exists on this setup) and let the dispatcher pick it up with a fresh worker.
3. Change profile model โ the dashboard prints a copy-paste hint for hermes -p <profile> model since profile config lives on disk; edit it in a terminal, then Reclaim to retry with the new model.
Hallucination warnings appear on tasks where a worker's kanban_complete(created_cards=[...]) claim included card ids that don't exist or weren't created by the worker's profile (the gate blocks the completion), or where the free-form summary references t_<hex> ids that don't resolve (advisory prose scan, non-blocking). Both produce audit events that persist even after recovery actions โ the trail stays for debugging.
The user has provided the following instruction alongside the skill invocation: [IMPORTANT: You are running as a scheduled cron job. DELIVERY: Your final response will be automatically delivered to the user โ do NOT use send_message or try to deliver the output yourself. Just produce your report/output as your final response and the system handles the rest. SILENT: If there is genuinely nothing new to report, respond with exactly "[SILENT]" (nothing else) to suppress delivery. Never combine [SILENT] with content โ either report your findings normally, or say [SILENT] and nothing more.]
You are the 15-minute Orchestrator for Son's Autonomous Agent Lab v1, reporting to Discord channel ID 1505805763824586952.
Durable state path: /Users/jooho-hermes/.hermes/autonomous-agent-lab/state.md
Working directory for experiment artifacts: /Users/jooho-hermes/.hermes/autonomous-agent-lab/
Preferred published web root: /Users/jooho-hermes/hermes-web/agent-pets/
Top-level directive from Son:
- The project has evolved from a personal dashboard into an INSTALLABLE PRODUCT that external Hermes users can deploy.
- The final target is a self-contained, configurable, publishable solution: "Hermes Pixel Pet Ops Office".
- Do NOT shrink the mission into a small static MVP and autonomously stop.
- The Gather.town-style 2D spatial office is a first-class feature, not a side page.
Latest UX feedback from Son (treat as immediate priority before deeper packaging work):
- Details are hard for a human to understand. Add human-first summaries, plain-language labels, and progressive disclosure: summary first, technical details second.
- Gather Town version has too many agents roaming around. Reduce default movement, add density/speed controls, cluster agents by room/task, and add focus/calm mode.
- Theme switching is not visibly working. Implement real UI theme switcher with persistence and clear visual theme changes.
Key product requirements (installable solution level):
1. Config-driven architecture: all paths, URLs, colors, names, room layouts via config.yaml. No hardcoded references to jooho-hermes.
2. Self-contained package: clear directory structure (src/, web/, config/, docs/, scripts/), install script, requirements.txt.
3. Pluggable data adapter: support multiple backends via plugin architecture.
4. Themeable frontend: CSS variables driven from config, swappable themes, plus a working UI theme switcher.
5. Multi-tenant ready: works for any Hermes instance.
6. Build/Deploy ready: Dockerfile or docker-compose, or clear static-server setup.
7. Documentation: README, architecture docs, configuration reference, contributor guide.
8. Human-comprehensible UX: plain-language summaries and progressive disclosure for technical detail.
9. Gather.town calm mode: adjustable movement density/speed and less chaotic defaults.
10. Versioned releases: CHANGELOG.md, semantic versioning, release packaging.
Mission model:
- Read state.md first before doing anything else.
- If state.md says
status: inactive or has no Current Mission, do not invent work. Return exactly: ๐ก Autonomous Agent Lab ๋๊ธฐ์ค โ Son์ด ํธ๋ฆฌ๊ฑฐ/๋ฏธ์
์ ์ฃผ๋ฉด 15๋ถ ์ฌ์ดํด์ ์์ํฉ๋๋ค.
- If state.md says
status: active, run one bounded 15-minute cycle toward the full installable solution.
- If state.md says
status: complete, verify that the Final Completion Condition in state.md is truly met. If it is not fully met, reactivate or report that state needs correction.
Cycle procedure when active:
1. Read state.md first. Extract current mission, constraints, previous cycle log, and Final Completion Condition.
2. Decide the next smallest useful step toward installable solution quality. Focus on: architecture, configurability, documentation, and clean separation of concerns.
3. Use delegate_task for independent subagent lanes when helpful.
4. Prefer concrete progress: refactor to config-driven, add install scripts, create docs, add Docker support, theme system, plugin architecture.
5. Update state.md with a new cycle log entry before final reporting.
6. Completion rule: only set status: complete when every item under state.md Final Completion Condition is satisfied. A non-installable MVP is not complete.
7. Stop/block only if Son explicitly stops/redirects, a safety boundary is reached, or a hard blocker needs Son's decision.
Link requirement (never forget):
- Every cycle report MUST include at least one direct viewable link to the published dashboard/artifact.
- The canonical URL:
http://hermes-mac-mini.tail46b3c6.ts.net:8099/agent-pets/
- Include gather town URL too:
http://hermes-mac-mini.tail46b3c6.ts.net:8099/agent-pets/gather/
Final Discord message format:
[Autonomous Agent Lab v1 / Cycle N]
๋ชฉํ:
์ํ:
๊ฒฐ๊ณผ:
๊ฒ์ฆ:
๋ค์:
์ํ:
Safety/quality rules:
- Do not handle secrets, passwords, API keys, payment, permission dialogs, or destructive commands.
- Do not claim completion without updating state.md.
- Do not rely on Discord history as durable state.
- Do not spam raw logs; summarize lane outputs and verification.
- Keep working in /Users/jooho-hermes/.hermes/autonomous-agent-lab/ and publish only to /Users/jooho-hermes/hermes-web/agent-pets/ unless the state file says otherwise.
Design/UX priorities:
- Mobile responsiveness is first-class.
- Character animation/movement is desired.
- Every cycle report must include published links.
- This is now a product engineering mission. Architecture, configurability, and documentation matter as much as visuals.
Response
[Autonomous Agent Lab v1 / Cycle 73]
๋ชฉํ:
15๋ถ ์ฃผ๊ธฐ ๊ฑด๊ฐ ๊ฒ์ฆ ๋ฐ ๋ฐ์ดํฐ ๋ณด์กด ํ์ดํ๋ผ์ธ ํ์ธ. ์์คโ๋ฐฐํฌ ํ์ผ 100% ๋๊ธฐํ ์ฌ๋ถ ์ ๊ฒ.
์ํ:
1. src.adapter.generate_ops_data ์คํ โ 32 agents, 15 cron jobs, 20 sessions, 16 events, schema 1.4.
2. ์๋ prune ํ์ธ โ 32๊ฐ ์ค๋๋ ์ํ ๋ณ๊ฒฝ ๊ธฐ๋ก ์ญ์ , DB ํฌ๊ธฐ 1.0MB ์ ์ง.
3. scripts/test.sh โ 128/128 passed.
4. scripts/validate_setup.sh โ 21/21 passed.
5. ์์ค์ ๋ฐฐํฌ ํ์ผ diff -q โ dashboard HTML, gather HTML, CSS, JS, sw.js ์ ๋ถ ์ผ์น.
6. ops-data.json / health.json mtime < 60s, refresh.err.log ๋น์ด์์.
7. LaunchAgent last exit code = 0, ์ฐ์ ์ฑ๊ณต ๊ฐฑ์ ํ์ธ.
๊ฒฐ๊ณผ:
- ์์คํ
์ ๋ฐ ๊ฑด๊ฐ. ๋ฐ์ดํฐ ๋ณด์กด ์ ์ ์๋.
- ๋ฒ์ ์ผ์น:
v1.4.4 ยท b68, data-build="68", ?v=68, CACHE_NAME = pixel-pet-ops-v22.
- ํ๋์ฝ๋ฉ ์ฐธ์กฐ 0๊ฑด.
๊ฒ์ฆ:
- 11๊ฐ Final Completion Condition ๋ชจ๋ ์ถฉ์กฑ.
- Son UX ํผ๋๋ฐฑ 3๊ฑด ๊ธฐ์ ์ ์ผ๋ก ๋ชจ๋ ํด๊ฒฐ๋จ:
1. ํ
๋ง ์ ํ ๊ฐ์์ฑ โ
2. Gather calm mode โ
(๊ธฐ๋ณธ 5 agents, calm ๊ธฐ๋ณธ ํ์ฑ)
3. Human-first ์์ฝ โ
๋ค์:
- Son์ด ๋ธ๋ผ์ฐ์ ์์ ์ธ ๊ฐ์ง UX ํญ๋ชฉ์ ํ์ธ ํ ๋ง์กฑํ๋ฉด
status: complete๋ก ์ ํ.
- ์ถ๊ฐ ๊ฐ๋ฐ ํฌ๋ง ์ ํธ์ ๊ธฐ๋ฅ ๋ ์ธ ์ค๋น๋จ: ์ฆ๊ฒจ์ฐพ๊ธฐ ์์ด์ ํธ, ๋น ๋ฅธ ๋ฌธ์ ํ์, ๋ชจ๋ฐ์ผ ํํฐ, ๊ณต์ ๊ฐ๋ฅํ ๋ทฐ.
์ํ:
active โ Son์ ๋ธ๋ผ์ฐ์ ์ฌ์ด๋ ํ์ธ ๋๊ธฐ ์ค.
๐ ๋์๋ณด๋: http://hermes-mac-mini.tail46b3c6.ts.net:8099/agent-pets/
๐ข Gather Town: http://hermes-mac-mini.tail46b3c6.ts.net:8099/agent-pets/gather/
|
| 2026-05-20 00-27-25 |
83,281 chars |
2026-05-20_00-27-25.md |
Cron Job: autonomous-agent-lab-v1-orchestrator
Job ID: 35127ff89556
Run Time: 2026-05-20 00:27:25
Schedule: every 15m
Prompt
[IMPORTANT: The user has invoked the "hermes-agent" skill, indicating they want you to follow its instructions. The full skill content is loaded below.]
---
name: hermes-agent
description: "Configure, extend, or contribute to Hermes Agent."
version: 2.1.0
author: Hermes Agent + Teknium
license: MIT
platforms: [linux, macos, windows]
metadata:
hermes:
tags: [hermes, setup, configuration, multi-agent, spawning, cli, gateway, development]
homepage: https://github.com/NousResearch/hermes-agent
related_skills: [claude-code, codex, opencode]
---
Hermes Agent
Hermes Agent is an open-source AI agent framework by Nous Research that runs in your terminal, messaging platforms, and IDEs. It belongs to the same category as Claude Code (Anthropic), Codex (OpenAI), and OpenClaw โ autonomous coding and task-execution agents that use tool calling to interact with your system. Hermes works with any LLM provider (OpenRouter, Anthropic, OpenAI, DeepSeek, local models, and 15+ others) and runs on Linux, macOS, and WSL.
What makes Hermes different:
- Self-improving through skills โ Hermes learns from experience by saving reusable procedures as skills. When it solves a complex problem, discovers a workflow, or gets corrected, it can persist that knowledge as a skill document that loads into future sessions. Skills accumulate over time, making the agent better at your specific tasks and environment.
- Persistent memory across sessions โ remembers who you are, your preferences, environment details, and lessons learned. Pluggable memory backends (built-in, Honcho, Mem0, and more) let you choose how memory works.
- Multi-platform gateway โ the same agent runs on Telegram, Discord, Slack, WhatsApp, Signal, Matrix, Email, and 10+ other platforms with full tool access, not just chat.
- Provider-agnostic โ swap models and providers mid-workflow without changing anything else. Credential pools rotate across multiple API keys automatically.
- Profiles โ run multiple independent Hermes instances with isolated configs, sessions, skills, and memory.
- Extensible โ plugins, MCP servers, custom tools, webhook triggers, cron scheduling, and the full Python ecosystem.
People use Hermes for software development, research, system administration, data analysis, content creation, home automation, and anything else that benefits from an AI agent with persistent context and full system access.
This skill helps you work with Hermes Agent effectively โ setting it up, configuring features, spawning additional agent instances, troubleshooting issues, finding the right commands and settings, and understanding how the system works when you need to extend or contribute to it.
Docs: https://hermes-agent.nousresearch.com/docs/
Quick Start
Install
curl -fsSL https://raw.githubusercontent.com/NousResearch/hermes-agent/main/scripts/install.sh | bash
Interactive chat (default)
hermes
Single query
hermes chat -q "What is the capital of France?"
Setup wizard
hermes setup
Change model/provider
hermes model
Check health
hermes doctor
---
CLI Reference
Global Flags
hermes [flags] [command]
--version, -V Show version
--resume, -r SESSION Resume session by ID or title
--continue, -c [NAME] Resume by name, or most recent session
--worktree, -w Isolated git worktree mode (parallel agents)
--skills, -s SKILL Preload skills (comma-separate or repeat)
--profile, -p NAME Use a named profile
--yolo Skip dangerous command approval
--pass-session-id Include session ID in system prompt
No subcommand defaults to chat.
Chat
hermes chat [flags]
-q, --query TEXT Single query, non-interactive
-m, --model MODEL Model (e.g. anthropic/claude-sonnet-4)
-t, --toolsets LIST Comma-separated toolsets
--provider PROVIDER Force provider (openrouter, anthropic, nous, etc.)
-v, --verbose Verbose output
-Q, --quiet Suppress banner, spinner, tool previews
--checkpoints Enable filesystem checkpoints (/rollback)
--source TAG Session source tag (default: cli)
Configuration
hermes setup [section] Interactive wizard (model|terminal|gateway|tools|agent)
hermes model Interactive model/provider picker
hermes config View current config
hermes config edit Open config.yaml in $EDITOR
hermes config set KEY VAL Set a config value
hermes config path Print config.yaml path
hermes config env-path Print .env path
hermes config check Check for missing/outdated config
hermes config migrate Update config with new options
hermes doctor [--fix] Check dependencies and config
Credential Pools
hermes auth add Interactive credential wizard (oauth, api-key)
hermes auth list [PROVIDER] List pooled credentials
hermes auth remove P INDEX Remove by provider + index
hermes auth reset PROVIDER Clear exhaustion status
hermes logout Clear stored auth
Tools & Skills
hermes tools Interactive tool enable/disable (curses UI)
hermes tools list Show all tools and status
hermes tools enable NAME Enable a toolset
hermes tools disable NAME Disable a toolset
hermes skills list List installed skills
hermes skills search QUERY Search the skills hub
hermes skills install ID Install a skill (ID can be a hub identifier OR a direct https://โฆ/SKILL.md URL; pass --name to override when frontmatter has no name)
hermes skills inspect ID Preview without installing
hermes skills config Enable/disable skills per platform
hermes skills check Check for updates
hermes skills update Update outdated skills
hermes skills uninstall N Remove a hub skill
hermes skills publish PATH Publish to registry
hermes skills browse Browse all available skills
hermes skills tap add REPO Add a GitHub repo as skill source
MCP Servers
hermes mcp serve Run Hermes as an MCP server
hermes mcp add NAME Add an MCP server (--url or --command)
hermes mcp remove NAME Remove an MCP server
hermes mcp list List configured servers
hermes mcp test NAME Test connection
hermes mcp configure NAME Toggle tool selection
Gateway (Messaging Platforms)
hermes gateway run Start gateway foreground
hermes gateway install Install as background service
hermes gateway start/stop Control the service
hermes gateway restart Restart the service
hermes gateway status Check status
hermes gateway setup Configure platforms
Supported platforms: Telegram, Discord, Slack, WhatsApp, Signal, Email, SMS, Matrix, Mattermost, Home Assistant, DingTalk, Feishu, WeCom, BlueBubbles (iMessage), Weixin (WeChat), API Server, Webhooks. Open WebUI connects via the API Server adapter.
Platform docs: https://hermes-agent.nousresearch.com/docs/user-guide/messaging/
Discord-specific walkthrough (token, intents, service install, access control): see references/discord-gateway-setup.md in this skill.
- Per-channel personas and skill bindings: see
references/gateway-channel-personas.md (works on Discord, Slack, Telegram, Mattermost, Matrix).
- For long-running Discord-first operations, purpose-specific channel routing, periodic summaries, weekly Dreaming/audit reports, and log-safety patterns: see
references/discord-operating-planes.md.
- For broad Hermes/LifeOS/SQAF ecosystem audits (cron inventory, live services, dashboards, provider/model warnings, and control-plane gaps), see
references/ecosystem-audit.md.
Sessions
hermes sessions list List recent sessions
hermes sessions browse Interactive picker
hermes sessions export OUT Export to JSONL
hermes sessions rename ID T Rename a session
hermes sessions delete ID Delete a session
hermes sessions prune Clean up old sessions (--older-than N days)
hermes sessions stats Session store statistics
For browser-based viewing of existing Hermes CLI/Discord/cron session transcripts, prefer a lightweight static export from ~/.hermes/state.db into a private web root instead of assuming Open WebUI can browse Hermes' native session store. See references/hermes-session-static-web-viewer.md for the SQLite schema, static HTML export workflow, redaction/truncation cautions, and the user's Mac mini deployment (/hermes-sessions/ under the Tailscale-only ~/hermes-web site).
For cron job execution history, the same static-export pattern applies to ~/.hermes/cron/jobs.json and ~/.hermes/cron/output/{job_id}/*.md. See references/cron-history-web-viewer.md for the cron data model, schedule-dict pitfall, and the user's deployed /cron-history/ dashboard.
Cron Jobs
hermes cron list List jobs (--all for disabled)
hermes cron create SCHED Create: '30m', 'every 2h', '0 9 *'
hermes cron edit ID Edit schedule, prompt, delivery
hermes cron pause/resume ID Control job state
hermes cron run ID Trigger on next tick
hermes cron remove ID Delete a job
hermes cron status Scheduler status
For bounded autonomous lab/orchestrator cron jobs that use file-based state, subagent lanes, artifact publishing, and status transitions (active โ complete/blocked/inactive), see references/autonomous-agent-lab-cron-cycle.md. A reusable verification script template lives at scripts/verify-completion-template.py.
For a worked example of evolving an autonomous lab into a config-driven, themeable, Docker-ready installable product, see references/autonomous-lab-product-architecture.md. For CI, integration testing, pluggable adapter architecture, bounded cycle orchestration, and post-productization patterns, see references/product-maturity-patterns.md.
For the final completion verification checklist โ the explicit audit pattern to run before marking status: complete on an installable-solution mission, see references/autonomous-lab-completion-verification.md.
For the reactivation protocol when a completed lab receives new P0 feedback or the user contradicts a completion claim, see references/autonomous-lab-reactivation-protocol.md.
For the config/CHANGELOG version drift pitfall that occurs when autonomous labs evolve over many cycles, and for the related source vs. published file drift problem where the live web root diverges from the project source, see references/autonomous-lab-version-drift.md.
For adding historical trend tracking (SQLite-backed agent status transitions + vanilla JS SVG sparklines) to an autonomous lab dashboard, see references/history-tracking-sparkline-pattern.md.
For reusable dashboard UX patterns (onboarding tours, data freshness badges, keyboard shortcuts, progressive disclosure inspectors, cross-linking between views), see references/dashboard-ux-patterns.md.
For the aggressive human-first inspector refinement โ when users report that details are hard to understand and the fix is to strip technical labels from the default view โ see references/progressive-disclosure-human-first.md.
For programmatic verification of CSS custom-property theme systems โ catching scoping bugs, confirming theme distinctness, and validating JS switching logic โ see references/theme-system-verification.md.
- For Son's Discord-first autonomous experiments where a channel hosts a repeated multi-agent loop, use the Autonomous Discord Agent Lab pattern: create file-based durable state, a paused cron orchestrator delivered to
discord:<channel_id>, then activate it from a user mission trigger. See references/autonomous-discord-agent-lab.md.
- For verifying that a release package (
tar.gz) is actually installable by third parties and contains no stale artifacts or hardcoded references, see references/release-package-verification.md and the reusable script at scripts/release-verify.sh.
Webhooks
hermes webhook subscribe N Create route at /webhooks/<name>
hermes webhook list List subscriptions
hermes webhook remove NAME Remove a subscription
hermes webhook test NAME Send a test POST
Profiles
hermes profile list List all profiles
hermes profile create NAME Create (--clone, --clone-all, --clone-from)
hermes profile use NAME Set sticky default
hermes profile delete NAME Delete a profile
hermes profile show NAME Show details
hermes profile alias NAME Manage wrapper scripts
hermes profile rename A B Rename a profile
hermes profile export NAME Export to tar.gz
hermes profile import FILE Import from archive
Credential Pools
hermes auth add Interactive credential wizard
hermes auth list [PROVIDER] List pooled credentials
hermes auth remove P INDEX Remove by provider + index
hermes auth reset PROVIDER Clear exhaustion status
Other
hermes insights [--days N] Usage analytics
hermes update Update to latest version
hermes pairing list/approve/revoke DM authorization
hermes plugins list/install/remove Plugin management
hermes honcho setup/status Honcho memory integration (requires honcho plugin)
hermes memory setup/status/off Memory provider config
hermes completion bash|zsh Shell completions
hermes acp ACP server (IDE integration)
hermes claw migrate Migrate from OpenClaw
hermes uninstall Uninstall Hermes
---
Slash Commands (In-Session)
Type these during an interactive chat session. New commands land fairly
often; if something below looks stale, run /help in-session for the
authoritative list or see the [live slash commands reference](https://hermes-agent.nousresearch.com/docs/reference/slash-commands).
The registry of record is hermes_cli/commands.py โ every consumer
(autocomplete, Telegram menu, Slack mapping, /help) derives from it.
Session Control
/new (/reset) Fresh session
/clear Clear screen + new session (CLI)
/retry Resend last message
/undo Remove last exchange
/title [name] Name the session
/compress Manually compress context
/stop Kill background processes
/rollback [N] Restore filesystem checkpoint
/snapshot [sub] Create or restore state snapshots of Hermes config/state (CLI)
/background <prompt> Run prompt in background
/queue <prompt> Queue for next turn
/steer <prompt> Inject a message after the next tool call without interrupting
/agents (/tasks) Show active agents and running tasks
/resume [name] Resume a named session
/goal [text|sub] Set a standing goal Hermes works on across turns until achieved
(subcommands: status, pause, resume, clear)
/redraw Force a full UI repaint (CLI)
Configuration
/config Show config (CLI)
/model [name] Show or change model
/personality [name] Set personality
/reasoning [level] Set reasoning (none|minimal|low|medium|high|xhigh|show|hide)
/verbose Cycle: off โ new โ all โ verbose
/voice [on|off|tts] Voice mode
/yolo Toggle approval bypass
/busy [sub] Control what Enter does while Hermes is working (CLI)
(subcommands: queue, steer, interrupt, status)
/indicator [style] Pick the TUI busy-indicator style (CLI)
(styles: kaomoji, emoji, unicode, ascii)
/footer [on|off] Toggle gateway runtime-metadata footer on final replies
/skin [name] Change theme (CLI)
/statusbar Toggle status bar (CLI)
Tools & Skills
/tools Manage tools (CLI)
/toolsets List toolsets (CLI)
/skills Search/install skills (CLI)
/skill <name> Load a skill into session
/reload-skills Re-scan ~/.hermes/skills/ for added/removed skills
/reload Reload .env variables into the running session (CLI)
/reload-mcp Reload MCP servers
/cron Manage cron jobs (CLI)
/curator [sub] Background skill maintenance (status, run, pin, archive, โฆ)
/kanban [sub] Multi-profile collaboration board (tasks, links, comments)
/plugins List plugins (CLI)
Gateway
/approve Approve a pending command (gateway)
/deny Deny a pending command (gateway)
/restart Restart gateway (gateway)
/sethome Set current chat as home channel (gateway)
/update Update Hermes to latest (gateway)
/topic [sub] Enable or inspect Telegram DM topic sessions (gateway)
/platforms (/gateway) Show platform connection status (gateway)
Utility
/branch (/fork) Branch the current session
/fast Toggle priority/fast processing
/browser Open CDP browser connection
/history Show conversation history (CLI)
/save Save conversation to file (CLI)
/copy [N] Copy the last assistant response to clipboard (CLI)
/paste Attach clipboard image (CLI)
/image Attach local image file (CLI)
Info
/help Show commands
/commands [page] Browse all commands (gateway)
/usage Token usage
/insights [days] Usage analytics
/gquota Show Google Gemini Code Assist quota usage (CLI)
/status Session info (gateway)
/profile Active profile info
/debug Upload debug report (system info + logs) and get shareable links
Exit
/quit (/exit, /q) Exit CLI
---
Key Paths & Config
~/.hermes/config.yaml Main configuration
~/.hermes/.env API keys and secrets
$HERMES_HOME/skills/ Installed skills
~/.hermes/sessions/ Session transcripts
~/.hermes/logs/ Gateway and error logs
~/.hermes/auth.json OAuth tokens and credential pools
~/.hermes/hermes-agent/ Source code (if git-installed)
Profiles use ~/.hermes/profiles/<name>/ with the same layout.
Config Sections
Edit with hermes config edit or hermes config set section.key value.
| Section | Key options |
|---------|-------------|
| model | default, provider, base_url, api_key, context_length |
| agent | max_turns (90), tool_use_enforcement |
| terminal | backend (local/docker/ssh/modal), cwd, timeout (180) |
| compression | enabled, threshold (0.50), target_ratio (0.20) |
| display | skin, tool_progress, show_reasoning, show_cost |
| stt | enabled, provider (local/groq/openai/mistral) |
| tts | provider (edge/elevenlabs/openai/minimax/mistral/neutts) |
| memory | memory_enabled, user_profile_enabled, provider |
| security | tirith_enabled, website_blocklist |
| delegation | model, provider, base_url, api_key, max_iterations (50), reasoning_effort |
| checkpoints | enabled, max_snapshots (50) |
| fallback_model | provider, model, base_url, key_env |
Fallback Providers
Hermes can automatically fail over to a backup provider:model when the primary is unavailable. This is turn-scoped โ each new user message starts with the primary restored; fallback only activates mid-turn when the primary fails.
Configuration ( ~/.hermes/config.yaml):
fallback_model:
provider: opencode-go
model: kimi-k2.6
Or use the interactive manager:
hermes fallback add # interactive picker
hermes fallback list # show fallback chain
hermes fallback remove # remove by index
Legacy note: fallback_model (singular) is the legacy single-fallback key. fallback_providers (list) supports multiple ordered fallbacks. When both exist, fallback_providers takes priority.
Trigger conditions (after exhausting retries where applicable):
- Rate limits (HTTP 429)
- Server errors (HTTP 500, 502, 503)
- Auth failures (HTTP 401, 403) โ immediately
- Not found (HTTP 404) โ immediately
- Invalid / empty responses repeatedly
Supported providers include all standard providers (OpenRouter, Anthropic, OpenCode Go/ Zen, Kimi, etc.) plus custom endpoints with base_url + key_env. Full provider docs: https://hermes-agent.nousresearch.com/docs/integrations/providers
Limitations:
- Subagent delegation does not inherit fallback config
- Cron jobs do not use fallback (use per-job provider/model overrides)
- Auxiliary tasks (vision, compression, etc.) use their own
auxiliary.* provider chain
For a deep-dive with worked examples and model lists, see references/fallback-providers.md.
Full config reference: https://hermes-agent.nousresearch.com/docs/user-guide/configuration
Providers
20+ providers supported. Set via hermes model or hermes setup.
| Provider | Auth | Key env var |
|----------|------|-------------|
| OpenRouter | API key | OPENROUTER_API_KEY |
| Anthropic | API key | ANTHROPIC_API_KEY |
| Nous Portal | OAuth | hermes auth |
| OpenAI Codex | OAuth | hermes auth |
| GitHub Copilot | Token | COPILOT_GITHUB_TOKEN |
| Google Gemini | API key | GOOGLE_API_KEY or GEMINI_API_KEY |
| DeepSeek | API key | DEEPSEEK_API_KEY |
| xAI / Grok | API key | XAI_API_KEY |
| Hugging Face | Token | HF_TOKEN |
| Z.AI / GLM | API key | GLM_API_KEY |
| MiniMax | API key | MINIMAX_API_KEY |
| MiniMax CN | API key | MINIMAX_CN_API_KEY |
| Kimi / Moonshot | API key | KIMI_API_KEY |
| Alibaba / DashScope | API key | DASHSCOPE_API_KEY |
| Xiaomi MiMo | API key | XIAOMI_API_KEY |
| Kilo Code | API key | KILOCODE_API_KEY |
| AI Gateway (Vercel) | API key | AI_GATEWAY_API_KEY |
| OpenCode Zen | API key | OPENCODE_ZEN_API_KEY |
| OpenCode Go | API key | OPENCODE_GO_API_KEY |
| Qwen OAuth | OAuth | hermes auth add qwen-oauth |
| Custom endpoint | Config | model.base_url + model.api_key in config.yaml |
| GitHub Copilot ACP | External | COPILOT_CLI_PATH or Copilot CLI |
Full provider docs: https://hermes-agent.nousresearch.com/docs/integrations/providers
Toolsets
Enable/disable via hermes tools (interactive) or hermes tools enable/disable NAME.
| Toolset | What it provides |
|---------|-----------------|
| web | Web search and content extraction |
| search | Web search only (subset of web) |
| browser | Browser automation (Browserbase, Camofox, or local Chromium) |
| terminal | Shell commands and process management |
| file | File read/write/search/patch |
| code_execution | Sandboxed Python execution |
| vision | Image analysis |
| image_gen | AI image generation |
| video | Video analysis and generation |
| tts | Text-to-speech |
| skills | Skill browsing and management |
| memory | Persistent cross-session memory |
| session_search | Search past conversations |
| delegation | Subagent task delegation |
| cronjob | Scheduled task management |
| clarify | Ask user clarifying questions |
| messaging | Cross-platform message sending |
| todo | In-session task planning and tracking |
| kanban | Multi-agent work-queue tools (gated to workers) |
| debugging | Extra introspection/debug tools (off by default) |
| safe | Minimal, low-risk toolset for locked-down sessions |
| spotify | Spotify playback and playlist control |
| homeassistant | Smart home control (off by default) |
| discord | Discord integration tools |
| discord_admin | Discord admin/moderation tools |
| feishu_doc | Feishu (Lark) document tools |
| feishu_drive | Feishu (Lark) drive tools |
| yuanbao | Yuanbao integration tools |
| rl | Reinforcement learning tools (off by default) |
| moa | Mixture of Agents (off by default) |
Full enumeration lives in toolsets.py as the TOOLSETS dict; _HERMES_CORE_TOOLS is the default bundle most platforms inherit from.
Tool changes take effect on /reset (new session). They do NOT apply mid-conversation to preserve prompt caching.
---
Security & Privacy Toggles
Common "why is Hermes doing X to my output / tool calls / commands?" toggles โ and the exact commands to change them. Most of these need a fresh session (/reset in chat, or start a new hermes invocation) because they're read once at startup.
Secret redaction in tool output
Secret redaction is off by default โ tool output (terminal stdout, read_file, web content, subagent summaries, etc.) passes through unmodified. If the user wants Hermes to auto-mask strings that look like API keys, tokens, and secrets before they enter the conversation context and logs:
hermes config set security.redact_secrets true # enable globally
Restart required. security.redact_secrets is snapshotted at import time โ toggling it mid-session (e.g. via export HERMES_REDACT_SECRETS=true from a tool call) will NOT take effect for the running process. Tell the user to run hermes config set security.redact_secrets true in a terminal, then start a new session. This is deliberate โ it prevents an LLM from flipping the toggle on itself mid-task.
Disable again with:
hermes config set security.redact_secrets false
PII redaction in gateway messages
Separate from secret redaction. When enabled, the gateway hashes user IDs and strips phone numbers from the session context before it reaches the model:
hermes config set privacy.redact_pii true # enable
hermes config set privacy.redact_pii false # disable (default)
Command approval prompts
By default (approvals.mode: manual), Hermes prompts the user before running shell commands flagged as destructive (rm -rf, git reset --hard, etc.). The modes are:
manual โ always prompt (default)
smart โ use an auxiliary LLM to auto-approve low-risk commands, prompt on high-risk
off โ skip all approval prompts (equivalent to --yolo)
hermes config set approvals.mode smart # recommended middle ground
hermes config set approvals.mode off # bypass everything (not recommended)
Per-invocation bypass without changing config:
hermes --yolo โฆ
export HERMES_YOLO_MODE=1
Note: YOLO / approvals.mode: off does NOT turn off secret redaction. They are independent.
Shell hooks allowlist
Some shell-hook integrations require explicit allowlisting before they fire. Managed via ~/.hermes/shell-hooks-allowlist.json โ prompted interactively the first time a hook wants to run.
Disabling the web/browser/image-gen tools
To keep the model away from network or media tools entirely, open hermes tools and toggle per-platform. Takes effect on next session (/reset). See the Tools & Skills section above.
---
Voice & Transcription
STT (Voice โ Text)
Voice messages from messaging platforms are auto-transcribed.
Provider priority (auto-detected):
1. Local faster-whisper โ free, no API key: pip install faster-whisper
2. Groq Whisper โ free tier: set GROQ_API_KEY
3. OpenAI Whisper โ paid: set VOICE_TOOLS_OPENAI_KEY
4. Mistral Voxtral โ set MISTRAL_API_KEY
Config:
stt:
enabled: true
provider: local # local, groq, openai, mistral
local:
model: base # tiny, base, small, medium, large-v3
TTS (Text โ Voice)
| Provider | Env var | Free? |
|----------|---------|-------|
| Edge TTS | None | Yes (default) |
| ElevenLabs | ELEVENLABS_API_KEY | Free tier |
| OpenAI | VOICE_TOOLS_OPENAI_KEY | Paid |
| MiniMax | MINIMAX_API_KEY | Paid |
| Mistral (Voxtral) | MISTRAL_API_KEY | Paid |
| NeuTTS (local) | None (pip install neutts[all] + espeak-ng) | Free |
Voice commands: /voice on (voice-to-voice), /voice tts (always voice), /voice off.
---
Spawning Additional Hermes Instances
Run additional Hermes processes as fully independent subprocesses โ separate sessions, tools, and environments.
When to Use This vs delegate_task
| | delegate_task | Spawning hermes process |
|-|-----------------|--------------------------|
| Isolation | Separate conversation, shared process | Fully independent process |
| Duration | Minutes (bounded by parent loop) | Hours/days |
| Tool access | Subset of parent's tools | Full tool access |
| Interactive | No | Yes (PTY mode) |
| Use case | Quick parallel subtasks | Long autonomous missions |
One-Shot Mode
terminal(command="hermes chat -q 'Research GRPO papers and write summary to ~/research/grpo.md'", timeout=300)
Background for long tasks:
terminal(command="hermes chat -q 'Set up CI/CD for ~/myapp'", background=true)
Interactive PTY Mode (via tmux)
Hermes uses prompt_toolkit, which requires a real terminal. Use tmux for interactive spawning:
Start
terminal(command="tmux new-session -d -s agent1 -x 120 -y 40 'hermes'", timeout=10)
Wait for startup, then send a message
terminal(command="sleep 8 && tmux send-keys -t agent1 'Build a FastAPI auth service' Enter", timeout=15)
Read output
terminal(command="sleep 20 && tmux capture-pane -t agent1 -p", timeout=5)
Send follow-up
terminal(command="tmux send-keys -t agent1 'Add rate limiting middleware' Enter", timeout=5)
Exit
terminal(command="tmux send-keys -t agent1 '/exit' Enter && sleep 2 && tmux kill-session -t agent1", timeout=10)
Multi-Agent Coordination
Agent A: backend
terminal(command="tmux new-session -d -s backend -x 120 -y 40 'hermes -w'", timeout=10)
terminal(command="sleep 8 && tmux send-keys -t backend 'Build REST API for user management' Enter", timeout=15)
Agent B: frontend
terminal(command="tmux new-session -d -s frontend -x 120 -y 40 'hermes -w'", timeout=10)
terminal(command="sleep 8 && tmux send-keys -t frontend 'Build React dashboard for user management' Enter", timeout=15)
Check progress, relay context between them
terminal(command="tmux capture-pane -t backend -p | tail -30", timeout=5)
terminal(command="tmux send-keys -t frontend 'Here is the API schema from the backend agent: ...' Enter", timeout=5)
Session Resume
Resume most recent session
terminal(command="tmux new-session -d -s resumed 'hermes --continue'", timeout=10)
Resume specific session
terminal(command="tmux new-session -d -s resumed 'hermes --resume 20260225_143052_a1b2c3'", timeout=10)
Tips
- Prefer
delegate_task for quick subtasks โ less overhead than spawning a full process
- Use
-w (worktree mode) when spawning agents that edit code โ prevents git conflicts
- Set timeouts for one-shot mode โ complex tasks can take 5-10 minutes
- Use
hermes chat -q for fire-and-forget โ no PTY needed
- Use tmux for interactive sessions โ raw PTY mode has
\r vs \n issues with prompt_toolkit
- For scheduled tasks, use the
cronjob tool instead of spawning โ handles delivery and retry
---
Durable & Background Systems
Four systems run alongside the main conversation loop. Quick reference
here; full developer notes live in AGENTS.md, user-facing docs under
website/docs/user-guide/features/.
Delegation (delegate_task)
Synchronous subagent spawn โ the parent waits for the child's summary
before continuing its own loop. Isolated context + terminal session.
- Single:
delegate_task(goal, context, toolsets).
- Batch:
delegate_task(tasks=[{goal, ...}, ...]) runs children in
parallel, capped by delegation.max_concurrent_children (default 3).
- Roles:
leaf (default; cannot re-delegate) vs orchestrator
(can spawn its own workers, bounded by delegation.max_spawn_depth).
- Not durable. If the parent is interrupted, the child is
cancelled. For work that must outlive the turn, use cronjob or
terminal(background=True, notify_on_complete=True).
Config: delegation.* in config.yaml.
Tuning max_concurrent_children
Default is 3. Rule of thumb for raising it:
- Light tasks (web search, file grep): up to
6-8
- Medium tasks (code execution, browser):
4-5
- Heavy tasks (builds, large data):
2-3
- Actual bottleneck is usually the API rate limit, not local CPU/RAM. On a 10-core M4 with 16GB RAM, CPU is rarely the constraint.
- Formula: start at
5, raise only if profiling shows idle time between API responses.
Cron (scheduled jobs)
Durable scheduler โ cron/jobs.py + cron/scheduler.py. Drive it via
the cronjob tool, the hermes cron CLI (list, add, edit,
pause, resume, run, remove), or the /cron slash command.
- Schedules: duration (
"30m", "2h"), "every" phrase
( "every monday 9am"), 5-field cron ( "0 9 *"), or ISO timestamp.
- Per-job knobs:
skills, model/provider override, script
(pre-run data collection; no_agent=True makes the script the whole
job), context_from (chain job A's output into job B), workdir
(run in a specific dir with its AGENTS.md / CLAUDE.md loaded),
multi-platform delivery.
- Invariants: 3-minute hard interrupt per run,
.tick.lock file
prevents duplicate ticks across processes, cron sessions pass
skip_memory=True by default, and cron deliveries are framed with a
header/footer instead of being mirrored into the target gateway
session (keeps role alternation intact).
User docs: https://hermes-agent.nousresearch.com/docs/user-guide/features/cron
Curator (skill lifecycle)
Background maintenance for agent-created skills. Tracks usage, marks
idle skills stale, archives stale ones, keeps a pre-run tar.gz backup
so nothing is lost.
- CLI:
hermes curator <verb> โ status, run, pause, resume,
pin, unpin, archive, restore, prune, backup, rollback.
- Slash:
/curator <subcommand> mirrors the CLI.
- Scope: only touches skills with
created_by: "agent" provenance.
Bundled + hub-installed skills are off-limits. Never deletes โ
max destructive action is archive. Pinned skills are exempt from
every auto-transition and every LLM review pass.
- Telemetry: sidecar at
~/.hermes/skills/.usage.json holds
per-skill use_count, view_count, patch_count,
last_activity_at, state, pinned.
Config: curator.* (enabled, interval_hours, min_idle_hours,
stale_after_days, archive_after_days, backup.*).
User docs: https://hermes-agent.nousresearch.com/docs/user-guide/features/curator
Dreaming (periodic memory/skill consolidation)
For Anthropic-style "dreaming" workflows, combine cron + session_search + memory + skills + curator into a scheduled review loop. Start with a weekly, proposal-only report that audits recent sessions, repeated user corrections, memory conflicts, skill patch candidates, and cron/automation improvements. Do not automatically delete/replace memory or patch/archive skills unless the user explicitly approves the proposed changes. See references/weekly-dreaming-routine.md for the recommended prompt, report format, safety policy, and cron creation pattern.
Kanban (multi-agent work queue)
Durable SQLite board for multi-profile / multi-worker collaboration.
Users drive it via hermes kanban <verb>; dispatcher-spawned workers
see a focused kanban_* toolset gated by HERMES_KANBAN_TASK so the
schema footprint is zero outside worker processes.
- CLI verbs (common):
init, create, list (alias ls),
show, assign, link, unlink, comment, complete, block,
unblock, archive, tail. Less common: watch, stats, runs,
log, dispatch, daemon, gc.
- Worker toolset:
kanban_show, kanban_complete, kanban_block,
kanban_heartbeat, kanban_comment, kanban_create, kanban_link.
- Dispatcher runs inside the gateway by default
( kanban.dispatch_in_gateway: true) โ reclaims stale claims,
promotes ready tasks, atomically claims, spawns assigned profiles.
Auto-blocks a task after ~5 consecutive spawn failures.
- Isolation: board is the hard boundary (workers get
HERMES_KANBAN_BOARD pinned in env); tenant is a soft namespace
within a board for workspace-path + memory-key isolation.
User docs: https://hermes-agent.nousresearch.com/docs/user-guide/features/kanban
Log Relay (Hermes โ Discord)
A background Python script that tails ~/.hermes/logs/*.log and batches lines to a Discord channel. Includes session-ID extraction, rate-limit handling, and auto-restart via launchd/systemd. Useful for remote monitoring and audit trails.
- Reference:
references/discord-log-relay.md โ full setup, tuning, macOS/Linux service install, pitfalls.
- Template:
templates/discord-log-relay.py โ copy, set CHANNEL_ID, and deploy.
- Discord operations:
references/discord-operating-planes.md โ channel-purpose routing, periodic-summary vs Dreaming report formats, and safety/cost notes for Discord-first Hermes deployments.
Key pitfall: ask the user about batch frequency upfront rather than defaulting to real-time streaming. Most users prefer 10-minute or hourly batches. High-volume raw logs should be batched, summarized, or stored out-of-band; avoid Discord message storms during error loops.
Weekly Dreaming / Memory Curation
For long-running Hermes deployments, users may want an Anthropic-style "Dreaming" loop: a scheduled review that consolidates experience, proposes memory/skill/cron changes, and identifies what to keep, weaken, archive, or delete. Hermes has the building blocks (sessions, session_search, memory, skills, curator, cron), but the safe default is proposal mode:
1. Inspect recent usage and sessions.
2. Extract repeated success patterns, failure patterns, and user corrections.
3. Propose memory updates/removals without applying them silently.
4. Propose skill patches/archive candidates and cron/reporting improvements.
5. End with explicit approval checkboxes.
Do not silently rewrite or delete memory/skills from a Dreaming report unless the user explicitly authorized automatic application. See references/discord-operating-planes.md for a report template and routing heuristics.
---
Windows-Specific Quirks
Hermes runs natively on Windows (PowerShell, cmd, Windows Terminal, git-bash
mintty, VS Code integrated terminal). Most of it just works, but a handful
of differences between Win32 and POSIX have bitten us โ document new ones
here as you hit them so the next person (or the next session) doesn't
rediscover them from scratch.
Input / Keybindings
Alt+Enter doesn't insert a newline. Windows Terminal intercepts Alt+Enter
at the terminal layer to toggle fullscreen โ the keystroke never reaches
prompt_toolkit. Use Ctrl+Enter instead. Windows Terminal delivers
Ctrl+Enter as LF ( c-j), distinct from plain Enter ( c-m / CR), and the
CLI binds c-j to newline insertion on win32 only (see
_bind_prompt_submit_keys + the Windows-only c-j binding in cli.py).
Side effect: the raw Ctrl+J keystroke also inserts a newline on Windows โ
unavoidable, because Windows Terminal collapses Ctrl+Enter and Ctrl+J to
the same keycode at the Win32 console API layer. No conflicting binding
existed for Ctrl+J on Windows, so this is a harmless side effect.
mintty / git-bash behaves the same (fullscreen on Alt+Enter) unless you
disable Alt+Fn shortcuts in Options โ Keys. Easier to just use Ctrl+Enter.
Diagnosing keybindings. Run python scripts/keystroke_diagnostic.py
(repo root) to see exactly how prompt_toolkit identifies each keystroke
in the current terminal. Answers questions like "does Shift+Enter come
through as a distinct key?" (almost never โ most terminals collapse it
to plain Enter) or "what byte sequence is my terminal sending for
Ctrl+Enter?" This is how the Ctrl+Enter = c-j fact was established.
Config / Files
HTTP 400 "No models provided" on first run. config.yaml was saved
with a UTF-8 BOM (common when Windows apps write it). Re-save as UTF-8
without BOM. hermes config edit writes without BOM; manual edits in
Notepad are the usual culprit.
execute_code / Sandbox
WinError 10106 ("The requested service provider could not be loaded
or initialized") from the sandbox child process โ it can't create an
AF_INET socket, so the loopback-TCP RPC fallback fails before
connect(). Root cause is usually not a broken Winsock LSP; it's
Hermes's own env scrubber dropping SYSTEMROOT / WINDIR / COMSPEC
from the child env. Python's socket module needs SYSTEMROOT to locate
mswsock.dll. Fixed via the _WINDOWS_ESSENTIAL_ENV_VARS allowlist in
tools/code_execution_tool.py. If you still hit it, echo os.environ
inside an execute_code block to confirm SYSTEMROOT is set. Full
diagnostic recipe in references/execute-code-sandbox-env-windows.md.
Testing / Contributing
scripts/run_tests.sh doesn't work as-is on Windows โ it looks for
POSIX venv layouts ( .venv/bin/activate). The Hermes-installed venv at
venv/Scripts/ has no pip or pytest either (stripped for install size).
Workaround: install pytest + pytest-xdist + pyyaml into a system Python
3.11 user site, then invoke pytest directly with PYTHONPATH set:
"/c/Program Files/Python311/python" -m pip install --user pytest pytest-xdist pyyaml
export PYTHONPATH="$(pwd)"
"/c/Program Files/Python311/python" -m pytest tests/foo/test_bar.py -v --tb=short -n 0
Use -n 0, not -n 4 โ pyproject.toml's default addopts already
includes -n, and the wrapper's CI-parity guarantees don't apply off POSIX.
POSIX-only tests need skip guards. Common markers already in the codebase:
- Symlinks โ elevated privileges on Windows
0o600 file modes โ POSIX mode bits not enforced on NTFS by default
signal.SIGALRM โ Unix-only (see tests/conftest.py::_enforce_test_timeout)
- Winsock / Windows-specific regressions โ
@pytest.mark.skipif(sys.platform != "win32", ...)
Use the existing skip-pattern style (sys.platform == "win32" or
sys.platform.startswith("win")) to stay consistent with the rest of the
suite.
Path / Filesystem
Line endings. Git may warn LF will be replaced by CRLF the next time
Git touches it. Cosmetic โ the repo's .gitattributes normalizes. Don't
let editors auto-convert committed POSIX-newline files to CRLF.
Forward slashes work almost everywhere. C:/Users/... is accepted by
every Hermes tool and most Windows APIs. Prefer forward slashes in code
and logs โ avoids shell-escaping backslashes in bash.
---
Troubleshooting
Voice not working
1. Check stt.enabled: true in config.yaml
2. Verify provider: pip install faster-whisper or set API key
3. In gateway: /restart. In CLI: exit and relaunch.
Tool not available
1. hermes tools โ check if toolset is enabled for your platform
2. Some tools need env vars (check .env)
3. /reset after enabling tools
Model/provider issues
1. hermes doctor โ check config and dependencies
2. hermes auth add <provider> โ re-authenticate OAuth providers (use --type oauth)
3. Check .env has the right API key
4. Copilot 403: gh auth login tokens do NOT work for Copilot API. You must use the Copilot-specific OAuth device code flow via hermes model โ GitHub Copilot.
Changes not taking effect
- Tools/skills:
/reset starts a new session with updated toolset
- Config changes: In gateway:
/restart. In CLI: exit and relaunch.
- Code changes: Restart the CLI or gateway process
Deployed web dashboard shows stale CSS or theme changes
- Browser cache: Add
?v=N cache-busting query strings to CSS/JS/theme links in HTML.
- Service Worker cache: Bump
CACHE_NAME in sw.js to invalidate old shell caches.
- Data freshness: Use
fetch(url, {cache:'no-store'}) for live JSON feeds.
- Auto-detection: Embed
data-build in <html> and compare server build vs loaded build on page load to show a "new version available" banner. See references/static-site-cache-invalidation.md for the full diagnostic recipe and auto-detection pattern.
- Theme switcher reliability: If theme switching works in Chrome but not Samsung Internet, or feels broken on mobile, see
references/theme-switcher-reliability.md for the create-new-link โ load โ remove-old pattern.
- Emergency recovery: If a bad deploy breaks the main app JS, users need a standalone reset page. See
references/emergency-reset-page.md for a zero-dependency reset.html that clears Service Workers and caches without relying on the main app's JS.
Dashboard inspector feels too technical
- The default inspector view should contain only plain-language sentences: headline, "what they're doing now", "why it matters", and a silent visual progress bar (no text label).
- Move all technical fields (source IDs, confidence scores, progress labels, status slugs, badges) behind a "Show technical details" toggle.
- If users say "details are hard to understand," the fix is to remove more fields from the default view, not to add explanations. Explanations of technical fields are still technical.
- See
references/progressive-disclosure-human-first.md for the aggressive simplification pattern.
Pixel-art characters look wrong on mobile
- Decorative CSS elements (cheeks, ears, tails, badges) can be misread as facial features or appendages when avatars shrink below ~50 px.
- Hide them inside
@media (max-width:480px) so only the essential silhouette remains.
- See
references/pixel-art-mobile-readability.md for the exact selectors and rationale.
Skills not showing
1. hermes skills list โ verify installed
2. hermes skills config โ check platform enablement
3. Load explicitly: /skill name or hermes -s name
Gateway issues
Check logs first:
grep -i "failed to send\|error" ~/.hermes/logs/gateway.log | tail -20
Common gateway problems:
- Gateway dies on SSH logout: Enable linger:
sudo loginctl enable-linger $USER
- Gateway dies on WSL2 close: WSL2 requires
systemd=true in /etc/wsl.conf for systemd services to work. Without it, gateway falls back to nohup (dies when session closes).
- Gateway crash loop: Reset the failed state:
systemctl --user reset-failed hermes-gateway
- macOS: bot shows offline after idle time: The gateway runs as a user agent (
LimitLoadToSessionType=Aqua), so macOS suspends it when the system sleeps. The platform websocket drops and the bot appears offline until the network returns. Fix: keep the Mac awake (System Settings -> Energy -> Prevent automatic sleeping, or caffeinate -d -i -s -u &). Low Power Mode makes this worse, not better. See references/macos-gateway-sleep-disconnect.md for the full diagnostic recipe.
Platform-specific issues
- Discord bot silent: Must enable Message Content Intent in Bot โ Privileged Gateway Intents. See full Discord setup reference:
references/discord-gateway-setup.md.
- Slack bot only works in DMs: Must subscribe to
message.channels event. Without it, the bot ignores public channels.
- Windows-specific issues (
Alt+Enter newline, WinError 10106, UTF-8 BOM config, test suite, line endings): see the dedicated Windows-Specific Quirks section above.
Auxiliary models not working
If auxiliary tasks (vision, compression, session_search) fail silently, the auto provider can't find a backend. Either set OPENROUTER_API_KEY or GOOGLE_API_KEY, or explicitly configure each auxiliary task's provider:
hermes config set auxiliary.vision.provider <your_provider>
hermes config set auxiliary.vision.model <model_name>
Full system auth provisioning
For a one-shot workflow to maximize available credentials โ installing gh, generating SSH keys, configuring git, enabling all Hermes toolsets, and auditing current auth state โ see references/system-auth-setup.md.
Editing large files with patch
When a file is read with read_file(offset=...) (pagination), the tool warns that the view is partial. If you attempt patch without re-reading the full file first, you will likely hit non-unique match errors or corrupt the file. Fix: always call read_file without offset to load the whole file before patching. The tool explicitly warns: "โฆwas last read with offset/limit pagination (partial view). Re-read the whole file before overwriting it." โ heed this warning. For append-only updates (e.g., adding a cycle log entry to state.md), do not use terminal(command="cat >> file << 'EOF'...EOF") โ the terminal tool on macOS/Linux misinterprets heredoc << as backgrounding and fails. Instead, write a short Python script via write_file and execute it with terminal(command="python3 /tmp/script.py"). See references/terminal-heredoc-workaround.md for the full pattern.
Sibling subagent file overwrites
When multiple subagents are running in parallel (e.g. via delegate_task batch mode or kanban worker lanes), a file may be modified by one subagent while another is about to write to it. If you use write_file or patch on a file that was last read before a sibling subagent modified it, your write may silently truncate or revert the sibling's changes. The tool may show a warning like "this file was modified by sibling subagent X but this agent never read it."
Fix:
1. Heed the warning. If the tool reports a sibling modification, re-read the file with read_file before writing.
2. Prefer patch over write_file for partial updates โ patch only changes the matched region and is less likely to wipe unrelated content.
3. If the file is already published/deployed, and the local working copy gets corrupted, recover from the published copy:
cp ~/hermes-web/agent-pets/css/dashboard.css ~/.hermes/autonomous-agent-lab/pixel-pet-ops/web/css/dashboard.css
4. For append-only updates, write a small Python script and execute it rather than using write_file on the whole file.
Prevention: In kanban/multi-agent workflows, assign file-level ownership so only one worker touches each file. If parallel workers must edit the same file, have them write to separate temp files and let the orchestrator merge.
---
Windows-Specific Quirks
| Looking for... | Location |
|----------------|----------|
| Config options | hermes config edit or [Configuration docs](https://hermes-agent.nousresearch.com/docs/user-guide/configuration) |
| Available tools | hermes tools list or [Tools reference](https://hermes-agent.nousresearch.com/docs/reference/tools-reference) |
| Slash commands | /help in session or [Slash commands reference](https://hermes-agent.nousresearch.com/docs/reference/slash-commands) |
| Skills catalog | hermes skills browse or [Skills catalog](https://hermes-agent.nousresearch.com/docs/reference/skills-catalog) |
| Provider setup | hermes model or [Providers guide](https://hermes-agent.nousresearch.com/docs/integrations/providers) |
| Platform setup | hermes gateway setup or [Messaging docs](https://hermes-agent.nousresearch.com/docs/user-guide/messaging/) |
| MCP servers | hermes mcp list or [MCP guide](https://hermes-agent.nousresearch.com/docs/user-guide/features/mcp) |
| Profiles | hermes profile list or [Profiles docs](https://hermes-agent.nousresearch.com/docs/user-guide/profiles) |
| Cron jobs | hermes cron list or [Cron docs](https://hermes-agent.nousresearch.com/docs/user-guide/features/cron) |
| Memory | hermes memory status or [Memory docs](https://hermes-agent.nousresearch.com/docs/user-guide/features/memory) |
| Env variables | hermes config env-path or [Env vars reference](https://hermes-agent.nousresearch.com/docs/reference/environment-variables) |
| CLI commands | hermes --help or [CLI reference](https://hermes-agent.nousresearch.com/docs/reference/cli-commands) |
| Gateway logs | ~/.hermes/logs/gateway.log |
| Session files | ~/.hermes/sessions/ or hermes sessions browse |
| Source code | ~/.hermes/hermes-agent/ |
---
Contributor Quick Reference
For occasional contributors and PR authors. Full developer docs: https://hermes-agent.nousresearch.com/docs/developer-guide/
Project Layout
hermes-agent/
โโโ run_agent.py # AIAgent โ core conversation loop
โโโ model_tools.py # Tool discovery and dispatch
โโโ toolsets.py # Toolset definitions
โโโ cli.py # Interactive CLI (HermesCLI)
โโโ hermes_state.py # SQLite session store
โโโ agent/ # Prompt builder, context compression, memory, model routing, credential pooling, skill dispatch
โโโ hermes_cli/ # CLI subcommands, config, setup, commands
โ โโโ commands.py # Slash command registry (CommandDef)
โ โโโ config.py # DEFAULT_CONFIG, env var definitions
โ โโโ main.py # CLI entry point and argparse
โโโ tools/ # One file per tool
โ โโโ registry.py # Central tool registry
โโโ gateway/ # Messaging gateway
โ โโโ platforms/ # Platform adapters (telegram, discord, etc.)
โโโ cron/ # Job scheduler
โโโ tests/ # ~3000 pytest tests
โโโ website/ # Docusaurus docs site
Config: ~/.hermes/config.yaml (settings), ~/.hermes/.env (API keys).
Adding a Tool (3 files)
1. Create tools/your_tool.py:
import json, os
from tools.registry import registry
def check_requirements() -> bool:
return bool(os.getenv("EXAMPLE_API_KEY"))
def example_tool(param: str, task_id: str = None) -> str:
return json.dumps({"success": True, "data": "..."})
registry.register(
name="example_tool",
toolset="example",
schema={"name": "example_tool", "description": "...", "parameters": {...}},
handler=lambda args, **kw: example_tool(
param=args.get("param", ""), task_id=kw.get("task_id")),
check_fn=check_requirements,
requires_env=["EXAMPLE_API_KEY"],
)
2. Add to toolsets.py โ _HERMES_CORE_TOOLS list.
Auto-discovery: any tools/*.py file with a top-level registry.register() call is imported automatically โ no manual list needed.
All handlers must return JSON strings. Use get_hermes_home() for paths, never hardcode ~/.hermes.
Adding a Slash Command
1. Add CommandDef to COMMAND_REGISTRY in hermes_cli/commands.py
2. Add handler in cli.py โ process_command()
3. (Optional) Add gateway handler in gateway/run.py
All consumers (help text, autocomplete, Telegram menu, Slack mapping) derive from the central registry automatically.
Agent Loop (High Level)
run_conversation():
1. Build system prompt
2. Loop while iterations < max:
a. Call LLM (OpenAI-format messages + tool schemas)
b. If tool_calls โ dispatch each via handle_function_call() โ append results โ continue
c. If text response โ return
3. Context compression triggers automatically near token limit
Testing
python -m pytest tests/ -o 'addopts=' -q # Full suite
python -m pytest tests/tools/ -q # Specific area
- Tests auto-redirect
HERMES_HOME to temp dirs โ never touch real ~/.hermes/
- Run full suite before pushing any change
- Use
-o 'addopts=' to clear any baked-in pytest flags
Windows contributors: scripts/run_tests.sh currently looks for POSIX venvs ( .venv/bin/activate / venv/bin/activate) and will error out on Windows where the layout is venv/Scripts/activate + python.exe. The Hermes-installed venv at venv/Scripts/ also has no pip or pytest โ it's stripped for end-user install size. Workaround: install pytest + pytest-xdist + pyyaml into a system Python 3.11 user site ( /c/Program Files/Python311/python -m pip install --user pytest pytest-xdist pyyaml), then run tests directly:
export PYTHONPATH="$(pwd)"
"/c/Program Files/Python311/python" -m pytest tests/tools/test_foo.py -v --tb=short -n 0
Use -n 0 (not -n 4) because pyproject.toml's default addopts already includes -n, and the wrapper's CI-parity story doesn't apply off-POSIX.
Cross-platform test guards: tests that use POSIX-only syscalls need a skip marker. Common ones already in the codebase:
- Symlink creation โ
@pytest.mark.skipif(sys.platform == "win32", reason="Symlinks require elevated privileges on Windows") (see tests/cron/test_cron_script.py)
- POSIX file modes (0o600, etc.) โ
@pytest.mark.skipif(sys.platform.startswith("win"), reason="POSIX mode bits not enforced on Windows") (see tests/hermes_cli/test_auth_toctou_file_modes.py)
signal.SIGALRM โ Unix-only (see tests/conftest.py::_enforce_test_timeout)
- Live Winsock / Windows-specific regression tests โ
@pytest.mark.skipif(sys.platform != "win32", reason="Windows-specific regression")
Monkeypatching sys.platform is not enough when the code under test also calls platform.system() / platform.release() / platform.mac_ver(). Those functions re-read the real OS independently, so a test that sets sys.platform = "linux" on a Windows runner will still see platform.system() == "Windows" and route through the Windows branch. Patch all three together:
monkeypatch.setattr(sys, "platform", "linux")
monkeypatch.setattr(platform, "system", lambda: "Linux")
monkeypatch.setattr(platform, "release", lambda: "6.8.0-generic")
See tests/agent/test_prompt_builder.py::TestEnvironmentHints for a worked example.
Extending the system prompt's execution-environment block
Factual guidance about the host OS, user home, cwd, terminal backend, and shell (bash vs. PowerShell on Windows) is emitted from agent/prompt_builder.py::build_environment_hints(). This is also where the WSL hint and per-backend probe logic live. The convention:
- Local terminal backend โ emit host info (OS,
$HOME, cwd) + Windows-specific notes (hostname โ username, terminal uses bash not PowerShell).
- Remote terminal backend (anything in
_REMOTE_TERMINAL_BACKENDS: docker, singularity, modal, daytona, ssh, vercel_sandbox, managed_modal) โ suppress host info entirely and describe only the backend. A live uname/whoami/pwd probe runs inside the backend via tools.environments.get_environment(...).execute(...), cached per process in _BACKEND_PROBE_CACHE, with a static fallback if the probe times out.
- Key fact for prompt authoring: when
TERMINAL_ENV != "local", every file tool (read_file, write_file, patch, search_files) runs inside the backend container, not on the host. The system prompt must never describe the host in that case โ the agent can't touch it.
Full design notes, the exact emitted strings, and testing pitfalls:
references/prompt-builder-environment-hints.md.
Refactor-safety pattern (POSIX-equivalence guard): when you extract inline logic into a helper that adds Windows/platform-specific behavior, keep a _legacy_<name> oracle function in the test file that's a verbatim copy of the old code, then parametrize-diff against it. Example: tests/tools/test_code_execution_windows_env.py::TestPosixEquivalence. This locks in the invariant that POSIX behavior is bit-for-bit identical and makes any future drift fail loudly with a clear diff.
Commit Conventions
type: concise subject line
Optional body.
Types: fix:, feat:, refactor:, docs:, chore:
Key Rules
- Never break prompt caching โ don't change context, tools, or system prompt mid-conversation
- Message role alternation โ never two assistant or two user messages in a row
- Use
get_hermes_home() from hermes_constants for all paths (profile-safe)
- Config values go in
config.yaml, secrets go in .env
- New tools need a
check_fn so they only appear when requirements are met
[IMPORTANT: The user has invoked the "kanban-orchestrator" skill, indicating they want you to follow its instructions. The full skill content is loaded below.]
---
name: kanban-orchestrator
description: Decomposition playbook + anti-temptation rules for an orchestrator profile routing work through Kanban. The "don't do the work yourself" rule and the basic lifecycle are auto-injected into every kanban worker's system prompt; this skill is the deeper playbook when you're specifically playing the orchestrator role.
version: 3.0.0
platforms: [linux, macos, windows]
metadata:
hermes:
tags: [kanban, multi-agent, orchestration, routing]
related_skills: [kanban-worker]
---
Kanban Orchestrator โ Decomposition Playbook
> The core worker lifecycle (including the kanban_create fan-out pattern and the "decompose, don't execute" rule) is auto-injected into every kanban process via the KANBAN_GUIDANCE system-prompt block. This skill is the deeper playbook when you're an orchestrator profile whose whole job is routing.
Profiles are user-configured โ not a fixed roster
Hermes setups vary widely. Some users run a single profile that does everything; some run a small fleet (docker-worker, cron-worker); some run a curated specialist team they've named themselves. There is no default specialist roster โ the orchestrator skill does not know what profiles exist on this machine.
Before fanning out, you must ground the decomposition in the profiles that actually exist. The dispatcher silently fails to spawn unknown assignee names โ it doesn't autocorrect, doesn't suggest, doesn't fall back. So a card assigned to researcher on a setup that only has docker-worker just sits in ready forever.
Step 0: discover available profiles before planning.
Use one of these:
hermes profile list โ prints the table of profiles configured on this machine. Run it through your terminal tool if you have one; otherwise ask the user.
kanban_list(assignee="<some-name>") โ sanity-check a single name. Returns an empty list (rather than an error) for an unknown assignee, so this only confirms a name you're already considering.
- Just ask the user. "What profiles do you have set up?" is a fine first turn when the goal needs more than one specialist.
Cache the result in your working memory for the rest of the conversation. Re-asking every turn wastes a tool call.
When to use the board (vs. just doing the work)
Create Kanban tasks when any of these are true:
1. Multiple specialists are needed. Research + analysis + writing is three profiles.
2. The work should survive a crash or restart. Long-running, recurring, or important.
3. The user might want to interject. Human-in-the-loop at any step.
4. Multiple subtasks can run in parallel. Fan-out for speed.
5. Review / iteration is expected. A reviewer profile loops on drafter output.
6. The audit trail matters. Board rows persist in SQLite forever.
If none of those apply โ it's a small one-shot reasoning task โ use delegate_task instead or answer the user directly.
The anti-temptation rules
Your job description says "route, don't execute." The rules that enforce that:
- Do not execute the work yourself. Your restricted toolset usually doesn't even include terminal/file/code/web for implementation. If you find yourself "just fixing this quickly" โ stop and create a task for the right specialist.
- For any concrete task, create a Kanban task and assign it. Every single time.
- Split multi-lane requests before creating cards. A user prompt can contain several independent workstreams. Extract those lanes first, then create one card per lane instead of bundling unrelated work into a single implementer card.
- Run independent lanes in parallel. If two cards do not need each other's output, leave them unlinked so the dispatcher can fan them out. Link only true data dependencies.
- If no specialist fits the available profiles, ask the user which profile to create or which existing profile to use. Do not invent profile names; the dispatcher will silently drop unknown assignees.
- Decompose, route, and summarize โ that's the whole job.
Exception: micro-UI polish cycles
There is one narrow exception where the orchestrator may execute directly instead of creating Kanban cards: tiny UI-only polish cycles (e.g., adding a CSS class, a theme preview dot, a hover state, a cross-link, or a HUD button) that are purely presentational, require no cross-file logic changes, and fit comfortably inside a single bounded cycle with no need for review or parallel work. If the change is limited to HTML/CSS/JS cosmetics, no other profile has a stake in it, and the user did not ask for a design review, the orchestrator should just edit and publish rather than paying the kanban-overhead tax. This exception does NOT apply to architecture changes, adapter logic, plugin interfaces, or anything that touches the data layer.
Decomposition playbook
Step 1 โ Understand the goal
Ask clarifying questions if the goal is ambiguous. Cheap to ask; expensive to spawn the wrong fleet.
Step 2 โ Sketch the task graph
Before creating anything, draft the graph out loud (in your response to the user). Treat every concrete workstream as a candidate card:
1. Extract the lanes from the request.
2. Map each lane to one of the profiles you discovered in Step 0. If a lane doesn't fit any existing profile, ask the user which to use or create.
3. Decide whether each lane is independent or gated by another lane.
4. Create independent lanes as parallel cards with no parent links.
5. Create synthesis/review/integration cards with parent links to the lanes they depend on.
Examples of prompts that should fan out (using placeholder profile names โ substitute whatever exists on the user's setup):
- "Build an app" โ one card to a design-oriented profile for product/UI direction, one or two cards to engineering profiles for implementation, plus a later integration/review card if the user has a reviewer profile.
- "Fix blockers and check model variants" โ one implementation card for the blocker fixes plus one discovery/research card for config/source verification. A final reviewer card can depend on both.
- "Research docs and implement" โ a docs-research card can run in parallel with a codebase-discovery card; implementation waits only if it truly needs those findings.
- "Analyze this screenshot and find the related code" โ one card to a vision-capable profile for the visual analysis while another searches the codebase.
Words like "also," "finally," or "and" do not automatically imply a dependency. They often mean "make sure this is covered before reporting back." Only link tasks when one card cannot start until another card's output exists.
Show the graph to the user before creating cards. Let them correct it โ including which actual profile name should own each lane.
Step 3 โ Create tasks and link
Use the profile names from Step 0. The example below uses placeholders <profile-A>, <profile-B>, <profile-C> โ replace them with what the user actually has.
t1 = kanban_create(
title="research: Postgres cost vs current",
assignee="<profile-A>", # whichever profile handles research on this setup
body="Compare estimated infrastructure costs, migration costs, and ongoing ops costs over a 3-year window. Sources: AWS/GCP pricing, team time estimates, current Postgres bills from peers.",
tenant=os.environ.get("HERMES_TENANT"),
)["task_id"]
t2 = kanban_create(
title="research: Postgres performance vs current",
assignee="<profile-A>", # same profile, run in parallel
body="Compare query latency, throughput, and scaling characteristics at our expected data volume (~500GB, 10k QPS peak). Sources: benchmark papers, public case studies, pgbench results if easy.",
)["task_id"]
t3 = kanban_create(
title="synthesize migration recommendation",
assignee="<profile-B>", # whichever profile does synthesis/analysis
body="Read the findings from T1 (cost) and T2 (performance). Produce a 1-page recommendation with explicit trade-offs and a go/no-go call.",
parents=[t1, t2],
)["task_id"]
t4 = kanban_create(
title="draft decision memo",
assignee="<profile-C>", # whichever profile drafts user-facing prose
body="Turn the analyst's recommendation into a 2-page memo for the CTO. Match the tone of previous decision memos in the team's knowledge base.",
parents=[t3],
)["task_id"]
parents=[...] gates promotion โ children stay in todo until every parent reaches done, then auto-promote to ready. No manual coordination needed; the dispatcher and dependency engine handle it.
Step 4 โ Complete your own task
If you were spawned as a task yourself (e.g. a planner profile was assigned T0: "investigate Postgres migration"), mark it done with a summary of what you created:
kanban_complete(
summary="decomposed into T1-T4: 2 research lanes in parallel, 1 synthesis on their outputs, 1 prose draft on the recommendation",
metadata={
"task_graph": {
"T1": {"assignee": "<profile-A>", "parents": []},
"T2": {"assignee": "<profile-A>", "parents": []},
"T3": {"assignee": "<profile-B>", "parents": ["T1", "T2"]},
"T4": {"assignee": "<profile-C>", "parents": ["T3"]},
},
},
)
Step 5 โ Report back to the user
Tell them what you created in plain prose, naming the actual profiles you used:
> I've queued 4 tasks:
> - T1 (<profile-A>): cost comparison
> - T2 (<profile-A>): performance comparison, in parallel with T1
> - T3 (<profile-B>): synthesizes T1 + T2 into a recommendation
> - T4 (<profile-C>): turns T3 into a CTO memo
>
> The dispatcher will pick up T1 and T2 now. T3 starts when both finish. You'll get a gateway ping when T4 completes. Use the dashboard or hermes kanban tail <id> to follow along.
Common patterns
Fan-out + fan-in (research โ synthesize): N research-style cards with no parents, one synthesis card with all of them as parents.
Parallel implementation + validation: one implementer card makes the change while one explorer/researcher card verifies config, docs, or source mapping. A reviewer card can depend on both. Do not make the implementer own unrelated verification just because the user mentioned both in one sentence.
Pipeline with gates: planner โ implementer โ reviewer. Each stage's parents=[previous_task]. Reviewer blocks or completes; if reviewer blocks, the operator unblocks with feedback and respawns.
Same-profile queue: N tasks, all assigned to the same profile, no dependencies between them. Dispatcher serializes โ that profile processes them in priority order, accumulating experience in its own memory.
Parallel UI/frontend lanes: When the goal touches multiple independent HTML/CSS/JS files (e.g., a dashboard page and a 2D gather view), fan out to separate subagents per file. Each lane edits its own file, then the orchestrator integrates, fixes cross-file references (theme paths, shared JSON endpoints), and publishes. This avoids merge conflicts in single-file HTML dashboards and keeps each subagent's context focused. See references/parallel-ui-lanes-and-publishing.md for the post-subagent integration checklist and rsync safety notes.
Human-in-the-loop: Any task can kanban_block() to wait for input. Dispatcher respawns after /unblock. The comment thread carries the full context.
Pitfalls
Inventing profile names that don't exist. The dispatcher silently fails to spawn unknown assignees โ the card just sits in ready forever. Always assign to a profile from your Step 0 discovery; ask the user if you're unsure.
Bundling independent lanes into one card. If the user asks for two independent outcomes, create two cards. Example: "fix blockers and check model variants" is not one fixer task; create a fixer/engineer card for the fixes and an explorer/researcher card for the variant check, then optionally gate review on both.
Over-linking because of wording. "Finally check X" may still be parallel with implementation if X is static config, docs, or source discovery. Link it after implementation only when the check depends on the implementation result.
Forgetting dependency links. If the task graph says research -> implement -> review, do not create all tasks as independent ready cards. Use parent links so implement/review cannot run before their inputs exist.
Reassignment vs. new task. If a reviewer blocks with "needs changes," create a NEW task linked from the reviewer's task โ don't re-run the same task with a stern look. The new task is assigned to the original implementer profile.
Argument order for links. kanban_link(parent_id=..., child_id=...) โ parent first. Mixing them up demotes the wrong task to todo.
Ignoring explicit user feedback to keep building infrastructure. When the user says a specific UX issue (legibility, theme switching, movement density) is "immediate priority," treat it as P0 and route it before deeper packaging/architecture work. Infrastructure polish feels productive, but shipping user-visible fixes is what matters. Create cards for the UX feedback first, then resume infrastructure lanes.
Treating status: complete as immutable when user feedback says otherwise. A state.md that says status: complete does not override a user's report that a completion criterion is actually broken. If the user says "theme switching is not working" and the Final Completion Condition requires "working UI theme switcher," the mission is not complete. Reactivate immediately: set status: active, append a reactivation cycle log, and fix the issue. Do not burn cycles on post-complete verification while the user is reporting active defects.
Don't pre-create the whole graph if the shape depends on intermediate findings. If T3's structure depends on what T1 and T2 find, let T3 exist as a "synthesize findings" task whose own first step is to read parent handoffs and plan the rest. Orchestrators can spawn orchestrators.
Tenant inheritance. If HERMES_TENANT is set in your env, pass tenant=os.environ.get("HERMES_TENANT") on every kanban_create call so child tasks stay in the same namespace.
Verifying cross-file references after directory reorganization. When subagents edit HTML/CSS/JS files and the directory structure shifts (e.g., moving files from root into web/dashboard/ and web/gather/), relative asset paths ( themes/default/theme.css, ./ops-data.json) often break. After subagents finish, the orchestrator must grep for href= and src= in moved files and fix relative paths before publishing. Subagents don't know the final publish layout โ the orchestrator does.
Destructive sync wipes needed files. Commands like rsync -av --delete will delete destination files that aren't in the source list. If you publish a directory tree piecemeal (e.g., copy web/dashboard/ first, then web/gather/ separately), --delete on the first rsync will erase the gather files before the second rsync runs. Either list all source paths in a single rsync invocation, or omit --delete and use cp -r / rsync -av without deletion when doing staged copies.
Recovering stuck workers
When a worker profile keeps crashing, hallucinating, or getting blocked by its own mistakes (usually: wrong model, missing skill, broken credential), the kanban dashboard flags the task with a โ badge and opens a Recovery section in the drawer. Three primary actions:
1. Reclaim (or hermes kanban reclaim <task_id>) โ abort the running worker immediately and reset the task to ready. The existing claim TTL is ~15 min; this is the fast path out.
2. Reassign (or hermes kanban reassign <task_id> <new-profile> --reclaim) โ switch the task to a different profile (one that exists on this setup) and let the dispatcher pick it up with a fresh worker.
3. Change profile model โ the dashboard prints a copy-paste hint for hermes -p <profile> model since profile config lives on disk; edit it in a terminal, then Reclaim to retry with the new model.
Hallucination warnings appear on tasks where a worker's kanban_complete(created_cards=[...]) claim included card ids that don't exist or weren't created by the worker's profile (the gate blocks the completion), or where the free-form summary references t_<hex> ids that don't resolve (advisory prose scan, non-blocking). Both produce audit events that persist even after recovery actions โ the trail stays for debugging.
The user has provided the following instruction alongside the skill invocation: [IMPORTANT: You are running as a scheduled cron job. DELIVERY: Your final response will be automatically delivered to the user โ do NOT use send_message or try to deliver the output yourself. Just produce your report/output as your final response and the system handles the rest. SILENT: If there is genuinely nothing new to report, respond with exactly "[SILENT]" (nothing else) to suppress delivery. Never combine [SILENT] with content โ either report your findings normally, or say [SILENT] and nothing more.]
You are the 15-minute Orchestrator for Son's Autonomous Agent Lab v1, reporting to Discord channel ID 1505805763824586952.
Durable state path: /Users/jooho-hermes/.hermes/autonomous-agent-lab/state.md
Working directory for experiment artifacts: /Users/jooho-hermes/.hermes/autonomous-agent-lab/
Preferred published web root: /Users/jooho-hermes/hermes-web/agent-pets/
Top-level directive from Son:
- The project has evolved from a personal dashboard into an INSTALLABLE PRODUCT that external Hermes users can deploy.
- The final target is a self-contained, configurable, publishable solution: "Hermes Pixel Pet Ops Office".
- Do NOT shrink the mission into a small static MVP and autonomously stop.
- The Gather.town-style 2D spatial office is a first-class feature, not a side page.
Latest UX feedback from Son (treat as immediate priority before deeper packaging work):
- Details are hard for a human to understand. Add human-first summaries, plain-language labels, and progressive disclosure: summary first, technical details second.
- Gather Town version has too many agents roaming around. Reduce default movement, add density/speed controls, cluster agents by room/task, and add focus/calm mode.
- Theme switching is not visibly working. Implement real UI theme switcher with persistence and clear visual theme changes.
Key product requirements (installable solution level):
1. Config-driven architecture: all paths, URLs, colors, names, room layouts via config.yaml. No hardcoded references to jooho-hermes.
2. Self-contained package: clear directory structure (src/, web/, config/, docs/, scripts/), install script, requirements.txt.
3. Pluggable data adapter: support multiple backends via plugin architecture.
4. Themeable frontend: CSS variables driven from config, swappable themes, plus a working UI theme switcher.
5. Multi-tenant ready: works for any Hermes instance.
6. Build/Deploy ready: Dockerfile or docker-compose, or clear static-server setup.
7. Documentation: README, architecture docs, configuration reference, contributor guide.
8. Human-comprehensible UX: plain-language summaries and progressive disclosure for technical detail.
9. Gather.town calm mode: adjustable movement density/speed and less chaotic defaults.
10. Versioned releases: CHANGELOG.md, semantic versioning, release packaging.
Mission model:
- Read state.md first before doing anything else.
- If state.md says
status: inactive or has no Current Mission, do not invent work. Return exactly: ๐ก Autonomous Agent Lab ๋๊ธฐ์ค โ Son์ด ํธ๋ฆฌ๊ฑฐ/๋ฏธ์
์ ์ฃผ๋ฉด 15๋ถ ์ฌ์ดํด์ ์์ํฉ๋๋ค.
- If state.md says
status: active, run one bounded 15-minute cycle toward the full installable solution.
- If state.md says
status: complete, verify that the Final Completion Condition in state.md is truly met. If it is not fully met, reactivate or report that state needs correction.
Cycle procedure when active:
1. Read state.md first. Extract current mission, constraints, previous cycle log, and Final Completion Condition.
2. Decide the next smallest useful step toward installable solution quality. Focus on: architecture, configurability, documentation, and clean separation of concerns.
3. Use delegate_task for independent subagent lanes when helpful.
4. Prefer concrete progress: refactor to config-driven, add install scripts, create docs, add Docker support, theme system, plugin architecture.
5. Update state.md with a new cycle log entry before final reporting.
6. Completion rule: only set status: complete when every item under state.md Final Completion Condition is satisfied. A non-installable MVP is not complete.
7. Stop/block only if Son explicitly stops/redirects, a safety boundary is reached, or a hard blocker needs Son's decision.
Link requirement (never forget):
- Every cycle report MUST include at least one direct viewable link to the published dashboard/artifact.
- The canonical URL:
http://hermes-mac-mini.tail46b3c6.ts.net:8099/agent-pets/
- Include gather town URL too:
http://hermes-mac-mini.tail46b3c6.ts.net:8099/agent-pets/gather/
Final Discord message format:
[Autonomous Agent Lab v1 / Cycle N]
๋ชฉํ:
์ํ:
๊ฒฐ๊ณผ:
๊ฒ์ฆ:
๋ค์:
์ํ:
Safety/quality rules:
- Do not handle secrets, passwords, API keys, payment, permission dialogs, or destructive commands.
- Do not claim completion without updating state.md.
- Do not rely on Discord history as durable state.
- Do not spam raw logs; summarize lane outputs and verification.
- Keep working in /Users/jooho-hermes/.hermes/autonomous-agent-lab/ and publish only to /Users/jooho-hermes/hermes-web/agent-pets/ unless the state file says otherwise.
Design/UX priorities:
- Mobile responsiveness is first-class.
- Character animation/movement is desired.
- Every cycle report must include published links.
- This is now a product engineering mission. Architecture, configurability, and documentation matter as much as visuals.
Response
[Autonomous Agent Lab v1 / Cycle 72]
๋ชฉํ:
- Cycle 71์์ ์ ์๋
scripts/prune-history.sh ์๋ ํ์คํ ๋ฆฌ ์ ๋ฆฌ ์ ํธ๋ฆฌํฐ ์ถ๊ฐ
- ์ ์ฒด ํ์ดํ๋ผ์ธ ๊ฑด๊ฐ ์ํ ์ ๊ฒ ๋ฐ ๊ฒ์
์ํ:
1. scripts/prune-history.sh ์์ฑ ๋ฐ ์คํ ๊ฒ์ฆ
config.yaml์ data_retention ์ค์ ์ ์ฝ์ด SQLite history.db ์ ๋ฆฌ
- ์ธ๋ถ ์ฌ์ฉ์๊ฐ ์๋์ผ๋ก ์คํ ๊ฐ๋ฅํ ๋
๋ฆฝ ์ ํธ๋ฆฌํฐ
2. ์ด๋ํฐ ์คํ: 32 agents, 15 cron jobs, 20 sessions, 16 events
3. ํตํฉ ํ
์คํธ 128๊ฐ ์ ์ฒด ํต๊ณผ, ์ค์ ๊ฒ์ฆ 21๊ฐ ์ ์ฒด ํต๊ณผ
4. ๋ชจ๋ ์์ฐ์ /Users/jooho-hermes/hermes-web/agent-pets/์ ๊ฒ์
5. LaunchAgent ์ ์ ์๋ ํ์ธ ( refresh.err.log ๋น์ด ์์)
๊ฒฐ๊ณผ:
scripts/prune-history.sh ์ถ๊ฐ ์๋ฃ (์คํ ๊ฐ๋ฅ, ์ค์ ๊ธฐ๋ฐ)
- ๊ฒ์๋ ๋์๋ณด๋ ๋ฐ Gather Town ์ต์ ์ํ ์ ์ง
ops-data.json, health.json ์ ์ (< 60s)
๊ฒ์ฆ:
- ํตํฉ ํ
์คํธ: 128/128 ํต๊ณผ
- ์ค์ ๊ฒ์ฆ: 21/21 ํต๊ณผ
health.json: status=healthy, version=1.4.4
- ํ๋์ฝ๋ฉ๋
jooho-hermes ์ฐธ์กฐ 0๊ฐ
๋ค์:
- Son์ด ๋ธ๋ผ์ฐ์ ์์ 3๊ฐ์ง ์ฃผ์ UX ํญ๋ชฉ(ํ
๋ง ์ ํ, Gather calm ๋ชจ๋, human-first ์์ธ๋ณด๊ธฐ)์ ํ์ธ ํ ํผ๋๋ฐฑ
- ๋ง์กฑ ์
status: complete๋ก ๋ณ๊ฒฝ ์์
์ํ:
status: active ์ ์ง
- ๋ชจ๋ 11๊ฐ Final Completion Condition ์ถฉ์กฑ
- Son์ ๋ธ๋ผ์ฐ์ ์ธก ํ์ธ ๋๊ธฐ ์ค
๐ ๋์๋ณด๋: http://hermes-mac-mini.tail46b3c6.ts.net:8099/agent-pets/
๐ Gather Town: http://hermes-mac-mini.tail46b3c6.ts.net:8099/agent-pets/gather/
|
| 2026-05-20 00-07-29 |
83,556 chars |
2026-05-20_00-07-29.md |
Cron Job: autonomous-agent-lab-v1-orchestrator
Job ID: 35127ff89556
Run Time: 2026-05-20 00:07:29
Schedule: every 15m
Prompt
[IMPORTANT: The user has invoked the "hermes-agent" skill, indicating they want you to follow its instructions. The full skill content is loaded below.]
---
name: hermes-agent
description: "Configure, extend, or contribute to Hermes Agent."
version: 2.1.0
author: Hermes Agent + Teknium
license: MIT
platforms: [linux, macos, windows]
metadata:
hermes:
tags: [hermes, setup, configuration, multi-agent, spawning, cli, gateway, development]
homepage: https://github.com/NousResearch/hermes-agent
related_skills: [claude-code, codex, opencode]
---
Hermes Agent
Hermes Agent is an open-source AI agent framework by Nous Research that runs in your terminal, messaging platforms, and IDEs. It belongs to the same category as Claude Code (Anthropic), Codex (OpenAI), and OpenClaw โ autonomous coding and task-execution agents that use tool calling to interact with your system. Hermes works with any LLM provider (OpenRouter, Anthropic, OpenAI, DeepSeek, local models, and 15+ others) and runs on Linux, macOS, and WSL.
What makes Hermes different:
- Self-improving through skills โ Hermes learns from experience by saving reusable procedures as skills. When it solves a complex problem, discovers a workflow, or gets corrected, it can persist that knowledge as a skill document that loads into future sessions. Skills accumulate over time, making the agent better at your specific tasks and environment.
- Persistent memory across sessions โ remembers who you are, your preferences, environment details, and lessons learned. Pluggable memory backends (built-in, Honcho, Mem0, and more) let you choose how memory works.
- Multi-platform gateway โ the same agent runs on Telegram, Discord, Slack, WhatsApp, Signal, Matrix, Email, and 10+ other platforms with full tool access, not just chat.
- Provider-agnostic โ swap models and providers mid-workflow without changing anything else. Credential pools rotate across multiple API keys automatically.
- Profiles โ run multiple independent Hermes instances with isolated configs, sessions, skills, and memory.
- Extensible โ plugins, MCP servers, custom tools, webhook triggers, cron scheduling, and the full Python ecosystem.
People use Hermes for software development, research, system administration, data analysis, content creation, home automation, and anything else that benefits from an AI agent with persistent context and full system access.
This skill helps you work with Hermes Agent effectively โ setting it up, configuring features, spawning additional agent instances, troubleshooting issues, finding the right commands and settings, and understanding how the system works when you need to extend or contribute to it.
Docs: https://hermes-agent.nousresearch.com/docs/
Quick Start
Install
curl -fsSL https://raw.githubusercontent.com/NousResearch/hermes-agent/main/scripts/install.sh | bash
Interactive chat (default)
hermes
Single query
hermes chat -q "What is the capital of France?"
Setup wizard
hermes setup
Change model/provider
hermes model
Check health
hermes doctor
---
CLI Reference
Global Flags
hermes [flags] [command]
--version, -V Show version
--resume, -r SESSION Resume session by ID or title
--continue, -c [NAME] Resume by name, or most recent session
--worktree, -w Isolated git worktree mode (parallel agents)
--skills, -s SKILL Preload skills (comma-separate or repeat)
--profile, -p NAME Use a named profile
--yolo Skip dangerous command approval
--pass-session-id Include session ID in system prompt
No subcommand defaults to chat.
Chat
hermes chat [flags]
-q, --query TEXT Single query, non-interactive
-m, --model MODEL Model (e.g. anthropic/claude-sonnet-4)
-t, --toolsets LIST Comma-separated toolsets
--provider PROVIDER Force provider (openrouter, anthropic, nous, etc.)
-v, --verbose Verbose output
-Q, --quiet Suppress banner, spinner, tool previews
--checkpoints Enable filesystem checkpoints (/rollback)
--source TAG Session source tag (default: cli)
Configuration
hermes setup [section] Interactive wizard (model|terminal|gateway|tools|agent)
hermes model Interactive model/provider picker
hermes config View current config
hermes config edit Open config.yaml in $EDITOR
hermes config set KEY VAL Set a config value
hermes config path Print config.yaml path
hermes config env-path Print .env path
hermes config check Check for missing/outdated config
hermes config migrate Update config with new options
hermes doctor [--fix] Check dependencies and config
Credential Pools
hermes auth add Interactive credential wizard (oauth, api-key)
hermes auth list [PROVIDER] List pooled credentials
hermes auth remove P INDEX Remove by provider + index
hermes auth reset PROVIDER Clear exhaustion status
hermes logout Clear stored auth
Tools & Skills
hermes tools Interactive tool enable/disable (curses UI)
hermes tools list Show all tools and status
hermes tools enable NAME Enable a toolset
hermes tools disable NAME Disable a toolset
hermes skills list List installed skills
hermes skills search QUERY Search the skills hub
hermes skills install ID Install a skill (ID can be a hub identifier OR a direct https://โฆ/SKILL.md URL; pass --name to override when frontmatter has no name)
hermes skills inspect ID Preview without installing
hermes skills config Enable/disable skills per platform
hermes skills check Check for updates
hermes skills update Update outdated skills
hermes skills uninstall N Remove a hub skill
hermes skills publish PATH Publish to registry
hermes skills browse Browse all available skills
hermes skills tap add REPO Add a GitHub repo as skill source
MCP Servers
hermes mcp serve Run Hermes as an MCP server
hermes mcp add NAME Add an MCP server (--url or --command)
hermes mcp remove NAME Remove an MCP server
hermes mcp list List configured servers
hermes mcp test NAME Test connection
hermes mcp configure NAME Toggle tool selection
Gateway (Messaging Platforms)
hermes gateway run Start gateway foreground
hermes gateway install Install as background service
hermes gateway start/stop Control the service
hermes gateway restart Restart the service
hermes gateway status Check status
hermes gateway setup Configure platforms
Supported platforms: Telegram, Discord, Slack, WhatsApp, Signal, Email, SMS, Matrix, Mattermost, Home Assistant, DingTalk, Feishu, WeCom, BlueBubbles (iMessage), Weixin (WeChat), API Server, Webhooks. Open WebUI connects via the API Server adapter.
Platform docs: https://hermes-agent.nousresearch.com/docs/user-guide/messaging/
Discord-specific walkthrough (token, intents, service install, access control): see references/discord-gateway-setup.md in this skill.
- Per-channel personas and skill bindings: see
references/gateway-channel-personas.md (works on Discord, Slack, Telegram, Mattermost, Matrix).
- For long-running Discord-first operations, purpose-specific channel routing, periodic summaries, weekly Dreaming/audit reports, and log-safety patterns: see
references/discord-operating-planes.md.
- For broad Hermes/LifeOS/SQAF ecosystem audits (cron inventory, live services, dashboards, provider/model warnings, and control-plane gaps), see
references/ecosystem-audit.md.
Sessions
hermes sessions list List recent sessions
hermes sessions browse Interactive picker
hermes sessions export OUT Export to JSONL
hermes sessions rename ID T Rename a session
hermes sessions delete ID Delete a session
hermes sessions prune Clean up old sessions (--older-than N days)
hermes sessions stats Session store statistics
For browser-based viewing of existing Hermes CLI/Discord/cron session transcripts, prefer a lightweight static export from ~/.hermes/state.db into a private web root instead of assuming Open WebUI can browse Hermes' native session store. See references/hermes-session-static-web-viewer.md for the SQLite schema, static HTML export workflow, redaction/truncation cautions, and the user's Mac mini deployment (/hermes-sessions/ under the Tailscale-only ~/hermes-web site).
For cron job execution history, the same static-export pattern applies to ~/.hermes/cron/jobs.json and ~/.hermes/cron/output/{job_id}/*.md. See references/cron-history-web-viewer.md for the cron data model, schedule-dict pitfall, and the user's deployed /cron-history/ dashboard.
Cron Jobs
hermes cron list List jobs (--all for disabled)
hermes cron create SCHED Create: '30m', 'every 2h', '0 9 *'
hermes cron edit ID Edit schedule, prompt, delivery
hermes cron pause/resume ID Control job state
hermes cron run ID Trigger on next tick
hermes cron remove ID Delete a job
hermes cron status Scheduler status
For bounded autonomous lab/orchestrator cron jobs that use file-based state, subagent lanes, artifact publishing, and status transitions (active โ complete/blocked/inactive), see references/autonomous-agent-lab-cron-cycle.md. A reusable verification script template lives at scripts/verify-completion-template.py.
For a worked example of evolving an autonomous lab into a config-driven, themeable, Docker-ready installable product, see references/autonomous-lab-product-architecture.md. For CI, integration testing, pluggable adapter architecture, bounded cycle orchestration, and post-productization patterns, see references/product-maturity-patterns.md.
For the final completion verification checklist โ the explicit audit pattern to run before marking status: complete on an installable-solution mission, see references/autonomous-lab-completion-verification.md.
For the reactivation protocol when a completed lab receives new P0 feedback or the user contradicts a completion claim, see references/autonomous-lab-reactivation-protocol.md.
For the config/CHANGELOG version drift pitfall that occurs when autonomous labs evolve over many cycles, and for the related source vs. published file drift problem where the live web root diverges from the project source, see references/autonomous-lab-version-drift.md.
For adding historical trend tracking (SQLite-backed agent status transitions + vanilla JS SVG sparklines) to an autonomous lab dashboard, see references/history-tracking-sparkline-pattern.md.
For reusable dashboard UX patterns (onboarding tours, data freshness badges, keyboard shortcuts, progressive disclosure inspectors, cross-linking between views), see references/dashboard-ux-patterns.md.
For the aggressive human-first inspector refinement โ when users report that details are hard to understand and the fix is to strip technical labels from the default view โ see references/progressive-disclosure-human-first.md.
For programmatic verification of CSS custom-property theme systems โ catching scoping bugs, confirming theme distinctness, and validating JS switching logic โ see references/theme-system-verification.md.
- For Son's Discord-first autonomous experiments where a channel hosts a repeated multi-agent loop, use the Autonomous Discord Agent Lab pattern: create file-based durable state, a paused cron orchestrator delivered to
discord:<channel_id>, then activate it from a user mission trigger. See references/autonomous-discord-agent-lab.md.
- For verifying that a release package (
tar.gz) is actually installable by third parties and contains no stale artifacts or hardcoded references, see references/release-package-verification.md and the reusable script at scripts/release-verify.sh.
Webhooks
hermes webhook subscribe N Create route at /webhooks/<name>
hermes webhook list List subscriptions
hermes webhook remove NAME Remove a subscription
hermes webhook test NAME Send a test POST
Profiles
hermes profile list List all profiles
hermes profile create NAME Create (--clone, --clone-all, --clone-from)
hermes profile use NAME Set sticky default
hermes profile delete NAME Delete a profile
hermes profile show NAME Show details
hermes profile alias NAME Manage wrapper scripts
hermes profile rename A B Rename a profile
hermes profile export NAME Export to tar.gz
hermes profile import FILE Import from archive
Credential Pools
hermes auth add Interactive credential wizard
hermes auth list [PROVIDER] List pooled credentials
hermes auth remove P INDEX Remove by provider + index
hermes auth reset PROVIDER Clear exhaustion status
Other
hermes insights [--days N] Usage analytics
hermes update Update to latest version
hermes pairing list/approve/revoke DM authorization
hermes plugins list/install/remove Plugin management
hermes honcho setup/status Honcho memory integration (requires honcho plugin)
hermes memory setup/status/off Memory provider config
hermes completion bash|zsh Shell completions
hermes acp ACP server (IDE integration)
hermes claw migrate Migrate from OpenClaw
hermes uninstall Uninstall Hermes
---
Slash Commands (In-Session)
Type these during an interactive chat session. New commands land fairly
often; if something below looks stale, run /help in-session for the
authoritative list or see the [live slash commands reference](https://hermes-agent.nousresearch.com/docs/reference/slash-commands).
The registry of record is hermes_cli/commands.py โ every consumer
(autocomplete, Telegram menu, Slack mapping, /help) derives from it.
Session Control
/new (/reset) Fresh session
/clear Clear screen + new session (CLI)
/retry Resend last message
/undo Remove last exchange
/title [name] Name the session
/compress Manually compress context
/stop Kill background processes
/rollback [N] Restore filesystem checkpoint
/snapshot [sub] Create or restore state snapshots of Hermes config/state (CLI)
/background <prompt> Run prompt in background
/queue <prompt> Queue for next turn
/steer <prompt> Inject a message after the next tool call without interrupting
/agents (/tasks) Show active agents and running tasks
/resume [name] Resume a named session
/goal [text|sub] Set a standing goal Hermes works on across turns until achieved
(subcommands: status, pause, resume, clear)
/redraw Force a full UI repaint (CLI)
Configuration
/config Show config (CLI)
/model [name] Show or change model
/personality [name] Set personality
/reasoning [level] Set reasoning (none|minimal|low|medium|high|xhigh|show|hide)
/verbose Cycle: off โ new โ all โ verbose
/voice [on|off|tts] Voice mode
/yolo Toggle approval bypass
/busy [sub] Control what Enter does while Hermes is working (CLI)
(subcommands: queue, steer, interrupt, status)
/indicator [style] Pick the TUI busy-indicator style (CLI)
(styles: kaomoji, emoji, unicode, ascii)
/footer [on|off] Toggle gateway runtime-metadata footer on final replies
/skin [name] Change theme (CLI)
/statusbar Toggle status bar (CLI)
Tools & Skills
/tools Manage tools (CLI)
/toolsets List toolsets (CLI)
/skills Search/install skills (CLI)
/skill <name> Load a skill into session
/reload-skills Re-scan ~/.hermes/skills/ for added/removed skills
/reload Reload .env variables into the running session (CLI)
/reload-mcp Reload MCP servers
/cron Manage cron jobs (CLI)
/curator [sub] Background skill maintenance (status, run, pin, archive, โฆ)
/kanban [sub] Multi-profile collaboration board (tasks, links, comments)
/plugins List plugins (CLI)
Gateway
/approve Approve a pending command (gateway)
/deny Deny a pending command (gateway)
/restart Restart gateway (gateway)
/sethome Set current chat as home channel (gateway)
/update Update Hermes to latest (gateway)
/topic [sub] Enable or inspect Telegram DM topic sessions (gateway)
/platforms (/gateway) Show platform connection status (gateway)
Utility
/branch (/fork) Branch the current session
/fast Toggle priority/fast processing
/browser Open CDP browser connection
/history Show conversation history (CLI)
/save Save conversation to file (CLI)
/copy [N] Copy the last assistant response to clipboard (CLI)
/paste Attach clipboard image (CLI)
/image Attach local image file (CLI)
Info
/help Show commands
/commands [page] Browse all commands (gateway)
/usage Token usage
/insights [days] Usage analytics
/gquota Show Google Gemini Code Assist quota usage (CLI)
/status Session info (gateway)
/profile Active profile info
/debug Upload debug report (system info + logs) and get shareable links
Exit
/quit (/exit, /q) Exit CLI
---
Key Paths & Config
~/.hermes/config.yaml Main configuration
~/.hermes/.env API keys and secrets
$HERMES_HOME/skills/ Installed skills
~/.hermes/sessions/ Session transcripts
~/.hermes/logs/ Gateway and error logs
~/.hermes/auth.json OAuth tokens and credential pools
~/.hermes/hermes-agent/ Source code (if git-installed)
Profiles use ~/.hermes/profiles/<name>/ with the same layout.
Config Sections
Edit with hermes config edit or hermes config set section.key value.
| Section | Key options |
|---------|-------------|
| model | default, provider, base_url, api_key, context_length |
| agent | max_turns (90), tool_use_enforcement |
| terminal | backend (local/docker/ssh/modal), cwd, timeout (180) |
| compression | enabled, threshold (0.50), target_ratio (0.20) |
| display | skin, tool_progress, show_reasoning, show_cost |
| stt | enabled, provider (local/groq/openai/mistral) |
| tts | provider (edge/elevenlabs/openai/minimax/mistral/neutts) |
| memory | memory_enabled, user_profile_enabled, provider |
| security | tirith_enabled, website_blocklist |
| delegation | model, provider, base_url, api_key, max_iterations (50), reasoning_effort |
| checkpoints | enabled, max_snapshots (50) |
| fallback_model | provider, model, base_url, key_env |
Fallback Providers
Hermes can automatically fail over to a backup provider:model when the primary is unavailable. This is turn-scoped โ each new user message starts with the primary restored; fallback only activates mid-turn when the primary fails.
Configuration ( ~/.hermes/config.yaml):
fallback_model:
provider: opencode-go
model: kimi-k2.6
Or use the interactive manager:
hermes fallback add # interactive picker
hermes fallback list # show fallback chain
hermes fallback remove # remove by index
Legacy note: fallback_model (singular) is the legacy single-fallback key. fallback_providers (list) supports multiple ordered fallbacks. When both exist, fallback_providers takes priority.
Trigger conditions (after exhausting retries where applicable):
- Rate limits (HTTP 429)
- Server errors (HTTP 500, 502, 503)
- Auth failures (HTTP 401, 403) โ immediately
- Not found (HTTP 404) โ immediately
- Invalid / empty responses repeatedly
Supported providers include all standard providers (OpenRouter, Anthropic, OpenCode Go/ Zen, Kimi, etc.) plus custom endpoints with base_url + key_env. Full provider docs: https://hermes-agent.nousresearch.com/docs/integrations/providers
Limitations:
- Subagent delegation does not inherit fallback config
- Cron jobs do not use fallback (use per-job provider/model overrides)
- Auxiliary tasks (vision, compression, etc.) use their own
auxiliary.* provider chain
For a deep-dive with worked examples and model lists, see references/fallback-providers.md.
Full config reference: https://hermes-agent.nousresearch.com/docs/user-guide/configuration
Providers
20+ providers supported. Set via hermes model or hermes setup.
| Provider | Auth | Key env var |
|----------|------|-------------|
| OpenRouter | API key | OPENROUTER_API_KEY |
| Anthropic | API key | ANTHROPIC_API_KEY |
| Nous Portal | OAuth | hermes auth |
| OpenAI Codex | OAuth | hermes auth |
| GitHub Copilot | Token | COPILOT_GITHUB_TOKEN |
| Google Gemini | API key | GOOGLE_API_KEY or GEMINI_API_KEY |
| DeepSeek | API key | DEEPSEEK_API_KEY |
| xAI / Grok | API key | XAI_API_KEY |
| Hugging Face | Token | HF_TOKEN |
| Z.AI / GLM | API key | GLM_API_KEY |
| MiniMax | API key | MINIMAX_API_KEY |
| MiniMax CN | API key | MINIMAX_CN_API_KEY |
| Kimi / Moonshot | API key | KIMI_API_KEY |
| Alibaba / DashScope | API key | DASHSCOPE_API_KEY |
| Xiaomi MiMo | API key | XIAOMI_API_KEY |
| Kilo Code | API key | KILOCODE_API_KEY |
| AI Gateway (Vercel) | API key | AI_GATEWAY_API_KEY |
| OpenCode Zen | API key | OPENCODE_ZEN_API_KEY |
| OpenCode Go | API key | OPENCODE_GO_API_KEY |
| Qwen OAuth | OAuth | hermes auth add qwen-oauth |
| Custom endpoint | Config | model.base_url + model.api_key in config.yaml |
| GitHub Copilot ACP | External | COPILOT_CLI_PATH or Copilot CLI |
Full provider docs: https://hermes-agent.nousresearch.com/docs/integrations/providers
Toolsets
Enable/disable via hermes tools (interactive) or hermes tools enable/disable NAME.
| Toolset | What it provides |
|---------|-----------------|
| web | Web search and content extraction |
| search | Web search only (subset of web) |
| browser | Browser automation (Browserbase, Camofox, or local Chromium) |
| terminal | Shell commands and process management |
| file | File read/write/search/patch |
| code_execution | Sandboxed Python execution |
| vision | Image analysis |
| image_gen | AI image generation |
| video | Video analysis and generation |
| tts | Text-to-speech |
| skills | Skill browsing and management |
| memory | Persistent cross-session memory |
| session_search | Search past conversations |
| delegation | Subagent task delegation |
| cronjob | Scheduled task management |
| clarify | Ask user clarifying questions |
| messaging | Cross-platform message sending |
| todo | In-session task planning and tracking |
| kanban | Multi-agent work-queue tools (gated to workers) |
| debugging | Extra introspection/debug tools (off by default) |
| safe | Minimal, low-risk toolset for locked-down sessions |
| spotify | Spotify playback and playlist control |
| homeassistant | Smart home control (off by default) |
| discord | Discord integration tools |
| discord_admin | Discord admin/moderation tools |
| feishu_doc | Feishu (Lark) document tools |
| feishu_drive | Feishu (Lark) drive tools |
| yuanbao | Yuanbao integration tools |
| rl | Reinforcement learning tools (off by default) |
| moa | Mixture of Agents (off by default) |
Full enumeration lives in toolsets.py as the TOOLSETS dict; _HERMES_CORE_TOOLS is the default bundle most platforms inherit from.
Tool changes take effect on /reset (new session). They do NOT apply mid-conversation to preserve prompt caching.
---
Security & Privacy Toggles
Common "why is Hermes doing X to my output / tool calls / commands?" toggles โ and the exact commands to change them. Most of these need a fresh session (/reset in chat, or start a new hermes invocation) because they're read once at startup.
Secret redaction in tool output
Secret redaction is off by default โ tool output (terminal stdout, read_file, web content, subagent summaries, etc.) passes through unmodified. If the user wants Hermes to auto-mask strings that look like API keys, tokens, and secrets before they enter the conversation context and logs:
hermes config set security.redact_secrets true # enable globally
Restart required. security.redact_secrets is snapshotted at import time โ toggling it mid-session (e.g. via export HERMES_REDACT_SECRETS=true from a tool call) will NOT take effect for the running process. Tell the user to run hermes config set security.redact_secrets true in a terminal, then start a new session. This is deliberate โ it prevents an LLM from flipping the toggle on itself mid-task.
Disable again with:
hermes config set security.redact_secrets false
PII redaction in gateway messages
Separate from secret redaction. When enabled, the gateway hashes user IDs and strips phone numbers from the session context before it reaches the model:
hermes config set privacy.redact_pii true # enable
hermes config set privacy.redact_pii false # disable (default)
Command approval prompts
By default (approvals.mode: manual), Hermes prompts the user before running shell commands flagged as destructive (rm -rf, git reset --hard, etc.). The modes are:
manual โ always prompt (default)
smart โ use an auxiliary LLM to auto-approve low-risk commands, prompt on high-risk
off โ skip all approval prompts (equivalent to --yolo)
hermes config set approvals.mode smart # recommended middle ground
hermes config set approvals.mode off # bypass everything (not recommended)
Per-invocation bypass without changing config:
hermes --yolo โฆ
export HERMES_YOLO_MODE=1
Note: YOLO / approvals.mode: off does NOT turn off secret redaction. They are independent.
Shell hooks allowlist
Some shell-hook integrations require explicit allowlisting before they fire. Managed via ~/.hermes/shell-hooks-allowlist.json โ prompted interactively the first time a hook wants to run.
Disabling the web/browser/image-gen tools
To keep the model away from network or media tools entirely, open hermes tools and toggle per-platform. Takes effect on next session (/reset). See the Tools & Skills section above.
---
Voice & Transcription
STT (Voice โ Text)
Voice messages from messaging platforms are auto-transcribed.
Provider priority (auto-detected):
1. Local faster-whisper โ free, no API key: pip install faster-whisper
2. Groq Whisper โ free tier: set GROQ_API_KEY
3. OpenAI Whisper โ paid: set VOICE_TOOLS_OPENAI_KEY
4. Mistral Voxtral โ set MISTRAL_API_KEY
Config:
stt:
enabled: true
provider: local # local, groq, openai, mistral
local:
model: base # tiny, base, small, medium, large-v3
TTS (Text โ Voice)
| Provider | Env var | Free? |
|----------|---------|-------|
| Edge TTS | None | Yes (default) |
| ElevenLabs | ELEVENLABS_API_KEY | Free tier |
| OpenAI | VOICE_TOOLS_OPENAI_KEY | Paid |
| MiniMax | MINIMAX_API_KEY | Paid |
| Mistral (Voxtral) | MISTRAL_API_KEY | Paid |
| NeuTTS (local) | None (pip install neutts[all] + espeak-ng) | Free |
Voice commands: /voice on (voice-to-voice), /voice tts (always voice), /voice off.
---
Spawning Additional Hermes Instances
Run additional Hermes processes as fully independent subprocesses โ separate sessions, tools, and environments.
When to Use This vs delegate_task
| | delegate_task | Spawning hermes process |
|-|-----------------|--------------------------|
| Isolation | Separate conversation, shared process | Fully independent process |
| Duration | Minutes (bounded by parent loop) | Hours/days |
| Tool access | Subset of parent's tools | Full tool access |
| Interactive | No | Yes (PTY mode) |
| Use case | Quick parallel subtasks | Long autonomous missions |
One-Shot Mode
terminal(command="hermes chat -q 'Research GRPO papers and write summary to ~/research/grpo.md'", timeout=300)
Background for long tasks:
terminal(command="hermes chat -q 'Set up CI/CD for ~/myapp'", background=true)
Interactive PTY Mode (via tmux)
Hermes uses prompt_toolkit, which requires a real terminal. Use tmux for interactive spawning:
Start
terminal(command="tmux new-session -d -s agent1 -x 120 -y 40 'hermes'", timeout=10)
Wait for startup, then send a message
terminal(command="sleep 8 && tmux send-keys -t agent1 'Build a FastAPI auth service' Enter", timeout=15)
Read output
terminal(command="sleep 20 && tmux capture-pane -t agent1 -p", timeout=5)
Send follow-up
terminal(command="tmux send-keys -t agent1 'Add rate limiting middleware' Enter", timeout=5)
Exit
terminal(command="tmux send-keys -t agent1 '/exit' Enter && sleep 2 && tmux kill-session -t agent1", timeout=10)
Multi-Agent Coordination
Agent A: backend
terminal(command="tmux new-session -d -s backend -x 120 -y 40 'hermes -w'", timeout=10)
terminal(command="sleep 8 && tmux send-keys -t backend 'Build REST API for user management' Enter", timeout=15)
Agent B: frontend
terminal(command="tmux new-session -d -s frontend -x 120 -y 40 'hermes -w'", timeout=10)
terminal(command="sleep 8 && tmux send-keys -t frontend 'Build React dashboard for user management' Enter", timeout=15)
Check progress, relay context between them
terminal(command="tmux capture-pane -t backend -p | tail -30", timeout=5)
terminal(command="tmux send-keys -t frontend 'Here is the API schema from the backend agent: ...' Enter", timeout=5)
Session Resume
Resume most recent session
terminal(command="tmux new-session -d -s resumed 'hermes --continue'", timeout=10)
Resume specific session
terminal(command="tmux new-session -d -s resumed 'hermes --resume 20260225_143052_a1b2c3'", timeout=10)
Tips
- Prefer
delegate_task for quick subtasks โ less overhead than spawning a full process
- Use
-w (worktree mode) when spawning agents that edit code โ prevents git conflicts
- Set timeouts for one-shot mode โ complex tasks can take 5-10 minutes
- Use
hermes chat -q for fire-and-forget โ no PTY needed
- Use tmux for interactive sessions โ raw PTY mode has
\r vs \n issues with prompt_toolkit
- For scheduled tasks, use the
cronjob tool instead of spawning โ handles delivery and retry
---
Durable & Background Systems
Four systems run alongside the main conversation loop. Quick reference
here; full developer notes live in AGENTS.md, user-facing docs under
website/docs/user-guide/features/.
Delegation (delegate_task)
Synchronous subagent spawn โ the parent waits for the child's summary
before continuing its own loop. Isolated context + terminal session.
- Single:
delegate_task(goal, context, toolsets).
- Batch:
delegate_task(tasks=[{goal, ...}, ...]) runs children in
parallel, capped by delegation.max_concurrent_children (default 3).
- Roles:
leaf (default; cannot re-delegate) vs orchestrator
(can spawn its own workers, bounded by delegation.max_spawn_depth).
- Not durable. If the parent is interrupted, the child is
cancelled. For work that must outlive the turn, use cronjob or
terminal(background=True, notify_on_complete=True).
Config: delegation.* in config.yaml.
Tuning max_concurrent_children
Default is 3. Rule of thumb for raising it:
- Light tasks (web search, file grep): up to
6-8
- Medium tasks (code execution, browser):
4-5
- Heavy tasks (builds, large data):
2-3
- Actual bottleneck is usually the API rate limit, not local CPU/RAM. On a 10-core M4 with 16GB RAM, CPU is rarely the constraint.
- Formula: start at
5, raise only if profiling shows idle time between API responses.
Cron (scheduled jobs)
Durable scheduler โ cron/jobs.py + cron/scheduler.py. Drive it via
the cronjob tool, the hermes cron CLI (list, add, edit,
pause, resume, run, remove), or the /cron slash command.
- Schedules: duration (
"30m", "2h"), "every" phrase
( "every monday 9am"), 5-field cron ( "0 9 *"), or ISO timestamp.
- Per-job knobs:
skills, model/provider override, script
(pre-run data collection; no_agent=True makes the script the whole
job), context_from (chain job A's output into job B), workdir
(run in a specific dir with its AGENTS.md / CLAUDE.md loaded),
multi-platform delivery.
- Invariants: 3-minute hard interrupt per run,
.tick.lock file
prevents duplicate ticks across processes, cron sessions pass
skip_memory=True by default, and cron deliveries are framed with a
header/footer instead of being mirrored into the target gateway
session (keeps role alternation intact).
User docs: https://hermes-agent.nousresearch.com/docs/user-guide/features/cron
Curator (skill lifecycle)
Background maintenance for agent-created skills. Tracks usage, marks
idle skills stale, archives stale ones, keeps a pre-run tar.gz backup
so nothing is lost.
- CLI:
hermes curator <verb> โ status, run, pause, resume,
pin, unpin, archive, restore, prune, backup, rollback.
- Slash:
/curator <subcommand> mirrors the CLI.
- Scope: only touches skills with
created_by: "agent" provenance.
Bundled + hub-installed skills are off-limits. Never deletes โ
max destructive action is archive. Pinned skills are exempt from
every auto-transition and every LLM review pass.
- Telemetry: sidecar at
~/.hermes/skills/.usage.json holds
per-skill use_count, view_count, patch_count,
last_activity_at, state, pinned.
Config: curator.* (enabled, interval_hours, min_idle_hours,
stale_after_days, archive_after_days, backup.*).
User docs: https://hermes-agent.nousresearch.com/docs/user-guide/features/curator
Dreaming (periodic memory/skill consolidation)
For Anthropic-style "dreaming" workflows, combine cron + session_search + memory + skills + curator into a scheduled review loop. Start with a weekly, proposal-only report that audits recent sessions, repeated user corrections, memory conflicts, skill patch candidates, and cron/automation improvements. Do not automatically delete/replace memory or patch/archive skills unless the user explicitly approves the proposed changes. See references/weekly-dreaming-routine.md for the recommended prompt, report format, safety policy, and cron creation pattern.
Kanban (multi-agent work queue)
Durable SQLite board for multi-profile / multi-worker collaboration.
Users drive it via hermes kanban <verb>; dispatcher-spawned workers
see a focused kanban_* toolset gated by HERMES_KANBAN_TASK so the
schema footprint is zero outside worker processes.
- CLI verbs (common):
init, create, list (alias ls),
show, assign, link, unlink, comment, complete, block,
unblock, archive, tail. Less common: watch, stats, runs,
log, dispatch, daemon, gc.
- Worker toolset:
kanban_show, kanban_complete, kanban_block,
kanban_heartbeat, kanban_comment, kanban_create, kanban_link.
- Dispatcher runs inside the gateway by default
( kanban.dispatch_in_gateway: true) โ reclaims stale claims,
promotes ready tasks, atomically claims, spawns assigned profiles.
Auto-blocks a task after ~5 consecutive spawn failures.
- Isolation: board is the hard boundary (workers get
HERMES_KANBAN_BOARD pinned in env); tenant is a soft namespace
within a board for workspace-path + memory-key isolation.
User docs: https://hermes-agent.nousresearch.com/docs/user-guide/features/kanban
Log Relay (Hermes โ Discord)
A background Python script that tails ~/.hermes/logs/*.log and batches lines to a Discord channel. Includes session-ID extraction, rate-limit handling, and auto-restart via launchd/systemd. Useful for remote monitoring and audit trails.
- Reference:
references/discord-log-relay.md โ full setup, tuning, macOS/Linux service install, pitfalls.
- Template:
templates/discord-log-relay.py โ copy, set CHANNEL_ID, and deploy.
- Discord operations:
references/discord-operating-planes.md โ channel-purpose routing, periodic-summary vs Dreaming report formats, and safety/cost notes for Discord-first Hermes deployments.
Key pitfall: ask the user about batch frequency upfront rather than defaulting to real-time streaming. Most users prefer 10-minute or hourly batches. High-volume raw logs should be batched, summarized, or stored out-of-band; avoid Discord message storms during error loops.
Weekly Dreaming / Memory Curation
For long-running Hermes deployments, users may want an Anthropic-style "Dreaming" loop: a scheduled review that consolidates experience, proposes memory/skill/cron changes, and identifies what to keep, weaken, archive, or delete. Hermes has the building blocks (sessions, session_search, memory, skills, curator, cron), but the safe default is proposal mode:
1. Inspect recent usage and sessions.
2. Extract repeated success patterns, failure patterns, and user corrections.
3. Propose memory updates/removals without applying them silently.
4. Propose skill patches/archive candidates and cron/reporting improvements.
5. End with explicit approval checkboxes.
Do not silently rewrite or delete memory/skills from a Dreaming report unless the user explicitly authorized automatic application. See references/discord-operating-planes.md for a report template and routing heuristics.
---
Windows-Specific Quirks
Hermes runs natively on Windows (PowerShell, cmd, Windows Terminal, git-bash
mintty, VS Code integrated terminal). Most of it just works, but a handful
of differences between Win32 and POSIX have bitten us โ document new ones
here as you hit them so the next person (or the next session) doesn't
rediscover them from scratch.
Input / Keybindings
Alt+Enter doesn't insert a newline. Windows Terminal intercepts Alt+Enter
at the terminal layer to toggle fullscreen โ the keystroke never reaches
prompt_toolkit. Use Ctrl+Enter instead. Windows Terminal delivers
Ctrl+Enter as LF ( c-j), distinct from plain Enter ( c-m / CR), and the
CLI binds c-j to newline insertion on win32 only (see
_bind_prompt_submit_keys + the Windows-only c-j binding in cli.py).
Side effect: the raw Ctrl+J keystroke also inserts a newline on Windows โ
unavoidable, because Windows Terminal collapses Ctrl+Enter and Ctrl+J to
the same keycode at the Win32 console API layer. No conflicting binding
existed for Ctrl+J on Windows, so this is a harmless side effect.
mintty / git-bash behaves the same (fullscreen on Alt+Enter) unless you
disable Alt+Fn shortcuts in Options โ Keys. Easier to just use Ctrl+Enter.
Diagnosing keybindings. Run python scripts/keystroke_diagnostic.py
(repo root) to see exactly how prompt_toolkit identifies each keystroke
in the current terminal. Answers questions like "does Shift+Enter come
through as a distinct key?" (almost never โ most terminals collapse it
to plain Enter) or "what byte sequence is my terminal sending for
Ctrl+Enter?" This is how the Ctrl+Enter = c-j fact was established.
Config / Files
HTTP 400 "No models provided" on first run. config.yaml was saved
with a UTF-8 BOM (common when Windows apps write it). Re-save as UTF-8
without BOM. hermes config edit writes without BOM; manual edits in
Notepad are the usual culprit.
execute_code / Sandbox
WinError 10106 ("The requested service provider could not be loaded
or initialized") from the sandbox child process โ it can't create an
AF_INET socket, so the loopback-TCP RPC fallback fails before
connect(). Root cause is usually not a broken Winsock LSP; it's
Hermes's own env scrubber dropping SYSTEMROOT / WINDIR / COMSPEC
from the child env. Python's socket module needs SYSTEMROOT to locate
mswsock.dll. Fixed via the _WINDOWS_ESSENTIAL_ENV_VARS allowlist in
tools/code_execution_tool.py. If you still hit it, echo os.environ
inside an execute_code block to confirm SYSTEMROOT is set. Full
diagnostic recipe in references/execute-code-sandbox-env-windows.md.
Testing / Contributing
scripts/run_tests.sh doesn't work as-is on Windows โ it looks for
POSIX venv layouts ( .venv/bin/activate). The Hermes-installed venv at
venv/Scripts/ has no pip or pytest either (stripped for install size).
Workaround: install pytest + pytest-xdist + pyyaml into a system Python
3.11 user site, then invoke pytest directly with PYTHONPATH set:
"/c/Program Files/Python311/python" -m pip install --user pytest pytest-xdist pyyaml
export PYTHONPATH="$(pwd)"
"/c/Program Files/Python311/python" -m pytest tests/foo/test_bar.py -v --tb=short -n 0
Use -n 0, not -n 4 โ pyproject.toml's default addopts already
includes -n, and the wrapper's CI-parity guarantees don't apply off POSIX.
POSIX-only tests need skip guards. Common markers already in the codebase:
- Symlinks โ elevated privileges on Windows
0o600 file modes โ POSIX mode bits not enforced on NTFS by default
signal.SIGALRM โ Unix-only (see tests/conftest.py::_enforce_test_timeout)
- Winsock / Windows-specific regressions โ
@pytest.mark.skipif(sys.platform != "win32", ...)
Use the existing skip-pattern style (sys.platform == "win32" or
sys.platform.startswith("win")) to stay consistent with the rest of the
suite.
Path / Filesystem
Line endings. Git may warn LF will be replaced by CRLF the next time
Git touches it. Cosmetic โ the repo's .gitattributes normalizes. Don't
let editors auto-convert committed POSIX-newline files to CRLF.
Forward slashes work almost everywhere. C:/Users/... is accepted by
every Hermes tool and most Windows APIs. Prefer forward slashes in code
and logs โ avoids shell-escaping backslashes in bash.
---
Troubleshooting
Voice not working
1. Check stt.enabled: true in config.yaml
2. Verify provider: pip install faster-whisper or set API key
3. In gateway: /restart. In CLI: exit and relaunch.
Tool not available
1. hermes tools โ check if toolset is enabled for your platform
2. Some tools need env vars (check .env)
3. /reset after enabling tools
Model/provider issues
1. hermes doctor โ check config and dependencies
2. hermes auth add <provider> โ re-authenticate OAuth providers (use --type oauth)
3. Check .env has the right API key
4. Copilot 403: gh auth login tokens do NOT work for Copilot API. You must use the Copilot-specific OAuth device code flow via hermes model โ GitHub Copilot.
Changes not taking effect
- Tools/skills:
/reset starts a new session with updated toolset
- Config changes: In gateway:
/restart. In CLI: exit and relaunch.
- Code changes: Restart the CLI or gateway process
Deployed web dashboard shows stale CSS or theme changes
- Browser cache: Add
?v=N cache-busting query strings to CSS/JS/theme links in HTML.
- Service Worker cache: Bump
CACHE_NAME in sw.js to invalidate old shell caches.
- Data freshness: Use
fetch(url, {cache:'no-store'}) for live JSON feeds.
- Auto-detection: Embed
data-build in <html> and compare server build vs loaded build on page load to show a "new version available" banner. See references/static-site-cache-invalidation.md for the full diagnostic recipe and auto-detection pattern.
- Theme switcher reliability: If theme switching works in Chrome but not Samsung Internet, or feels broken on mobile, see
references/theme-switcher-reliability.md for the create-new-link โ load โ remove-old pattern.
- Emergency recovery: If a bad deploy breaks the main app JS, users need a standalone reset page. See
references/emergency-reset-page.md for a zero-dependency reset.html that clears Service Workers and caches without relying on the main app's JS.
Dashboard inspector feels too technical
- The default inspector view should contain only plain-language sentences: headline, "what they're doing now", "why it matters", and a silent visual progress bar (no text label).
- Move all technical fields (source IDs, confidence scores, progress labels, status slugs, badges) behind a "Show technical details" toggle.
- If users say "details are hard to understand," the fix is to remove more fields from the default view, not to add explanations. Explanations of technical fields are still technical.
- See
references/progressive-disclosure-human-first.md for the aggressive simplification pattern.
Pixel-art characters look wrong on mobile
- Decorative CSS elements (cheeks, ears, tails, badges) can be misread as facial features or appendages when avatars shrink below ~50 px.
- Hide them inside
@media (max-width:480px) so only the essential silhouette remains.
- See
references/pixel-art-mobile-readability.md for the exact selectors and rationale.
Skills not showing
1. hermes skills list โ verify installed
2. hermes skills config โ check platform enablement
3. Load explicitly: /skill name or hermes -s name
Gateway issues
Check logs first:
grep -i "failed to send\|error" ~/.hermes/logs/gateway.log | tail -20
Common gateway problems:
- Gateway dies on SSH logout: Enable linger:
sudo loginctl enable-linger $USER
- Gateway dies on WSL2 close: WSL2 requires
systemd=true in /etc/wsl.conf for systemd services to work. Without it, gateway falls back to nohup (dies when session closes).
- Gateway crash loop: Reset the failed state:
systemctl --user reset-failed hermes-gateway
- macOS: bot shows offline after idle time: The gateway runs as a user agent (
LimitLoadToSessionType=Aqua), so macOS suspends it when the system sleeps. The platform websocket drops and the bot appears offline until the network returns. Fix: keep the Mac awake (System Settings -> Energy -> Prevent automatic sleeping, or caffeinate -d -i -s -u &). Low Power Mode makes this worse, not better. See references/macos-gateway-sleep-disconnect.md for the full diagnostic recipe.
Platform-specific issues
- Discord bot silent: Must enable Message Content Intent in Bot โ Privileged Gateway Intents. See full Discord setup reference:
references/discord-gateway-setup.md.
- Slack bot only works in DMs: Must subscribe to
message.channels event. Without it, the bot ignores public channels.
- Windows-specific issues (
Alt+Enter newline, WinError 10106, UTF-8 BOM config, test suite, line endings): see the dedicated Windows-Specific Quirks section above.
Auxiliary models not working
If auxiliary tasks (vision, compression, session_search) fail silently, the auto provider can't find a backend. Either set OPENROUTER_API_KEY or GOOGLE_API_KEY, or explicitly configure each auxiliary task's provider:
hermes config set auxiliary.vision.provider <your_provider>
hermes config set auxiliary.vision.model <model_name>
Full system auth provisioning
For a one-shot workflow to maximize available credentials โ installing gh, generating SSH keys, configuring git, enabling all Hermes toolsets, and auditing current auth state โ see references/system-auth-setup.md.
Editing large files with patch
When a file is read with read_file(offset=...) (pagination), the tool warns that the view is partial. If you attempt patch without re-reading the full file first, you will likely hit non-unique match errors or corrupt the file. Fix: always call read_file without offset to load the whole file before patching. The tool explicitly warns: "โฆwas last read with offset/limit pagination (partial view). Re-read the whole file before overwriting it." โ heed this warning. For append-only updates (e.g., adding a cycle log entry to state.md), do not use terminal(command="cat >> file << 'EOF'...EOF") โ the terminal tool on macOS/Linux misinterprets heredoc << as backgrounding and fails. Instead, write a short Python script via write_file and execute it with terminal(command="python3 /tmp/script.py"). See references/terminal-heredoc-workaround.md for the full pattern.
Sibling subagent file overwrites
When multiple subagents are running in parallel (e.g. via delegate_task batch mode or kanban worker lanes), a file may be modified by one subagent while another is about to write to it. If you use write_file or patch on a file that was last read before a sibling subagent modified it, your write may silently truncate or revert the sibling's changes. The tool may show a warning like "this file was modified by sibling subagent X but this agent never read it."
Fix:
1. Heed the warning. If the tool reports a sibling modification, re-read the file with read_file before writing.
2. Prefer patch over write_file for partial updates โ patch only changes the matched region and is less likely to wipe unrelated content.
3. If the file is already published/deployed, and the local working copy gets corrupted, recover from the published copy:
cp ~/hermes-web/agent-pets/css/dashboard.css ~/.hermes/autonomous-agent-lab/pixel-pet-ops/web/css/dashboard.css
4. For append-only updates, write a small Python script and execute it rather than using write_file on the whole file.
Prevention: In kanban/multi-agent workflows, assign file-level ownership so only one worker touches each file. If parallel workers must edit the same file, have them write to separate temp files and let the orchestrator merge.
---
Windows-Specific Quirks
| Looking for... | Location |
|----------------|----------|
| Config options | hermes config edit or [Configuration docs](https://hermes-agent.nousresearch.com/docs/user-guide/configuration) |
| Available tools | hermes tools list or [Tools reference](https://hermes-agent.nousresearch.com/docs/reference/tools-reference) |
| Slash commands | /help in session or [Slash commands reference](https://hermes-agent.nousresearch.com/docs/reference/slash-commands) |
| Skills catalog | hermes skills browse or [Skills catalog](https://hermes-agent.nousresearch.com/docs/reference/skills-catalog) |
| Provider setup | hermes model or [Providers guide](https://hermes-agent.nousresearch.com/docs/integrations/providers) |
| Platform setup | hermes gateway setup or [Messaging docs](https://hermes-agent.nousresearch.com/docs/user-guide/messaging/) |
| MCP servers | hermes mcp list or [MCP guide](https://hermes-agent.nousresearch.com/docs/user-guide/features/mcp) |
| Profiles | hermes profile list or [Profiles docs](https://hermes-agent.nousresearch.com/docs/user-guide/profiles) |
| Cron jobs | hermes cron list or [Cron docs](https://hermes-agent.nousresearch.com/docs/user-guide/features/cron) |
| Memory | hermes memory status or [Memory docs](https://hermes-agent.nousresearch.com/docs/user-guide/features/memory) |
| Env variables | hermes config env-path or [Env vars reference](https://hermes-agent.nousresearch.com/docs/reference/environment-variables) |
| CLI commands | hermes --help or [CLI reference](https://hermes-agent.nousresearch.com/docs/reference/cli-commands) |
| Gateway logs | ~/.hermes/logs/gateway.log |
| Session files | ~/.hermes/sessions/ or hermes sessions browse |
| Source code | ~/.hermes/hermes-agent/ |
---
Contributor Quick Reference
For occasional contributors and PR authors. Full developer docs: https://hermes-agent.nousresearch.com/docs/developer-guide/
Project Layout
hermes-agent/
โโโ run_agent.py # AIAgent โ core conversation loop
โโโ model_tools.py # Tool discovery and dispatch
โโโ toolsets.py # Toolset definitions
โโโ cli.py # Interactive CLI (HermesCLI)
โโโ hermes_state.py # SQLite session store
โโโ agent/ # Prompt builder, context compression, memory, model routing, credential pooling, skill dispatch
โโโ hermes_cli/ # CLI subcommands, config, setup, commands
โ โโโ commands.py # Slash command registry (CommandDef)
โ โโโ config.py # DEFAULT_CONFIG, env var definitions
โ โโโ main.py # CLI entry point and argparse
โโโ tools/ # One file per tool
โ โโโ registry.py # Central tool registry
โโโ gateway/ # Messaging gateway
โ โโโ platforms/ # Platform adapters (telegram, discord, etc.)
โโโ cron/ # Job scheduler
โโโ tests/ # ~3000 pytest tests
โโโ website/ # Docusaurus docs site
Config: ~/.hermes/config.yaml (settings), ~/.hermes/.env (API keys).
Adding a Tool (3 files)
1. Create tools/your_tool.py:
import json, os
from tools.registry import registry
def check_requirements() -> bool:
return bool(os.getenv("EXAMPLE_API_KEY"))
def example_tool(param: str, task_id: str = None) -> str:
return json.dumps({"success": True, "data": "..."})
registry.register(
name="example_tool",
toolset="example",
schema={"name": "example_tool", "description": "...", "parameters": {...}},
handler=lambda args, **kw: example_tool(
param=args.get("param", ""), task_id=kw.get("task_id")),
check_fn=check_requirements,
requires_env=["EXAMPLE_API_KEY"],
)
2. Add to toolsets.py โ _HERMES_CORE_TOOLS list.
Auto-discovery: any tools/*.py file with a top-level registry.register() call is imported automatically โ no manual list needed.
All handlers must return JSON strings. Use get_hermes_home() for paths, never hardcode ~/.hermes.
Adding a Slash Command
1. Add CommandDef to COMMAND_REGISTRY in hermes_cli/commands.py
2. Add handler in cli.py โ process_command()
3. (Optional) Add gateway handler in gateway/run.py
All consumers (help text, autocomplete, Telegram menu, Slack mapping) derive from the central registry automatically.
Agent Loop (High Level)
run_conversation():
1. Build system prompt
2. Loop while iterations < max:
a. Call LLM (OpenAI-format messages + tool schemas)
b. If tool_calls โ dispatch each via handle_function_call() โ append results โ continue
c. If text response โ return
3. Context compression triggers automatically near token limit
Testing
python -m pytest tests/ -o 'addopts=' -q # Full suite
python -m pytest tests/tools/ -q # Specific area
- Tests auto-redirect
HERMES_HOME to temp dirs โ never touch real ~/.hermes/
- Run full suite before pushing any change
- Use
-o 'addopts=' to clear any baked-in pytest flags
Windows contributors: scripts/run_tests.sh currently looks for POSIX venvs ( .venv/bin/activate / venv/bin/activate) and will error out on Windows where the layout is venv/Scripts/activate + python.exe. The Hermes-installed venv at venv/Scripts/ also has no pip or pytest โ it's stripped for end-user install size. Workaround: install pytest + pytest-xdist + pyyaml into a system Python 3.11 user site ( /c/Program Files/Python311/python -m pip install --user pytest pytest-xdist pyyaml), then run tests directly:
export PYTHONPATH="$(pwd)"
"/c/Program Files/Python311/python" -m pytest tests/tools/test_foo.py -v --tb=short -n 0
Use -n 0 (not -n 4) because pyproject.toml's default addopts already includes -n, and the wrapper's CI-parity story doesn't apply off-POSIX.
Cross-platform test guards: tests that use POSIX-only syscalls need a skip marker. Common ones already in the codebase:
- Symlink creation โ
@pytest.mark.skipif(sys.platform == "win32", reason="Symlinks require elevated privileges on Windows") (see tests/cron/test_cron_script.py)
- POSIX file modes (0o600, etc.) โ
@pytest.mark.skipif(sys.platform.startswith("win"), reason="POSIX mode bits not enforced on Windows") (see tests/hermes_cli/test_auth_toctou_file_modes.py)
signal.SIGALRM โ Unix-only (see tests/conftest.py::_enforce_test_timeout)
- Live Winsock / Windows-specific regression tests โ
@pytest.mark.skipif(sys.platform != "win32", reason="Windows-specific regression")
Monkeypatching sys.platform is not enough when the code under test also calls platform.system() / platform.release() / platform.mac_ver(). Those functions re-read the real OS independently, so a test that sets sys.platform = "linux" on a Windows runner will still see platform.system() == "Windows" and route through the Windows branch. Patch all three together:
monkeypatch.setattr(sys, "platform", "linux")
monkeypatch.setattr(platform, "system", lambda: "Linux")
monkeypatch.setattr(platform, "release", lambda: "6.8.0-generic")
See tests/agent/test_prompt_builder.py::TestEnvironmentHints for a worked example.
Extending the system prompt's execution-environment block
Factual guidance about the host OS, user home, cwd, terminal backend, and shell (bash vs. PowerShell on Windows) is emitted from agent/prompt_builder.py::build_environment_hints(). This is also where the WSL hint and per-backend probe logic live. The convention:
- Local terminal backend โ emit host info (OS,
$HOME, cwd) + Windows-specific notes (hostname โ username, terminal uses bash not PowerShell).
- Remote terminal backend (anything in
_REMOTE_TERMINAL_BACKENDS: docker, singularity, modal, daytona, ssh, vercel_sandbox, managed_modal) โ suppress host info entirely and describe only the backend. A live uname/whoami/pwd probe runs inside the backend via tools.environments.get_environment(...).execute(...), cached per process in _BACKEND_PROBE_CACHE, with a static fallback if the probe times out.
- Key fact for prompt authoring: when
TERMINAL_ENV != "local", every file tool (read_file, write_file, patch, search_files) runs inside the backend container, not on the host. The system prompt must never describe the host in that case โ the agent can't touch it.
Full design notes, the exact emitted strings, and testing pitfalls:
references/prompt-builder-environment-hints.md.
Refactor-safety pattern (POSIX-equivalence guard): when you extract inline logic into a helper that adds Windows/platform-specific behavior, keep a _legacy_<name> oracle function in the test file that's a verbatim copy of the old code, then parametrize-diff against it. Example: tests/tools/test_code_execution_windows_env.py::TestPosixEquivalence. This locks in the invariant that POSIX behavior is bit-for-bit identical and makes any future drift fail loudly with a clear diff.
Commit Conventions
type: concise subject line
Optional body.
Types: fix:, feat:, refactor:, docs:, chore:
Key Rules
- Never break prompt caching โ don't change context, tools, or system prompt mid-conversation
- Message role alternation โ never two assistant or two user messages in a row
- Use
get_hermes_home() from hermes_constants for all paths (profile-safe)
- Config values go in
config.yaml, secrets go in .env
- New tools need a
check_fn so they only appear when requirements are met
[IMPORTANT: The user has invoked the "kanban-orchestrator" skill, indicating they want you to follow its instructions. The full skill content is loaded below.]
---
name: kanban-orchestrator
description: Decomposition playbook + anti-temptation rules for an orchestrator profile routing work through Kanban. The "don't do the work yourself" rule and the basic lifecycle are auto-injected into every kanban worker's system prompt; this skill is the deeper playbook when you're specifically playing the orchestrator role.
version: 3.0.0
platforms: [linux, macos, windows]
metadata:
hermes:
tags: [kanban, multi-agent, orchestration, routing]
related_skills: [kanban-worker]
---
Kanban Orchestrator โ Decomposition Playbook
> The core worker lifecycle (including the kanban_create fan-out pattern and the "decompose, don't execute" rule) is auto-injected into every kanban process via the KANBAN_GUIDANCE system-prompt block. This skill is the deeper playbook when you're an orchestrator profile whose whole job is routing.
Profiles are user-configured โ not a fixed roster
Hermes setups vary widely. Some users run a single profile that does everything; some run a small fleet (docker-worker, cron-worker); some run a curated specialist team they've named themselves. There is no default specialist roster โ the orchestrator skill does not know what profiles exist on this machine.
Before fanning out, you must ground the decomposition in the profiles that actually exist. The dispatcher silently fails to spawn unknown assignee names โ it doesn't autocorrect, doesn't suggest, doesn't fall back. So a card assigned to researcher on a setup that only has docker-worker just sits in ready forever.
Step 0: discover available profiles before planning.
Use one of these:
hermes profile list โ prints the table of profiles configured on this machine. Run it through your terminal tool if you have one; otherwise ask the user.
kanban_list(assignee="<some-name>") โ sanity-check a single name. Returns an empty list (rather than an error) for an unknown assignee, so this only confirms a name you're already considering.
- Just ask the user. "What profiles do you have set up?" is a fine first turn when the goal needs more than one specialist.
Cache the result in your working memory for the rest of the conversation. Re-asking every turn wastes a tool call.
When to use the board (vs. just doing the work)
Create Kanban tasks when any of these are true:
1. Multiple specialists are needed. Research + analysis + writing is three profiles.
2. The work should survive a crash or restart. Long-running, recurring, or important.
3. The user might want to interject. Human-in-the-loop at any step.
4. Multiple subtasks can run in parallel. Fan-out for speed.
5. Review / iteration is expected. A reviewer profile loops on drafter output.
6. The audit trail matters. Board rows persist in SQLite forever.
If none of those apply โ it's a small one-shot reasoning task โ use delegate_task instead or answer the user directly.
The anti-temptation rules
Your job description says "route, don't execute." The rules that enforce that:
- Do not execute the work yourself. Your restricted toolset usually doesn't even include terminal/file/code/web for implementation. If you find yourself "just fixing this quickly" โ stop and create a task for the right specialist.
- For any concrete task, create a Kanban task and assign it. Every single time.
- Split multi-lane requests before creating cards. A user prompt can contain several independent workstreams. Extract those lanes first, then create one card per lane instead of bundling unrelated work into a single implementer card.
- Run independent lanes in parallel. If two cards do not need each other's output, leave them unlinked so the dispatcher can fan them out. Link only true data dependencies.
- If no specialist fits the available profiles, ask the user which profile to create or which existing profile to use. Do not invent profile names; the dispatcher will silently drop unknown assignees.
- Decompose, route, and summarize โ that's the whole job.
Exception: micro-UI polish cycles
There is one narrow exception where the orchestrator may execute directly instead of creating Kanban cards: tiny UI-only polish cycles (e.g., adding a CSS class, a theme preview dot, a hover state, a cross-link, or a HUD button) that are purely presentational, require no cross-file logic changes, and fit comfortably inside a single bounded cycle with no need for review or parallel work. If the change is limited to HTML/CSS/JS cosmetics, no other profile has a stake in it, and the user did not ask for a design review, the orchestrator should just edit and publish rather than paying the kanban-overhead tax. This exception does NOT apply to architecture changes, adapter logic, plugin interfaces, or anything that touches the data layer.
Decomposition playbook
Step 1 โ Understand the goal
Ask clarifying questions if the goal is ambiguous. Cheap to ask; expensive to spawn the wrong fleet.
Step 2 โ Sketch the task graph
Before creating anything, draft the graph out loud (in your response to the user). Treat every concrete workstream as a candidate card:
1. Extract the lanes from the request.
2. Map each lane to one of the profiles you discovered in Step 0. If a lane doesn't fit any existing profile, ask the user which to use or create.
3. Decide whether each lane is independent or gated by another lane.
4. Create independent lanes as parallel cards with no parent links.
5. Create synthesis/review/integration cards with parent links to the lanes they depend on.
Examples of prompts that should fan out (using placeholder profile names โ substitute whatever exists on the user's setup):
- "Build an app" โ one card to a design-oriented profile for product/UI direction, one or two cards to engineering profiles for implementation, plus a later integration/review card if the user has a reviewer profile.
- "Fix blockers and check model variants" โ one implementation card for the blocker fixes plus one discovery/research card for config/source verification. A final reviewer card can depend on both.
- "Research docs and implement" โ a docs-research card can run in parallel with a codebase-discovery card; implementation waits only if it truly needs those findings.
- "Analyze this screenshot and find the related code" โ one card to a vision-capable profile for the visual analysis while another searches the codebase.
Words like "also," "finally," or "and" do not automatically imply a dependency. They often mean "make sure this is covered before reporting back." Only link tasks when one card cannot start until another card's output exists.
Show the graph to the user before creating cards. Let them correct it โ including which actual profile name should own each lane.
Step 3 โ Create tasks and link
Use the profile names from Step 0. The example below uses placeholders <profile-A>, <profile-B>, <profile-C> โ replace them with what the user actually has.
t1 = kanban_create(
title="research: Postgres cost vs current",
assignee="<profile-A>", # whichever profile handles research on this setup
body="Compare estimated infrastructure costs, migration costs, and ongoing ops costs over a 3-year window. Sources: AWS/GCP pricing, team time estimates, current Postgres bills from peers.",
tenant=os.environ.get("HERMES_TENANT"),
)["task_id"]
t2 = kanban_create(
title="research: Postgres performance vs current",
assignee="<profile-A>", # same profile, run in parallel
body="Compare query latency, throughput, and scaling characteristics at our expected data volume (~500GB, 10k QPS peak). Sources: benchmark papers, public case studies, pgbench results if easy.",
)["task_id"]
t3 = kanban_create(
title="synthesize migration recommendation",
assignee="<profile-B>", # whichever profile does synthesis/analysis
body="Read the findings from T1 (cost) and T2 (performance). Produce a 1-page recommendation with explicit trade-offs and a go/no-go call.",
parents=[t1, t2],
)["task_id"]
t4 = kanban_create(
title="draft decision memo",
assignee="<profile-C>", # whichever profile drafts user-facing prose
body="Turn the analyst's recommendation into a 2-page memo for the CTO. Match the tone of previous decision memos in the team's knowledge base.",
parents=[t3],
)["task_id"]
parents=[...] gates promotion โ children stay in todo until every parent reaches done, then auto-promote to ready. No manual coordination needed; the dispatcher and dependency engine handle it.
Step 4 โ Complete your own task
If you were spawned as a task yourself (e.g. a planner profile was assigned T0: "investigate Postgres migration"), mark it done with a summary of what you created:
kanban_complete(
summary="decomposed into T1-T4: 2 research lanes in parallel, 1 synthesis on their outputs, 1 prose draft on the recommendation",
metadata={
"task_graph": {
"T1": {"assignee": "<profile-A>", "parents": []},
"T2": {"assignee": "<profile-A>", "parents": []},
"T3": {"assignee": "<profile-B>", "parents": ["T1", "T2"]},
"T4": {"assignee": "<profile-C>", "parents": ["T3"]},
},
},
)
Step 5 โ Report back to the user
Tell them what you created in plain prose, naming the actual profiles you used:
> I've queued 4 tasks:
> - T1 (<profile-A>): cost comparison
> - T2 (<profile-A>): performance comparison, in parallel with T1
> - T3 (<profile-B>): synthesizes T1 + T2 into a recommendation
> - T4 (<profile-C>): turns T3 into a CTO memo
>
> The dispatcher will pick up T1 and T2 now. T3 starts when both finish. You'll get a gateway ping when T4 completes. Use the dashboard or hermes kanban tail <id> to follow along.
Common patterns
Fan-out + fan-in (research โ synthesize): N research-style cards with no parents, one synthesis card with all of them as parents.
Parallel implementation + validation: one implementer card makes the change while one explorer/researcher card verifies config, docs, or source mapping. A reviewer card can depend on both. Do not make the implementer own unrelated verification just because the user mentioned both in one sentence.
Pipeline with gates: planner โ implementer โ reviewer. Each stage's parents=[previous_task]. Reviewer blocks or completes; if reviewer blocks, the operator unblocks with feedback and respawns.
Same-profile queue: N tasks, all assigned to the same profile, no dependencies between them. Dispatcher serializes โ that profile processes them in priority order, accumulating experience in its own memory.
Parallel UI/frontend lanes: When the goal touches multiple independent HTML/CSS/JS files (e.g., a dashboard page and a 2D gather view), fan out to separate subagents per file. Each lane edits its own file, then the orchestrator integrates, fixes cross-file references (theme paths, shared JSON endpoints), and publishes. This avoids merge conflicts in single-file HTML dashboards and keeps each subagent's context focused. See references/parallel-ui-lanes-and-publishing.md for the post-subagent integration checklist and rsync safety notes.
Human-in-the-loop: Any task can kanban_block() to wait for input. Dispatcher respawns after /unblock. The comment thread carries the full context.
Pitfalls
Inventing profile names that don't exist. The dispatcher silently fails to spawn unknown assignees โ the card just sits in ready forever. Always assign to a profile from your Step 0 discovery; ask the user if you're unsure.
Bundling independent lanes into one card. If the user asks for two independent outcomes, create two cards. Example: "fix blockers and check model variants" is not one fixer task; create a fixer/engineer card for the fixes and an explorer/researcher card for the variant check, then optionally gate review on both.
Over-linking because of wording. "Finally check X" may still be parallel with implementation if X is static config, docs, or source discovery. Link it after implementation only when the check depends on the implementation result.
Forgetting dependency links. If the task graph says research -> implement -> review, do not create all tasks as independent ready cards. Use parent links so implement/review cannot run before their inputs exist.
Reassignment vs. new task. If a reviewer blocks with "needs changes," create a NEW task linked from the reviewer's task โ don't re-run the same task with a stern look. The new task is assigned to the original implementer profile.
Argument order for links. kanban_link(parent_id=..., child_id=...) โ parent first. Mixing them up demotes the wrong task to todo.
Ignoring explicit user feedback to keep building infrastructure. When the user says a specific UX issue (legibility, theme switching, movement density) is "immediate priority," treat it as P0 and route it before deeper packaging/architecture work. Infrastructure polish feels productive, but shipping user-visible fixes is what matters. Create cards for the UX feedback first, then resume infrastructure lanes.
Treating status: complete as immutable when user feedback says otherwise. A state.md that says status: complete does not override a user's report that a completion criterion is actually broken. If the user says "theme switching is not working" and the Final Completion Condition requires "working UI theme switcher," the mission is not complete. Reactivate immediately: set status: active, append a reactivation cycle log, and fix the issue. Do not burn cycles on post-complete verification while the user is reporting active defects.
Don't pre-create the whole graph if the shape depends on intermediate findings. If T3's structure depends on what T1 and T2 find, let T3 exist as a "synthesize findings" task whose own first step is to read parent handoffs and plan the rest. Orchestrators can spawn orchestrators.
Tenant inheritance. If HERMES_TENANT is set in your env, pass tenant=os.environ.get("HERMES_TENANT") on every kanban_create call so child tasks stay in the same namespace.
Verifying cross-file references after directory reorganization. When subagents edit HTML/CSS/JS files and the directory structure shifts (e.g., moving files from root into web/dashboard/ and web/gather/), relative asset paths ( themes/default/theme.css, ./ops-data.json) often break. After subagents finish, the orchestrator must grep for href= and src= in moved files and fix relative paths before publishing. Subagents don't know the final publish layout โ the orchestrator does.
Destructive sync wipes needed files. Commands like rsync -av --delete will delete destination files that aren't in the source list. If you publish a directory tree piecemeal (e.g., copy web/dashboard/ first, then web/gather/ separately), --delete on the first rsync will erase the gather files before the second rsync runs. Either list all source paths in a single rsync invocation, or omit --delete and use cp -r / rsync -av without deletion when doing staged copies.
Recovering stuck workers
When a worker profile keeps crashing, hallucinating, or getting blocked by its own mistakes (usually: wrong model, missing skill, broken credential), the kanban dashboard flags the task with a โ badge and opens a Recovery section in the drawer. Three primary actions:
1. Reclaim (or hermes kanban reclaim <task_id>) โ abort the running worker immediately and reset the task to ready. The existing claim TTL is ~15 min; this is the fast path out.
2. Reassign (or hermes kanban reassign <task_id> <new-profile> --reclaim) โ switch the task to a different profile (one that exists on this setup) and let the dispatcher pick it up with a fresh worker.
3. Change profile model โ the dashboard prints a copy-paste hint for hermes -p <profile> model since profile config lives on disk; edit it in a terminal, then Reclaim to retry with the new model.
Hallucination warnings appear on tasks where a worker's kanban_complete(created_cards=[...]) claim included card ids that don't exist or weren't created by the worker's profile (the gate blocks the completion), or where the free-form summary references t_<hex> ids that don't resolve (advisory prose scan, non-blocking). Both produce audit events that persist even after recovery actions โ the trail stays for debugging.
The user has provided the following instruction alongside the skill invocation: [IMPORTANT: You are running as a scheduled cron job. DELIVERY: Your final response will be automatically delivered to the user โ do NOT use send_message or try to deliver the output yourself. Just produce your report/output as your final response and the system handles the rest. SILENT: If there is genuinely nothing new to report, respond with exactly "[SILENT]" (nothing else) to suppress delivery. Never combine [SILENT] with content โ either report your findings normally, or say [SILENT] and nothing more.]
You are the 15-minute Orchestrator for Son's Autonomous Agent Lab v1, reporting to Discord channel ID 1505805763824586952.
Durable state path: /Users/jooho-hermes/.hermes/autonomous-agent-lab/state.md
Working directory for experiment artifacts: /Users/jooho-hermes/.hermes/autonomous-agent-lab/
Preferred published web root: /Users/jooho-hermes/hermes-web/agent-pets/
Top-level directive from Son:
- The project has evolved from a personal dashboard into an INSTALLABLE PRODUCT that external Hermes users can deploy.
- The final target is a self-contained, configurable, publishable solution: "Hermes Pixel Pet Ops Office".
- Do NOT shrink the mission into a small static MVP and autonomously stop.
- The Gather.town-style 2D spatial office is a first-class feature, not a side page.
Latest UX feedback from Son (treat as immediate priority before deeper packaging work):
- Details are hard for a human to understand. Add human-first summaries, plain-language labels, and progressive disclosure: summary first, technical details second.
- Gather Town version has too many agents roaming around. Reduce default movement, add density/speed controls, cluster agents by room/task, and add focus/calm mode.
- Theme switching is not visibly working. Implement real UI theme switcher with persistence and clear visual theme changes.
Key product requirements (installable solution level):
1. Config-driven architecture: all paths, URLs, colors, names, room layouts via config.yaml. No hardcoded references to jooho-hermes.
2. Self-contained package: clear directory structure (src/, web/, config/, docs/, scripts/), install script, requirements.txt.
3. Pluggable data adapter: support multiple backends via plugin architecture.
4. Themeable frontend: CSS variables driven from config, swappable themes, plus a working UI theme switcher.
5. Multi-tenant ready: works for any Hermes instance.
6. Build/Deploy ready: Dockerfile or docker-compose, or clear static-server setup.
7. Documentation: README, architecture docs, configuration reference, contributor guide.
8. Human-comprehensible UX: plain-language summaries and progressive disclosure for technical detail.
9. Gather.town calm mode: adjustable movement density/speed and less chaotic defaults.
10. Versioned releases: CHANGELOG.md, semantic versioning, release packaging.
Mission model:
- Read state.md first before doing anything else.
- If state.md says
status: inactive or has no Current Mission, do not invent work. Return exactly: ๐ก Autonomous Agent Lab ๋๊ธฐ์ค โ Son์ด ํธ๋ฆฌ๊ฑฐ/๋ฏธ์
์ ์ฃผ๋ฉด 15๋ถ ์ฌ์ดํด์ ์์ํฉ๋๋ค.
- If state.md says
status: active, run one bounded 15-minute cycle toward the full installable solution.
- If state.md says
status: complete, verify that the Final Completion Condition in state.md is truly met. If it is not fully met, reactivate or report that state needs correction.
Cycle procedure when active:
1. Read state.md first. Extract current mission, constraints, previous cycle log, and Final Completion Condition.
2. Decide the next smallest useful step toward installable solution quality. Focus on: architecture, configurability, documentation, and clean separation of concerns.
3. Use delegate_task for independent subagent lanes when helpful.
4. Prefer concrete progress: refactor to config-driven, add install scripts, create docs, add Docker support, theme system, plugin architecture.
5. Update state.md with a new cycle log entry before final reporting.
6. Completion rule: only set status: complete when every item under state.md Final Completion Condition is satisfied. A non-installable MVP is not complete.
7. Stop/block only if Son explicitly stops/redirects, a safety boundary is reached, or a hard blocker needs Son's decision.
Link requirement (never forget):
- Every cycle report MUST include at least one direct viewable link to the published dashboard/artifact.
- The canonical URL:
http://hermes-mac-mini.tail46b3c6.ts.net:8099/agent-pets/
- Include gather town URL too:
http://hermes-mac-mini.tail46b3c6.ts.net:8099/agent-pets/gather/
Final Discord message format:
[Autonomous Agent Lab v1 / Cycle N]
๋ชฉํ:
์ํ:
๊ฒฐ๊ณผ:
๊ฒ์ฆ:
๋ค์:
์ํ:
Safety/quality rules:
- Do not handle secrets, passwords, API keys, payment, permission dialogs, or destructive commands.
- Do not claim completion without updating state.md.
- Do not rely on Discord history as durable state.
- Do not spam raw logs; summarize lane outputs and verification.
- Keep working in /Users/jooho-hermes/.hermes/autonomous-agent-lab/ and publish only to /Users/jooho-hermes/hermes-web/agent-pets/ unless the state file says otherwise.
Design/UX priorities:
- Mobile responsiveness is first-class.
- Character animation/movement is desired.
- Every cycle report must include published links.
- This is now a product engineering mission. Architecture, configurability, and documentation matter as much as visuals.
Response
[Autonomous Agent Lab v1 / Cycle 71]
๋ชฉํ:
์๋ ๋ฐ์ดํฐ ๋ณด์กด(data retention) ๋ฐ ์ด๋ ฅ ์ ๋ฆฌ(pruning)๋ฅผ ์ถ๊ฐํ์ฌ ์ฅ๊ธฐ ์ด์ ์ SQLite DB๊ฐ ๋ฌดํ ์ฆ๊ฐํ์ง ์๋๋ก ๊ฐ์ ํฉ๋๋ค.
์ํ:
1. src/server/history_db.py์ prune_history() ์ถ๊ฐ โ 7์ผ ์ด์ ๊ธฐ๋ก ์ญ์ , ์ํ ๋ณ๊ฒฝ 5,000๊ฑด/๋ฉํธ๋ฆญ 5,000๊ฑด ์ด๊ณผ ์ ์ค๋๋ ๊ฒ ์ ๋ฆฌ, VACUUM์ผ๋ก ๋์คํฌ ๊ณต๊ฐ ํ์
2. config.yaml์ data_retention ์น์
์ถ๊ฐ โ max_history_days, max_status_changes, max_metrics_snapshots, auto_prune ์ค์
3. src/adapter/generate_ops_data.py์ ์ ๋ฆฌ ๋ก์ง ์ฐ๋ โ ์ด๋ํฐ ์คํ ์ ์๋ ์ ๋ฆฌ ํ ์ ๋ฐ์ดํฐ ๊ธฐ๋ก
4. ์ฒซ ์คํ์ผ๋ก 46,751๊ฑด์ ์ค๋๋ ์ํ ๋ณ๊ฒฝ ๊ธฐ๋ก ์ญ์ ๋ฐ DB ํฌ๊ธฐ 9.7MB โ 1.0MB๋ก ์ถ์
5. ํตํฉ ํ
์คํธ(128/128), ์ค์ ๊ฒ์ฆ(21/21), publish.sh ๋ฐฐํฌ ์๋ฃ
๊ฒฐ๊ณผ:
- ์ฅ๊ธฐ ๋ฐฐํฌ ํ๊ฒฝ์์๋ history.db๊ฐ ์ค์ ๊ฐ ๋ด์์ ์๋ ๊ด๋ฆฌ๋จ
- ๋ฐ์ดํฐ๋ฒ ์ด์ค ํฌ๊ธฐ 90% ๊ฐ์ (9.7MB โ 1.0MB)
- ์ค์ ๊ธฐ๋ฐ์ผ๋ก ์ธ๋ถ ์ฌ์ฉ์๊ฐ ๋ณด์กด ๊ธฐ๊ฐ ์กฐ์ ๊ฐ๋ฅ
- ๋ชจ๋ ๊ฒ์ ์์ฐ ์ต์ ์ํ ์ ์ง
๊ฒ์ฆ:
- Integration tests: 128 passed, 0 failed
- Setup validation: 21 passed, 0 warned, 0 critical
- Adapter: exit 0, 32 agents, 15 cron, 20 sessions, 16 events, schema 1.4
ops-data.json / health.json mtime fresh (< 60s)
refresh.err.log empty
- DB size after VACUUM: 1.0 MB
๋ค์:
- Son์ ๋ธ๋ผ์ฐ์ ํ์ธ ๋๊ธฐ ์ค (ํ
๋ง ์ ํ, Gather calm mode, human-first inspector)
- ํ์ธ ์๋ฃ ์
status: complete ์ ํ ๊ฒํ
- ์ ํ์ : ์ธ๋ถ ์ฌ์ฉ์์ฉ
scripts/prune-history.sh ์๋ ์ ํธ๋ฆฌํฐ ์ถ๊ฐ
์ํ: active โ ๋ชจ๋ 11๊ฐ ์ต์ข
์๋ฃ ์กฐ๊ฑด ์ถฉ์กฑ, Cycle 71 ์๋ฃ, Son ํ์ธ ๋๊ธฐ
Dashboard: http://hermes-mac-mini.tail46b3c6.ts.net:8099/agent-pets/
Gather Town: http://hermes-mac-mini.tail46b3c6.ts.net:8099/agent-pets/gather/
|
| 2026-05-19 21-02-37 |
82,967 chars |
2026-05-19_21-02-37.md |
Cron Job: autonomous-agent-lab-v1-orchestrator
Job ID: 35127ff89556
Run Time: 2026-05-19 21:02:37
Schedule: every 15m
Prompt
[IMPORTANT: The user has invoked the "hermes-agent" skill, indicating they want you to follow its instructions. The full skill content is loaded below.]
---
name: hermes-agent
description: "Configure, extend, or contribute to Hermes Agent."
version: 2.1.0
author: Hermes Agent + Teknium
license: MIT
platforms: [linux, macos, windows]
metadata:
hermes:
tags: [hermes, setup, configuration, multi-agent, spawning, cli, gateway, development]
homepage: https://github.com/NousResearch/hermes-agent
related_skills: [claude-code, codex, opencode]
---
Hermes Agent
Hermes Agent is an open-source AI agent framework by Nous Research that runs in your terminal, messaging platforms, and IDEs. It belongs to the same category as Claude Code (Anthropic), Codex (OpenAI), and OpenClaw โ autonomous coding and task-execution agents that use tool calling to interact with your system. Hermes works with any LLM provider (OpenRouter, Anthropic, OpenAI, DeepSeek, local models, and 15+ others) and runs on Linux, macOS, and WSL.
What makes Hermes different:
- Self-improving through skills โ Hermes learns from experience by saving reusable procedures as skills. When it solves a complex problem, discovers a workflow, or gets corrected, it can persist that knowledge as a skill document that loads into future sessions. Skills accumulate over time, making the agent better at your specific tasks and environment.
- Persistent memory across sessions โ remembers who you are, your preferences, environment details, and lessons learned. Pluggable memory backends (built-in, Honcho, Mem0, and more) let you choose how memory works.
- Multi-platform gateway โ the same agent runs on Telegram, Discord, Slack, WhatsApp, Signal, Matrix, Email, and 10+ other platforms with full tool access, not just chat.
- Provider-agnostic โ swap models and providers mid-workflow without changing anything else. Credential pools rotate across multiple API keys automatically.
- Profiles โ run multiple independent Hermes instances with isolated configs, sessions, skills, and memory.
- Extensible โ plugins, MCP servers, custom tools, webhook triggers, cron scheduling, and the full Python ecosystem.
People use Hermes for software development, research, system administration, data analysis, content creation, home automation, and anything else that benefits from an AI agent with persistent context and full system access.
This skill helps you work with Hermes Agent effectively โ setting it up, configuring features, spawning additional agent instances, troubleshooting issues, finding the right commands and settings, and understanding how the system works when you need to extend or contribute to it.
Docs: https://hermes-agent.nousresearch.com/docs/
Quick Start
Install
curl -fsSL https://raw.githubusercontent.com/NousResearch/hermes-agent/main/scripts/install.sh | bash
Interactive chat (default)
hermes
Single query
hermes chat -q "What is the capital of France?"
Setup wizard
hermes setup
Change model/provider
hermes model
Check health
hermes doctor
---
CLI Reference
Global Flags
hermes [flags] [command]
--version, -V Show version
--resume, -r SESSION Resume session by ID or title
--continue, -c [NAME] Resume by name, or most recent session
--worktree, -w Isolated git worktree mode (parallel agents)
--skills, -s SKILL Preload skills (comma-separate or repeat)
--profile, -p NAME Use a named profile
--yolo Skip dangerous command approval
--pass-session-id Include session ID in system prompt
No subcommand defaults to chat.
Chat
hermes chat [flags]
-q, --query TEXT Single query, non-interactive
-m, --model MODEL Model (e.g. anthropic/claude-sonnet-4)
-t, --toolsets LIST Comma-separated toolsets
--provider PROVIDER Force provider (openrouter, anthropic, nous, etc.)
-v, --verbose Verbose output
-Q, --quiet Suppress banner, spinner, tool previews
--checkpoints Enable filesystem checkpoints (/rollback)
--source TAG Session source tag (default: cli)
Configuration
hermes setup [section] Interactive wizard (model|terminal|gateway|tools|agent)
hermes model Interactive model/provider picker
hermes config View current config
hermes config edit Open config.yaml in $EDITOR
hermes config set KEY VAL Set a config value
hermes config path Print config.yaml path
hermes config env-path Print .env path
hermes config check Check for missing/outdated config
hermes config migrate Update config with new options
hermes doctor [--fix] Check dependencies and config
Credential Pools
hermes auth add Interactive credential wizard (oauth, api-key)
hermes auth list [PROVIDER] List pooled credentials
hermes auth remove P INDEX Remove by provider + index
hermes auth reset PROVIDER Clear exhaustion status
hermes logout Clear stored auth
Tools & Skills
hermes tools Interactive tool enable/disable (curses UI)
hermes tools list Show all tools and status
hermes tools enable NAME Enable a toolset
hermes tools disable NAME Disable a toolset
hermes skills list List installed skills
hermes skills search QUERY Search the skills hub
hermes skills install ID Install a skill (ID can be a hub identifier OR a direct https://โฆ/SKILL.md URL; pass --name to override when frontmatter has no name)
hermes skills inspect ID Preview without installing
hermes skills config Enable/disable skills per platform
hermes skills check Check for updates
hermes skills update Update outdated skills
hermes skills uninstall N Remove a hub skill
hermes skills publish PATH Publish to registry
hermes skills browse Browse all available skills
hermes skills tap add REPO Add a GitHub repo as skill source
MCP Servers
hermes mcp serve Run Hermes as an MCP server
hermes mcp add NAME Add an MCP server (--url or --command)
hermes mcp remove NAME Remove an MCP server
hermes mcp list List configured servers
hermes mcp test NAME Test connection
hermes mcp configure NAME Toggle tool selection
Gateway (Messaging Platforms)
hermes gateway run Start gateway foreground
hermes gateway install Install as background service
hermes gateway start/stop Control the service
hermes gateway restart Restart the service
hermes gateway status Check status
hermes gateway setup Configure platforms
Supported platforms: Telegram, Discord, Slack, WhatsApp, Signal, Email, SMS, Matrix, Mattermost, Home Assistant, DingTalk, Feishu, WeCom, BlueBubbles (iMessage), Weixin (WeChat), API Server, Webhooks. Open WebUI connects via the API Server adapter.
Platform docs: https://hermes-agent.nousresearch.com/docs/user-guide/messaging/
Discord-specific walkthrough (token, intents, service install, access control): see references/discord-gateway-setup.md in this skill.
- Per-channel personas and skill bindings: see
references/gateway-channel-personas.md (works on Discord, Slack, Telegram, Mattermost, Matrix).
- For long-running Discord-first operations, purpose-specific channel routing, periodic summaries, weekly Dreaming/audit reports, and log-safety patterns: see
references/discord-operating-planes.md.
- For broad Hermes/LifeOS/SQAF ecosystem audits (cron inventory, live services, dashboards, provider/model warnings, and control-plane gaps), see
references/ecosystem-audit.md.
Sessions
hermes sessions list List recent sessions
hermes sessions browse Interactive picker
hermes sessions export OUT Export to JSONL
hermes sessions rename ID T Rename a session
hermes sessions delete ID Delete a session
hermes sessions prune Clean up old sessions (--older-than N days)
hermes sessions stats Session store statistics
For browser-based viewing of existing Hermes CLI/Discord/cron session transcripts, prefer a lightweight static export from ~/.hermes/state.db into a private web root instead of assuming Open WebUI can browse Hermes' native session store. See references/hermes-session-static-web-viewer.md for the SQLite schema, static HTML export workflow, redaction/truncation cautions, and the user's Mac mini deployment (/hermes-sessions/ under the Tailscale-only ~/hermes-web site).
For cron job execution history, the same static-export pattern applies to ~/.hermes/cron/jobs.json and ~/.hermes/cron/output/{job_id}/*.md. See references/cron-history-web-viewer.md for the cron data model, schedule-dict pitfall, and the user's deployed /cron-history/ dashboard.
Cron Jobs
hermes cron list List jobs (--all for disabled)
hermes cron create SCHED Create: '30m', 'every 2h', '0 9 *'
hermes cron edit ID Edit schedule, prompt, delivery
hermes cron pause/resume ID Control job state
hermes cron run ID Trigger on next tick
hermes cron remove ID Delete a job
hermes cron status Scheduler status
For bounded autonomous lab/orchestrator cron jobs that use file-based state, subagent lanes, artifact publishing, and status transitions (active โ complete/blocked/inactive), see references/autonomous-agent-lab-cron-cycle.md. A reusable verification script template lives at scripts/verify-completion-template.py.
For a worked example of evolving an autonomous lab into a config-driven, themeable, Docker-ready installable product, see references/autonomous-lab-product-architecture.md. For CI, integration testing, pluggable adapter architecture, bounded cycle orchestration, and post-productization patterns, see references/product-maturity-patterns.md.
For the final completion verification checklist โ the explicit audit pattern to run before marking status: complete on an installable-solution mission, see references/autonomous-lab-completion-verification.md.
For the reactivation protocol when a completed lab receives new P0 feedback or the user contradicts a completion claim, see references/autonomous-lab-reactivation-protocol.md.
For the config/CHANGELOG version drift pitfall that occurs when autonomous labs evolve over many cycles, and for the related source vs. published file drift problem where the live web root diverges from the project source, see references/autonomous-lab-version-drift.md.
For adding historical trend tracking (SQLite-backed agent status transitions + vanilla JS SVG sparklines) to an autonomous lab dashboard, see references/history-tracking-sparkline-pattern.md.
For reusable dashboard UX patterns (onboarding tours, data freshness badges, keyboard shortcuts, progressive disclosure inspectors, cross-linking between views), see references/dashboard-ux-patterns.md.
For the aggressive human-first inspector refinement โ when users report that details are hard to understand and the fix is to strip technical labels from the default view โ see references/progressive-disclosure-human-first.md.
For programmatic verification of CSS custom-property theme systems โ catching scoping bugs, confirming theme distinctness, and validating JS switching logic โ see references/theme-system-verification.md.
- For Son's Discord-first autonomous experiments where a channel hosts a repeated multi-agent loop, use the Autonomous Discord Agent Lab pattern: create file-based durable state, a paused cron orchestrator delivered to
discord:<channel_id>, then activate it from a user mission trigger. See references/autonomous-discord-agent-lab.md.
- For verifying that a release package (
tar.gz) is actually installable by third parties and contains no stale artifacts or hardcoded references, see references/release-package-verification.md and the reusable script at scripts/release-verify.sh.
Webhooks
hermes webhook subscribe N Create route at /webhooks/<name>
hermes webhook list List subscriptions
hermes webhook remove NAME Remove a subscription
hermes webhook test NAME Send a test POST
Profiles
hermes profile list List all profiles
hermes profile create NAME Create (--clone, --clone-all, --clone-from)
hermes profile use NAME Set sticky default
hermes profile delete NAME Delete a profile
hermes profile show NAME Show details
hermes profile alias NAME Manage wrapper scripts
hermes profile rename A B Rename a profile
hermes profile export NAME Export to tar.gz
hermes profile import FILE Import from archive
Credential Pools
hermes auth add Interactive credential wizard
hermes auth list [PROVIDER] List pooled credentials
hermes auth remove P INDEX Remove by provider + index
hermes auth reset PROVIDER Clear exhaustion status
Other
hermes insights [--days N] Usage analytics
hermes update Update to latest version
hermes pairing list/approve/revoke DM authorization
hermes plugins list/install/remove Plugin management
hermes honcho setup/status Honcho memory integration (requires honcho plugin)
hermes memory setup/status/off Memory provider config
hermes completion bash|zsh Shell completions
hermes acp ACP server (IDE integration)
hermes claw migrate Migrate from OpenClaw
hermes uninstall Uninstall Hermes
---
Slash Commands (In-Session)
Type these during an interactive chat session. New commands land fairly
often; if something below looks stale, run /help in-session for the
authoritative list or see the [live slash commands reference](https://hermes-agent.nousresearch.com/docs/reference/slash-commands).
The registry of record is hermes_cli/commands.py โ every consumer
(autocomplete, Telegram menu, Slack mapping, /help) derives from it.
Session Control
/new (/reset) Fresh session
/clear Clear screen + new session (CLI)
/retry Resend last message
/undo Remove last exchange
/title [name] Name the session
/compress Manually compress context
/stop Kill background processes
/rollback [N] Restore filesystem checkpoint
/snapshot [sub] Create or restore state snapshots of Hermes config/state (CLI)
/background <prompt> Run prompt in background
/queue <prompt> Queue for next turn
/steer <prompt> Inject a message after the next tool call without interrupting
/agents (/tasks) Show active agents and running tasks
/resume [name] Resume a named session
/goal [text|sub] Set a standing goal Hermes works on across turns until achieved
(subcommands: status, pause, resume, clear)
/redraw Force a full UI repaint (CLI)
Configuration
/config Show config (CLI)
/model [name] Show or change model
/personality [name] Set personality
/reasoning [level] Set reasoning (none|minimal|low|medium|high|xhigh|show|hide)
/verbose Cycle: off โ new โ all โ verbose
/voice [on|off|tts] Voice mode
/yolo Toggle approval bypass
/busy [sub] Control what Enter does while Hermes is working (CLI)
(subcommands: queue, steer, interrupt, status)
/indicator [style] Pick the TUI busy-indicator style (CLI)
(styles: kaomoji, emoji, unicode, ascii)
/footer [on|off] Toggle gateway runtime-metadata footer on final replies
/skin [name] Change theme (CLI)
/statusbar Toggle status bar (CLI)
Tools & Skills
/tools Manage tools (CLI)
/toolsets List toolsets (CLI)
/skills Search/install skills (CLI)
/skill <name> Load a skill into session
/reload-skills Re-scan ~/.hermes/skills/ for added/removed skills
/reload Reload .env variables into the running session (CLI)
/reload-mcp Reload MCP servers
/cron Manage cron jobs (CLI)
/curator [sub] Background skill maintenance (status, run, pin, archive, โฆ)
/kanban [sub] Multi-profile collaboration board (tasks, links, comments)
/plugins List plugins (CLI)
Gateway
/approve Approve a pending command (gateway)
/deny Deny a pending command (gateway)
/restart Restart gateway (gateway)
/sethome Set current chat as home channel (gateway)
/update Update Hermes to latest (gateway)
/topic [sub] Enable or inspect Telegram DM topic sessions (gateway)
/platforms (/gateway) Show platform connection status (gateway)
Utility
/branch (/fork) Branch the current session
/fast Toggle priority/fast processing
/browser Open CDP browser connection
/history Show conversation history (CLI)
/save Save conversation to file (CLI)
/copy [N] Copy the last assistant response to clipboard (CLI)
/paste Attach clipboard image (CLI)
/image Attach local image file (CLI)
Info
/help Show commands
/commands [page] Browse all commands (gateway)
/usage Token usage
/insights [days] Usage analytics
/gquota Show Google Gemini Code Assist quota usage (CLI)
/status Session info (gateway)
/profile Active profile info
/debug Upload debug report (system info + logs) and get shareable links
Exit
/quit (/exit, /q) Exit CLI
---
Key Paths & Config
~/.hermes/config.yaml Main configuration
~/.hermes/.env API keys and secrets
$HERMES_HOME/skills/ Installed skills
~/.hermes/sessions/ Session transcripts
~/.hermes/logs/ Gateway and error logs
~/.hermes/auth.json OAuth tokens and credential pools
~/.hermes/hermes-agent/ Source code (if git-installed)
Profiles use ~/.hermes/profiles/<name>/ with the same layout.
Config Sections
Edit with hermes config edit or hermes config set section.key value.
| Section | Key options |
|---------|-------------|
| model | default, provider, base_url, api_key, context_length |
| agent | max_turns (90), tool_use_enforcement |
| terminal | backend (local/docker/ssh/modal), cwd, timeout (180) |
| compression | enabled, threshold (0.50), target_ratio (0.20) |
| display | skin, tool_progress, show_reasoning, show_cost |
| stt | enabled, provider (local/groq/openai/mistral) |
| tts | provider (edge/elevenlabs/openai/minimax/mistral/neutts) |
| memory | memory_enabled, user_profile_enabled, provider |
| security | tirith_enabled, website_blocklist |
| delegation | model, provider, base_url, api_key, max_iterations (50), reasoning_effort |
| checkpoints | enabled, max_snapshots (50) |
| fallback_model | provider, model, base_url, key_env |
Fallback Providers
Hermes can automatically fail over to a backup provider:model when the primary is unavailable. This is turn-scoped โ each new user message starts with the primary restored; fallback only activates mid-turn when the primary fails.
Configuration ( ~/.hermes/config.yaml):
fallback_model:
provider: opencode-go
model: kimi-k2.6
Or use the interactive manager:
hermes fallback add # interactive picker
hermes fallback list # show fallback chain
hermes fallback remove # remove by index
Legacy note: fallback_model (singular) is the legacy single-fallback key. fallback_providers (list) supports multiple ordered fallbacks. When both exist, fallback_providers takes priority.
Trigger conditions (after exhausting retries where applicable):
- Rate limits (HTTP 429)
- Server errors (HTTP 500, 502, 503)
- Auth failures (HTTP 401, 403) โ immediately
- Not found (HTTP 404) โ immediately
- Invalid / empty responses repeatedly
Supported providers include all standard providers (OpenRouter, Anthropic, OpenCode Go/ Zen, Kimi, etc.) plus custom endpoints with base_url + key_env. Full provider docs: https://hermes-agent.nousresearch.com/docs/integrations/providers
Limitations:
- Subagent delegation does not inherit fallback config
- Cron jobs do not use fallback (use per-job provider/model overrides)
- Auxiliary tasks (vision, compression, etc.) use their own
auxiliary.* provider chain
For a deep-dive with worked examples and model lists, see references/fallback-providers.md.
Full config reference: https://hermes-agent.nousresearch.com/docs/user-guide/configuration
Providers
20+ providers supported. Set via hermes model or hermes setup.
| Provider | Auth | Key env var |
|----------|------|-------------|
| OpenRouter | API key | OPENROUTER_API_KEY |
| Anthropic | API key | ANTHROPIC_API_KEY |
| Nous Portal | OAuth | hermes auth |
| OpenAI Codex | OAuth | hermes auth |
| GitHub Copilot | Token | COPILOT_GITHUB_TOKEN |
| Google Gemini | API key | GOOGLE_API_KEY or GEMINI_API_KEY |
| DeepSeek | API key | DEEPSEEK_API_KEY |
| xAI / Grok | API key | XAI_API_KEY |
| Hugging Face | Token | HF_TOKEN |
| Z.AI / GLM | API key | GLM_API_KEY |
| MiniMax | API key | MINIMAX_API_KEY |
| MiniMax CN | API key | MINIMAX_CN_API_KEY |
| Kimi / Moonshot | API key | KIMI_API_KEY |
| Alibaba / DashScope | API key | DASHSCOPE_API_KEY |
| Xiaomi MiMo | API key | XIAOMI_API_KEY |
| Kilo Code | API key | KILOCODE_API_KEY |
| AI Gateway (Vercel) | API key | AI_GATEWAY_API_KEY |
| OpenCode Zen | API key | OPENCODE_ZEN_API_KEY |
| OpenCode Go | API key | OPENCODE_GO_API_KEY |
| Qwen OAuth | OAuth | hermes auth add qwen-oauth |
| Custom endpoint | Config | model.base_url + model.api_key in config.yaml |
| GitHub Copilot ACP | External | COPILOT_CLI_PATH or Copilot CLI |
Full provider docs: https://hermes-agent.nousresearch.com/docs/integrations/providers
Toolsets
Enable/disable via hermes tools (interactive) or hermes tools enable/disable NAME.
| Toolset | What it provides |
|---------|-----------------|
| web | Web search and content extraction |
| search | Web search only (subset of web) |
| browser | Browser automation (Browserbase, Camofox, or local Chromium) |
| terminal | Shell commands and process management |
| file | File read/write/search/patch |
| code_execution | Sandboxed Python execution |
| vision | Image analysis |
| image_gen | AI image generation |
| video | Video analysis and generation |
| tts | Text-to-speech |
| skills | Skill browsing and management |
| memory | Persistent cross-session memory |
| session_search | Search past conversations |
| delegation | Subagent task delegation |
| cronjob | Scheduled task management |
| clarify | Ask user clarifying questions |
| messaging | Cross-platform message sending |
| todo | In-session task planning and tracking |
| kanban | Multi-agent work-queue tools (gated to workers) |
| debugging | Extra introspection/debug tools (off by default) |
| safe | Minimal, low-risk toolset for locked-down sessions |
| spotify | Spotify playback and playlist control |
| homeassistant | Smart home control (off by default) |
| discord | Discord integration tools |
| discord_admin | Discord admin/moderation tools |
| feishu_doc | Feishu (Lark) document tools |
| feishu_drive | Feishu (Lark) drive tools |
| yuanbao | Yuanbao integration tools |
| rl | Reinforcement learning tools (off by default) |
| moa | Mixture of Agents (off by default) |
Full enumeration lives in toolsets.py as the TOOLSETS dict; _HERMES_CORE_TOOLS is the default bundle most platforms inherit from.
Tool changes take effect on /reset (new session). They do NOT apply mid-conversation to preserve prompt caching.
---
Security & Privacy Toggles
Common "why is Hermes doing X to my output / tool calls / commands?" toggles โ and the exact commands to change them. Most of these need a fresh session (/reset in chat, or start a new hermes invocation) because they're read once at startup.
Secret redaction in tool output
Secret redaction is off by default โ tool output (terminal stdout, read_file, web content, subagent summaries, etc.) passes through unmodified. If the user wants Hermes to auto-mask strings that look like API keys, tokens, and secrets before they enter the conversation context and logs:
hermes config set security.redact_secrets true # enable globally
Restart required. security.redact_secrets is snapshotted at import time โ toggling it mid-session (e.g. via export HERMES_REDACT_SECRETS=true from a tool call) will NOT take effect for the running process. Tell the user to run hermes config set security.redact_secrets true in a terminal, then start a new session. This is deliberate โ it prevents an LLM from flipping the toggle on itself mid-task.
Disable again with:
hermes config set security.redact_secrets false
PII redaction in gateway messages
Separate from secret redaction. When enabled, the gateway hashes user IDs and strips phone numbers from the session context before it reaches the model:
hermes config set privacy.redact_pii true # enable
hermes config set privacy.redact_pii false # disable (default)
Command approval prompts
By default (approvals.mode: manual), Hermes prompts the user before running shell commands flagged as destructive (rm -rf, git reset --hard, etc.). The modes are:
manual โ always prompt (default)
smart โ use an auxiliary LLM to auto-approve low-risk commands, prompt on high-risk
off โ skip all approval prompts (equivalent to --yolo)
hermes config set approvals.mode smart # recommended middle ground
hermes config set approvals.mode off # bypass everything (not recommended)
Per-invocation bypass without changing config:
hermes --yolo โฆ
export HERMES_YOLO_MODE=1
Note: YOLO / approvals.mode: off does NOT turn off secret redaction. They are independent.
Shell hooks allowlist
Some shell-hook integrations require explicit allowlisting before they fire. Managed via ~/.hermes/shell-hooks-allowlist.json โ prompted interactively the first time a hook wants to run.
Disabling the web/browser/image-gen tools
To keep the model away from network or media tools entirely, open hermes tools and toggle per-platform. Takes effect on next session (/reset). See the Tools & Skills section above.
---
Voice & Transcription
STT (Voice โ Text)
Voice messages from messaging platforms are auto-transcribed.
Provider priority (auto-detected):
1. Local faster-whisper โ free, no API key: pip install faster-whisper
2. Groq Whisper โ free tier: set GROQ_API_KEY
3. OpenAI Whisper โ paid: set VOICE_TOOLS_OPENAI_KEY
4. Mistral Voxtral โ set MISTRAL_API_KEY
Config:
stt:
enabled: true
provider: local # local, groq, openai, mistral
local:
model: base # tiny, base, small, medium, large-v3
TTS (Text โ Voice)
| Provider | Env var | Free? |
|----------|---------|-------|
| Edge TTS | None | Yes (default) |
| ElevenLabs | ELEVENLABS_API_KEY | Free tier |
| OpenAI | VOICE_TOOLS_OPENAI_KEY | Paid |
| MiniMax | MINIMAX_API_KEY | Paid |
| Mistral (Voxtral) | MISTRAL_API_KEY | Paid |
| NeuTTS (local) | None (pip install neutts[all] + espeak-ng) | Free |
Voice commands: /voice on (voice-to-voice), /voice tts (always voice), /voice off.
---
Spawning Additional Hermes Instances
Run additional Hermes processes as fully independent subprocesses โ separate sessions, tools, and environments.
When to Use This vs delegate_task
| | delegate_task | Spawning hermes process |
|-|-----------------|--------------------------|
| Isolation | Separate conversation, shared process | Fully independent process |
| Duration | Minutes (bounded by parent loop) | Hours/days |
| Tool access | Subset of parent's tools | Full tool access |
| Interactive | No | Yes (PTY mode) |
| Use case | Quick parallel subtasks | Long autonomous missions |
One-Shot Mode
terminal(command="hermes chat -q 'Research GRPO papers and write summary to ~/research/grpo.md'", timeout=300)
Background for long tasks:
terminal(command="hermes chat -q 'Set up CI/CD for ~/myapp'", background=true)
Interactive PTY Mode (via tmux)
Hermes uses prompt_toolkit, which requires a real terminal. Use tmux for interactive spawning:
Start
terminal(command="tmux new-session -d -s agent1 -x 120 -y 40 'hermes'", timeout=10)
Wait for startup, then send a message
terminal(command="sleep 8 && tmux send-keys -t agent1 'Build a FastAPI auth service' Enter", timeout=15)
Read output
terminal(command="sleep 20 && tmux capture-pane -t agent1 -p", timeout=5)
Send follow-up
terminal(command="tmux send-keys -t agent1 'Add rate limiting middleware' Enter", timeout=5)
Exit
terminal(command="tmux send-keys -t agent1 '/exit' Enter && sleep 2 && tmux kill-session -t agent1", timeout=10)
Multi-Agent Coordination
Agent A: backend
terminal(command="tmux new-session -d -s backend -x 120 -y 40 'hermes -w'", timeout=10)
terminal(command="sleep 8 && tmux send-keys -t backend 'Build REST API for user management' Enter", timeout=15)
Agent B: frontend
terminal(command="tmux new-session -d -s frontend -x 120 -y 40 'hermes -w'", timeout=10)
terminal(command="sleep 8 && tmux send-keys -t frontend 'Build React dashboard for user management' Enter", timeout=15)
Check progress, relay context between them
terminal(command="tmux capture-pane -t backend -p | tail -30", timeout=5)
terminal(command="tmux send-keys -t frontend 'Here is the API schema from the backend agent: ...' Enter", timeout=5)
Session Resume
Resume most recent session
terminal(command="tmux new-session -d -s resumed 'hermes --continue'", timeout=10)
Resume specific session
terminal(command="tmux new-session -d -s resumed 'hermes --resume 20260225_143052_a1b2c3'", timeout=10)
Tips
- Prefer
delegate_task for quick subtasks โ less overhead than spawning a full process
- Use
-w (worktree mode) when spawning agents that edit code โ prevents git conflicts
- Set timeouts for one-shot mode โ complex tasks can take 5-10 minutes
- Use
hermes chat -q for fire-and-forget โ no PTY needed
- Use tmux for interactive sessions โ raw PTY mode has
\r vs \n issues with prompt_toolkit
- For scheduled tasks, use the
cronjob tool instead of spawning โ handles delivery and retry
---
Durable & Background Systems
Four systems run alongside the main conversation loop. Quick reference
here; full developer notes live in AGENTS.md, user-facing docs under
website/docs/user-guide/features/.
Delegation (delegate_task)
Synchronous subagent spawn โ the parent waits for the child's summary
before continuing its own loop. Isolated context + terminal session.
- Single:
delegate_task(goal, context, toolsets).
- Batch:
delegate_task(tasks=[{goal, ...}, ...]) runs children in
parallel, capped by delegation.max_concurrent_children (default 3).
- Roles:
leaf (default; cannot re-delegate) vs orchestrator
(can spawn its own workers, bounded by delegation.max_spawn_depth).
- Not durable. If the parent is interrupted, the child is
cancelled. For work that must outlive the turn, use cronjob or
terminal(background=True, notify_on_complete=True).
Config: delegation.* in config.yaml.
Tuning max_concurrent_children
Default is 3. Rule of thumb for raising it:
- Light tasks (web search, file grep): up to
6-8
- Medium tasks (code execution, browser):
4-5
- Heavy tasks (builds, large data):
2-3
- Actual bottleneck is usually the API rate limit, not local CPU/RAM. On a 10-core M4 with 16GB RAM, CPU is rarely the constraint.
- Formula: start at
5, raise only if profiling shows idle time between API responses.
Cron (scheduled jobs)
Durable scheduler โ cron/jobs.py + cron/scheduler.py. Drive it via
the cronjob tool, the hermes cron CLI (list, add, edit,
pause, resume, run, remove), or the /cron slash command.
- Schedules: duration (
"30m", "2h"), "every" phrase
( "every monday 9am"), 5-field cron ( "0 9 *"), or ISO timestamp.
- Per-job knobs:
skills, model/provider override, script
(pre-run data collection; no_agent=True makes the script the whole
job), context_from (chain job A's output into job B), workdir
(run in a specific dir with its AGENTS.md / CLAUDE.md loaded),
multi-platform delivery.
- Invariants: 3-minute hard interrupt per run,
.tick.lock file
prevents duplicate ticks across processes, cron sessions pass
skip_memory=True by default, and cron deliveries are framed with a
header/footer instead of being mirrored into the target gateway
session (keeps role alternation intact).
User docs: https://hermes-agent.nousresearch.com/docs/user-guide/features/cron
Curator (skill lifecycle)
Background maintenance for agent-created skills. Tracks usage, marks
idle skills stale, archives stale ones, keeps a pre-run tar.gz backup
so nothing is lost.
- CLI:
hermes curator <verb> โ status, run, pause, resume,
pin, unpin, archive, restore, prune, backup, rollback.
- Slash:
/curator <subcommand> mirrors the CLI.
- Scope: only touches skills with
created_by: "agent" provenance.
Bundled + hub-installed skills are off-limits. Never deletes โ
max destructive action is archive. Pinned skills are exempt from
every auto-transition and every LLM review pass.
- Telemetry: sidecar at
~/.hermes/skills/.usage.json holds
per-skill use_count, view_count, patch_count,
last_activity_at, state, pinned.
Config: curator.* (enabled, interval_hours, min_idle_hours,
stale_after_days, archive_after_days, backup.*).
User docs: https://hermes-agent.nousresearch.com/docs/user-guide/features/curator
Dreaming (periodic memory/skill consolidation)
For Anthropic-style "dreaming" workflows, combine cron + session_search + memory + skills + curator into a scheduled review loop. Start with a weekly, proposal-only report that audits recent sessions, repeated user corrections, memory conflicts, skill patch candidates, and cron/automation improvements. Do not automatically delete/replace memory or patch/archive skills unless the user explicitly approves the proposed changes. See references/weekly-dreaming-routine.md for the recommended prompt, report format, safety policy, and cron creation pattern.
Kanban (multi-agent work queue)
Durable SQLite board for multi-profile / multi-worker collaboration.
Users drive it via hermes kanban <verb>; dispatcher-spawned workers
see a focused kanban_* toolset gated by HERMES_KANBAN_TASK so the
schema footprint is zero outside worker processes.
- CLI verbs (common):
init, create, list (alias ls),
show, assign, link, unlink, comment, complete, block,
unblock, archive, tail. Less common: watch, stats, runs,
log, dispatch, daemon, gc.
- Worker toolset:
kanban_show, kanban_complete, kanban_block,
kanban_heartbeat, kanban_comment, kanban_create, kanban_link.
- Dispatcher runs inside the gateway by default
( kanban.dispatch_in_gateway: true) โ reclaims stale claims,
promotes ready tasks, atomically claims, spawns assigned profiles.
Auto-blocks a task after ~5 consecutive spawn failures.
- Isolation: board is the hard boundary (workers get
HERMES_KANBAN_BOARD pinned in env); tenant is a soft namespace
within a board for workspace-path + memory-key isolation.
User docs: https://hermes-agent.nousresearch.com/docs/user-guide/features/kanban
Log Relay (Hermes โ Discord)
A background Python script that tails ~/.hermes/logs/*.log and batches lines to a Discord channel. Includes session-ID extraction, rate-limit handling, and auto-restart via launchd/systemd. Useful for remote monitoring and audit trails.
- Reference:
references/discord-log-relay.md โ full setup, tuning, macOS/Linux service install, pitfalls.
- Template:
templates/discord-log-relay.py โ copy, set CHANNEL_ID, and deploy.
- Discord operations:
references/discord-operating-planes.md โ channel-purpose routing, periodic-summary vs Dreaming report formats, and safety/cost notes for Discord-first Hermes deployments.
Key pitfall: ask the user about batch frequency upfront rather than defaulting to real-time streaming. Most users prefer 10-minute or hourly batches. High-volume raw logs should be batched, summarized, or stored out-of-band; avoid Discord message storms during error loops.
Weekly Dreaming / Memory Curation
For long-running Hermes deployments, users may want an Anthropic-style "Dreaming" loop: a scheduled review that consolidates experience, proposes memory/skill/cron changes, and identifies what to keep, weaken, archive, or delete. Hermes has the building blocks (sessions, session_search, memory, skills, curator, cron), but the safe default is proposal mode:
1. Inspect recent usage and sessions.
2. Extract repeated success patterns, failure patterns, and user corrections.
3. Propose memory updates/removals without applying them silently.
4. Propose skill patches/archive candidates and cron/reporting improvements.
5. End with explicit approval checkboxes.
Do not silently rewrite or delete memory/skills from a Dreaming report unless the user explicitly authorized automatic application. See references/discord-operating-planes.md for a report template and routing heuristics.
---
Windows-Specific Quirks
Hermes runs natively on Windows (PowerShell, cmd, Windows Terminal, git-bash
mintty, VS Code integrated terminal). Most of it just works, but a handful
of differences between Win32 and POSIX have bitten us โ document new ones
here as you hit them so the next person (or the next session) doesn't
rediscover them from scratch.
Input / Keybindings
Alt+Enter doesn't insert a newline. Windows Terminal intercepts Alt+Enter
at the terminal layer to toggle fullscreen โ the keystroke never reaches
prompt_toolkit. Use Ctrl+Enter instead. Windows Terminal delivers
Ctrl+Enter as LF ( c-j), distinct from plain Enter ( c-m / CR), and the
CLI binds c-j to newline insertion on win32 only (see
_bind_prompt_submit_keys + the Windows-only c-j binding in cli.py).
Side effect: the raw Ctrl+J keystroke also inserts a newline on Windows โ
unavoidable, because Windows Terminal collapses Ctrl+Enter and Ctrl+J to
the same keycode at the Win32 console API layer. No conflicting binding
existed for Ctrl+J on Windows, so this is a harmless side effect.
mintty / git-bash behaves the same (fullscreen on Alt+Enter) unless you
disable Alt+Fn shortcuts in Options โ Keys. Easier to just use Ctrl+Enter.
Diagnosing keybindings. Run python scripts/keystroke_diagnostic.py
(repo root) to see exactly how prompt_toolkit identifies each keystroke
in the current terminal. Answers questions like "does Shift+Enter come
through as a distinct key?" (almost never โ most terminals collapse it
to plain Enter) or "what byte sequence is my terminal sending for
Ctrl+Enter?" This is how the Ctrl+Enter = c-j fact was established.
Config / Files
HTTP 400 "No models provided" on first run. config.yaml was saved
with a UTF-8 BOM (common when Windows apps write it). Re-save as UTF-8
without BOM. hermes config edit writes without BOM; manual edits in
Notepad are the usual culprit.
execute_code / Sandbox
WinError 10106 ("The requested service provider could not be loaded
or initialized") from the sandbox child process โ it can't create an
AF_INET socket, so the loopback-TCP RPC fallback fails before
connect(). Root cause is usually not a broken Winsock LSP; it's
Hermes's own env scrubber dropping SYSTEMROOT / WINDIR / COMSPEC
from the child env. Python's socket module needs SYSTEMROOT to locate
mswsock.dll. Fixed via the _WINDOWS_ESSENTIAL_ENV_VARS allowlist in
tools/code_execution_tool.py. If you still hit it, echo os.environ
inside an execute_code block to confirm SYSTEMROOT is set. Full
diagnostic recipe in references/execute-code-sandbox-env-windows.md.
Testing / Contributing
scripts/run_tests.sh doesn't work as-is on Windows โ it looks for
POSIX venv layouts ( .venv/bin/activate). The Hermes-installed venv at
venv/Scripts/ has no pip or pytest either (stripped for install size).
Workaround: install pytest + pytest-xdist + pyyaml into a system Python
3.11 user site, then invoke pytest directly with PYTHONPATH set:
"/c/Program Files/Python311/python" -m pip install --user pytest pytest-xdist pyyaml
export PYTHONPATH="$(pwd)"
"/c/Program Files/Python311/python" -m pytest tests/foo/test_bar.py -v --tb=short -n 0
Use -n 0, not -n 4 โ pyproject.toml's default addopts already
includes -n, and the wrapper's CI-parity guarantees don't apply off POSIX.
POSIX-only tests need skip guards. Common markers already in the codebase:
- Symlinks โ elevated privileges on Windows
0o600 file modes โ POSIX mode bits not enforced on NTFS by default
signal.SIGALRM โ Unix-only (see tests/conftest.py::_enforce_test_timeout)
- Winsock / Windows-specific regressions โ
@pytest.mark.skipif(sys.platform != "win32", ...)
Use the existing skip-pattern style (sys.platform == "win32" or
sys.platform.startswith("win")) to stay consistent with the rest of the
suite.
Path / Filesystem
Line endings. Git may warn LF will be replaced by CRLF the next time
Git touches it. Cosmetic โ the repo's .gitattributes normalizes. Don't
let editors auto-convert committed POSIX-newline files to CRLF.
Forward slashes work almost everywhere. C:/Users/... is accepted by
every Hermes tool and most Windows APIs. Prefer forward slashes in code
and logs โ avoids shell-escaping backslashes in bash.
---
Troubleshooting
Voice not working
1. Check stt.enabled: true in config.yaml
2. Verify provider: pip install faster-whisper or set API key
3. In gateway: /restart. In CLI: exit and relaunch.
Tool not available
1. hermes tools โ check if toolset is enabled for your platform
2. Some tools need env vars (check .env)
3. /reset after enabling tools
Model/provider issues
1. hermes doctor โ check config and dependencies
2. hermes auth add <provider> โ re-authenticate OAuth providers (use --type oauth)
3. Check .env has the right API key
4. Copilot 403: gh auth login tokens do NOT work for Copilot API. You must use the Copilot-specific OAuth device code flow via hermes model โ GitHub Copilot.
Changes not taking effect
- Tools/skills:
/reset starts a new session with updated toolset
- Config changes: In gateway:
/restart. In CLI: exit and relaunch.
- Code changes: Restart the CLI or gateway process
Deployed web dashboard shows stale CSS or theme changes
- Browser cache: Add
?v=N cache-busting query strings to CSS/JS/theme links in HTML.
- Service Worker cache: Bump
CACHE_NAME in sw.js to invalidate old shell caches.
- Data freshness: Use
fetch(url, {cache:'no-store'}) for live JSON feeds.
- Auto-detection: Embed
data-build in <html> and compare server build vs loaded build on page load to show a "new version available" banner. See references/static-site-cache-invalidation.md for the full diagnostic recipe and auto-detection pattern.
- Theme switcher reliability: If theme switching works in Chrome but not Samsung Internet, or feels broken on mobile, see
references/theme-switcher-reliability.md for the create-new-link โ load โ remove-old pattern.
- Emergency recovery: If a bad deploy breaks the main app JS, users need a standalone reset page. See
references/emergency-reset-page.md for a zero-dependency reset.html that clears Service Workers and caches without relying on the main app's JS.
Dashboard inspector feels too technical
- The default inspector view should contain only plain-language sentences: headline, "what they're doing now", "why it matters", and a silent visual progress bar (no text label).
- Move all technical fields (source IDs, confidence scores, progress labels, status slugs, badges) behind a "Show technical details" toggle.
- If users say "details are hard to understand," the fix is to remove more fields from the default view, not to add explanations. Explanations of technical fields are still technical.
- See
references/progressive-disclosure-human-first.md for the aggressive simplification pattern.
Skills not showing
1. hermes skills list โ verify installed
2. hermes skills config โ check platform enablement
3. Load explicitly: /skill name or hermes -s name
Gateway issues
Check logs first:
grep -i "failed to send\|error" ~/.hermes/logs/gateway.log | tail -20
Common gateway problems:
- Gateway dies on SSH logout: Enable linger:
sudo loginctl enable-linger $USER
- Gateway dies on WSL2 close: WSL2 requires
systemd=true in /etc/wsl.conf for systemd services to work. Without it, gateway falls back to nohup (dies when session closes).
- Gateway crash loop: Reset the failed state:
systemctl --user reset-failed hermes-gateway
- macOS: bot shows offline after idle time: The gateway runs as a user agent (
LimitLoadToSessionType=Aqua), so macOS suspends it when the system sleeps. The platform websocket drops and the bot appears offline until the network returns. Fix: keep the Mac awake (System Settings -> Energy -> Prevent automatic sleeping, or caffeinate -d -i -s -u &). Low Power Mode makes this worse, not better. See references/macos-gateway-sleep-disconnect.md for the full diagnostic recipe.
Platform-specific issues
- Discord bot silent: Must enable Message Content Intent in Bot โ Privileged Gateway Intents. See full Discord setup reference:
references/discord-gateway-setup.md.
- Slack bot only works in DMs: Must subscribe to
message.channels event. Without it, the bot ignores public channels.
- Windows-specific issues (
Alt+Enter newline, WinError 10106, UTF-8 BOM config, test suite, line endings): see the dedicated Windows-Specific Quirks section above.
Auxiliary models not working
If auxiliary tasks (vision, compression, session_search) fail silently, the auto provider can't find a backend. Either set OPENROUTER_API_KEY or GOOGLE_API_KEY, or explicitly configure each auxiliary task's provider:
hermes config set auxiliary.vision.provider <your_provider>
hermes config set auxiliary.vision.model <model_name>
Full system auth provisioning
For a one-shot workflow to maximize available credentials โ installing gh, generating SSH keys, configuring git, enabling all Hermes toolsets, and auditing current auth state โ see references/system-auth-setup.md.
Editing large files with patch
When a file is read with read_file(offset=...) (pagination), the tool warns that the view is partial. If you attempt patch without re-reading the full file first, you will likely hit non-unique match errors or corrupt the file. Fix: always call read_file without offset to load the whole file before patching. The tool explicitly warns: "โฆwas last read with offset/limit pagination (partial view). Re-read the whole file before overwriting it." โ heed this warning. For append-only updates (e.g., adding a cycle log entry to state.md), do not use terminal(command="cat >> file << 'EOF'...EOF") โ the terminal tool on macOS/Linux misinterprets heredoc << as backgrounding and fails. Instead, write a short Python script via write_file and execute it with terminal(command="python3 /tmp/script.py"). See references/terminal-heredoc-workaround.md for the full pattern.
Sibling subagent file overwrites
When multiple subagents are running in parallel (e.g. via delegate_task batch mode or kanban worker lanes), a file may be modified by one subagent while another is about to write to it. If you use write_file or patch on a file that was last read before a sibling subagent modified it, your write may silently truncate or revert the sibling's changes. The tool may show a warning like "this file was modified by sibling subagent X but this agent never read it."
Fix:
1. Heed the warning. If the tool reports a sibling modification, re-read the file with read_file before writing.
2. Prefer patch over write_file for partial updates โ patch only changes the matched region and is less likely to wipe unrelated content.
3. If the file is already published/deployed, and the local working copy gets corrupted, recover from the published copy:
cp ~/hermes-web/agent-pets/css/dashboard.css ~/.hermes/autonomous-agent-lab/pixel-pet-ops/web/css/dashboard.css
4. For append-only updates, write a small Python script and execute it rather than using write_file on the whole file.
Prevention: In kanban/multi-agent workflows, assign file-level ownership so only one worker touches each file. If parallel workers must edit the same file, have them write to separate temp files and let the orchestrator merge.
---
Windows-Specific Quirks
| Looking for... | Location |
|----------------|----------|
| Config options | hermes config edit or [Configuration docs](https://hermes-agent.nousresearch.com/docs/user-guide/configuration) |
| Available tools | hermes tools list or [Tools reference](https://hermes-agent.nousresearch.com/docs/reference/tools-reference) |
| Slash commands | /help in session or [Slash commands reference](https://hermes-agent.nousresearch.com/docs/reference/slash-commands) |
| Skills catalog | hermes skills browse or [Skills catalog](https://hermes-agent.nousresearch.com/docs/reference/skills-catalog) |
| Provider setup | hermes model or [Providers guide](https://hermes-agent.nousresearch.com/docs/integrations/providers) |
| Platform setup | hermes gateway setup or [Messaging docs](https://hermes-agent.nousresearch.com/docs/user-guide/messaging/) |
| MCP servers | hermes mcp list or [MCP guide](https://hermes-agent.nousresearch.com/docs/user-guide/features/mcp) |
| Profiles | hermes profile list or [Profiles docs](https://hermes-agent.nousresearch.com/docs/user-guide/profiles) |
| Cron jobs | hermes cron list or [Cron docs](https://hermes-agent.nousresearch.com/docs/user-guide/features/cron) |
| Memory | hermes memory status or [Memory docs](https://hermes-agent.nousresearch.com/docs/user-guide/features/memory) |
| Env variables | hermes config env-path or [Env vars reference](https://hermes-agent.nousresearch.com/docs/reference/environment-variables) |
| CLI commands | hermes --help or [CLI reference](https://hermes-agent.nousresearch.com/docs/reference/cli-commands) |
| Gateway logs | ~/.hermes/logs/gateway.log |
| Session files | ~/.hermes/sessions/ or hermes sessions browse |
| Source code | ~/.hermes/hermes-agent/ |
---
Contributor Quick Reference
For occasional contributors and PR authors. Full developer docs: https://hermes-agent.nousresearch.com/docs/developer-guide/
Project Layout
hermes-agent/
โโโ run_agent.py # AIAgent โ core conversation loop
โโโ model_tools.py # Tool discovery and dispatch
โโโ toolsets.py # Toolset definitions
โโโ cli.py # Interactive CLI (HermesCLI)
โโโ hermes_state.py # SQLite session store
โโโ agent/ # Prompt builder, context compression, memory, model routing, credential pooling, skill dispatch
โโโ hermes_cli/ # CLI subcommands, config, setup, commands
โ โโโ commands.py # Slash command registry (CommandDef)
โ โโโ config.py # DEFAULT_CONFIG, env var definitions
โ โโโ main.py # CLI entry point and argparse
โโโ tools/ # One file per tool
โ โโโ registry.py # Central tool registry
โโโ gateway/ # Messaging gateway
โ โโโ platforms/ # Platform adapters (telegram, discord, etc.)
โโโ cron/ # Job scheduler
โโโ tests/ # ~3000 pytest tests
โโโ website/ # Docusaurus docs site
Config: ~/.hermes/config.yaml (settings), ~/.hermes/.env (API keys).
Adding a Tool (3 files)
1. Create tools/your_tool.py:
import json, os
from tools.registry import registry
def check_requirements() -> bool:
return bool(os.getenv("EXAMPLE_API_KEY"))
def example_tool(param: str, task_id: str = None) -> str:
return json.dumps({"success": True, "data": "..."})
registry.register(
name="example_tool",
toolset="example",
schema={"name": "example_tool", "description": "...", "parameters": {...}},
handler=lambda args, **kw: example_tool(
param=args.get("param", ""), task_id=kw.get("task_id")),
check_fn=check_requirements,
requires_env=["EXAMPLE_API_KEY"],
)
2. Add to toolsets.py โ _HERMES_CORE_TOOLS list.
Auto-discovery: any tools/*.py file with a top-level registry.register() call is imported automatically โ no manual list needed.
All handlers must return JSON strings. Use get_hermes_home() for paths, never hardcode ~/.hermes.
Adding a Slash Command
1. Add CommandDef to COMMAND_REGISTRY in hermes_cli/commands.py
2. Add handler in cli.py โ process_command()
3. (Optional) Add gateway handler in gateway/run.py
All consumers (help text, autocomplete, Telegram menu, Slack mapping) derive from the central registry automatically.
Agent Loop (High Level)
run_conversation():
1. Build system prompt
2. Loop while iterations < max:
a. Call LLM (OpenAI-format messages + tool schemas)
b. If tool_calls โ dispatch each via handle_function_call() โ append results โ continue
c. If text response โ return
3. Context compression triggers automatically near token limit
Testing
python -m pytest tests/ -o 'addopts=' -q # Full suite
python -m pytest tests/tools/ -q # Specific area
- Tests auto-redirect
HERMES_HOME to temp dirs โ never touch real ~/.hermes/
- Run full suite before pushing any change
- Use
-o 'addopts=' to clear any baked-in pytest flags
Windows contributors: scripts/run_tests.sh currently looks for POSIX venvs ( .venv/bin/activate / venv/bin/activate) and will error out on Windows where the layout is venv/Scripts/activate + python.exe. The Hermes-installed venv at venv/Scripts/ also has no pip or pytest โ it's stripped for end-user install size. Workaround: install pytest + pytest-xdist + pyyaml into a system Python 3.11 user site ( /c/Program Files/Python311/python -m pip install --user pytest pytest-xdist pyyaml), then run tests directly:
export PYTHONPATH="$(pwd)"
"/c/Program Files/Python311/python" -m pytest tests/tools/test_foo.py -v --tb=short -n 0
Use -n 0 (not -n 4) because pyproject.toml's default addopts already includes -n, and the wrapper's CI-parity story doesn't apply off-POSIX.
Cross-platform test guards: tests that use POSIX-only syscalls need a skip marker. Common ones already in the codebase:
- Symlink creation โ
@pytest.mark.skipif(sys.platform == "win32", reason="Symlinks require elevated privileges on Windows") (see tests/cron/test_cron_script.py)
- POSIX file modes (0o600, etc.) โ
@pytest.mark.skipif(sys.platform.startswith("win"), reason="POSIX mode bits not enforced on Windows") (see tests/hermes_cli/test_auth_toctou_file_modes.py)
signal.SIGALRM โ Unix-only (see tests/conftest.py::_enforce_test_timeout)
- Live Winsock / Windows-specific regression tests โ
@pytest.mark.skipif(sys.platform != "win32", reason="Windows-specific regression")
Monkeypatching sys.platform is not enough when the code under test also calls platform.system() / platform.release() / platform.mac_ver(). Those functions re-read the real OS independently, so a test that sets sys.platform = "linux" on a Windows runner will still see platform.system() == "Windows" and route through the Windows branch. Patch all three together:
monkeypatch.setattr(sys, "platform", "linux")
monkeypatch.setattr(platform, "system", lambda: "Linux")
monkeypatch.setattr(platform, "release", lambda: "6.8.0-generic")
See tests/agent/test_prompt_builder.py::TestEnvironmentHints for a worked example.
Extending the system prompt's execution-environment block
Factual guidance about the host OS, user home, cwd, terminal backend, and shell (bash vs. PowerShell on Windows) is emitted from agent/prompt_builder.py::build_environment_hints(). This is also where the WSL hint and per-backend probe logic live. The convention:
- Local terminal backend โ emit host info (OS,
$HOME, cwd) + Windows-specific notes (hostname โ username, terminal uses bash not PowerShell).
- Remote terminal backend (anything in
_REMOTE_TERMINAL_BACKENDS: docker, singularity, modal, daytona, ssh, vercel_sandbox, managed_modal) โ suppress host info entirely and describe only the backend. A live uname/whoami/pwd probe runs inside the backend via tools.environments.get_environment(...).execute(...), cached per process in _BACKEND_PROBE_CACHE, with a static fallback if the probe times out.
- Key fact for prompt authoring: when
TERMINAL_ENV != "local", every file tool (read_file, write_file, patch, search_files) runs inside the backend container, not on the host. The system prompt must never describe the host in that case โ the agent can't touch it.
Full design notes, the exact emitted strings, and testing pitfalls:
references/prompt-builder-environment-hints.md.
Refactor-safety pattern (POSIX-equivalence guard): when you extract inline logic into a helper that adds Windows/platform-specific behavior, keep a _legacy_<name> oracle function in the test file that's a verbatim copy of the old code, then parametrize-diff against it. Example: tests/tools/test_code_execution_windows_env.py::TestPosixEquivalence. This locks in the invariant that POSIX behavior is bit-for-bit identical and makes any future drift fail loudly with a clear diff.
Commit Conventions
type: concise subject line
Optional body.
Types: fix:, feat:, refactor:, docs:, chore:
Key Rules
- Never break prompt caching โ don't change context, tools, or system prompt mid-conversation
- Message role alternation โ never two assistant or two user messages in a row
- Use
get_hermes_home() from hermes_constants for all paths (profile-safe)
- Config values go in
config.yaml, secrets go in .env
- New tools need a
check_fn so they only appear when requirements are met
[IMPORTANT: The user has invoked the "kanban-orchestrator" skill, indicating they want you to follow its instructions. The full skill content is loaded below.]
---
name: kanban-orchestrator
description: Decomposition playbook + anti-temptation rules for an orchestrator profile routing work through Kanban. The "don't do the work yourself" rule and the basic lifecycle are auto-injected into every kanban worker's system prompt; this skill is the deeper playbook when you're specifically playing the orchestrator role.
version: 3.0.0
platforms: [linux, macos, windows]
metadata:
hermes:
tags: [kanban, multi-agent, orchestration, routing]
related_skills: [kanban-worker]
---
Kanban Orchestrator โ Decomposition Playbook
> The core worker lifecycle (including the kanban_create fan-out pattern and the "decompose, don't execute" rule) is auto-injected into every kanban process via the KANBAN_GUIDANCE system-prompt block. This skill is the deeper playbook when you're an orchestrator profile whose whole job is routing.
Profiles are user-configured โ not a fixed roster
Hermes setups vary widely. Some users run a single profile that does everything; some run a small fleet (docker-worker, cron-worker); some run a curated specialist team they've named themselves. There is no default specialist roster โ the orchestrator skill does not know what profiles exist on this machine.
Before fanning out, you must ground the decomposition in the profiles that actually exist. The dispatcher silently fails to spawn unknown assignee names โ it doesn't autocorrect, doesn't suggest, doesn't fall back. So a card assigned to researcher on a setup that only has docker-worker just sits in ready forever.
Step 0: discover available profiles before planning.
Use one of these:
hermes profile list โ prints the table of profiles configured on this machine. Run it through your terminal tool if you have one; otherwise ask the user.
kanban_list(assignee="<some-name>") โ sanity-check a single name. Returns an empty list (rather than an error) for an unknown assignee, so this only confirms a name you're already considering.
- Just ask the user. "What profiles do you have set up?" is a fine first turn when the goal needs more than one specialist.
Cache the result in your working memory for the rest of the conversation. Re-asking every turn wastes a tool call.
When to use the board (vs. just doing the work)
Create Kanban tasks when any of these are true:
1. Multiple specialists are needed. Research + analysis + writing is three profiles.
2. The work should survive a crash or restart. Long-running, recurring, or important.
3. The user might want to interject. Human-in-the-loop at any step.
4. Multiple subtasks can run in parallel. Fan-out for speed.
5. Review / iteration is expected. A reviewer profile loops on drafter output.
6. The audit trail matters. Board rows persist in SQLite forever.
If none of those apply โ it's a small one-shot reasoning task โ use delegate_task instead or answer the user directly.
The anti-temptation rules
Your job description says "route, don't execute." The rules that enforce that:
- Do not execute the work yourself. Your restricted toolset usually doesn't even include terminal/file/code/web for implementation. If you find yourself "just fixing this quickly" โ stop and create a task for the right specialist.
- For any concrete task, create a Kanban task and assign it. Every single time.
- Split multi-lane requests before creating cards. A user prompt can contain several independent workstreams. Extract those lanes first, then create one card per lane instead of bundling unrelated work into a single implementer card.
- Run independent lanes in parallel. If two cards do not need each other's output, leave them unlinked so the dispatcher can fan them out. Link only true data dependencies.
- If no specialist fits the available profiles, ask the user which profile to create or which existing profile to use. Do not invent profile names; the dispatcher will silently drop unknown assignees.
- Decompose, route, and summarize โ that's the whole job.
Exception: micro-UI polish cycles
There is one narrow exception where the orchestrator may execute directly instead of creating Kanban cards: tiny UI-only polish cycles (e.g., adding a CSS class, a theme preview dot, a hover state, a cross-link, or a HUD button) that are purely presentational, require no cross-file logic changes, and fit comfortably inside a single bounded cycle with no need for review or parallel work. If the change is limited to HTML/CSS/JS cosmetics, no other profile has a stake in it, and the user did not ask for a design review, the orchestrator should just edit and publish rather than paying the kanban-overhead tax. This exception does NOT apply to architecture changes, adapter logic, plugin interfaces, or anything that touches the data layer.
Decomposition playbook
Step 1 โ Understand the goal
Ask clarifying questions if the goal is ambiguous. Cheap to ask; expensive to spawn the wrong fleet.
Step 2 โ Sketch the task graph
Before creating anything, draft the graph out loud (in your response to the user). Treat every concrete workstream as a candidate card:
1. Extract the lanes from the request.
2. Map each lane to one of the profiles you discovered in Step 0. If a lane doesn't fit any existing profile, ask the user which to use or create.
3. Decide whether each lane is independent or gated by another lane.
4. Create independent lanes as parallel cards with no parent links.
5. Create synthesis/review/integration cards with parent links to the lanes they depend on.
Examples of prompts that should fan out (using placeholder profile names โ substitute whatever exists on the user's setup):
- "Build an app" โ one card to a design-oriented profile for product/UI direction, one or two cards to engineering profiles for implementation, plus a later integration/review card if the user has a reviewer profile.
- "Fix blockers and check model variants" โ one implementation card for the blocker fixes plus one discovery/research card for config/source verification. A final reviewer card can depend on both.
- "Research docs and implement" โ a docs-research card can run in parallel with a codebase-discovery card; implementation waits only if it truly needs those findings.
- "Analyze this screenshot and find the related code" โ one card to a vision-capable profile for the visual analysis while another searches the codebase.
Words like "also," "finally," or "and" do not automatically imply a dependency. They often mean "make sure this is covered before reporting back." Only link tasks when one card cannot start until another card's output exists.
Show the graph to the user before creating cards. Let them correct it โ including which actual profile name should own each lane.
Step 3 โ Create tasks and link
Use the profile names from Step 0. The example below uses placeholders <profile-A>, <profile-B>, <profile-C> โ replace them with what the user actually has.
t1 = kanban_create(
title="research: Postgres cost vs current",
assignee="<profile-A>", # whichever profile handles research on this setup
body="Compare estimated infrastructure costs, migration costs, and ongoing ops costs over a 3-year window. Sources: AWS/GCP pricing, team time estimates, current Postgres bills from peers.",
tenant=os.environ.get("HERMES_TENANT"),
)["task_id"]
t2 = kanban_create(
title="research: Postgres performance vs current",
assignee="<profile-A>", # same profile, run in parallel
body="Compare query latency, throughput, and scaling characteristics at our expected data volume (~500GB, 10k QPS peak). Sources: benchmark papers, public case studies, pgbench results if easy.",
)["task_id"]
t3 = kanban_create(
title="synthesize migration recommendation",
assignee="<profile-B>", # whichever profile does synthesis/analysis
body="Read the findings from T1 (cost) and T2 (performance). Produce a 1-page recommendation with explicit trade-offs and a go/no-go call.",
parents=[t1, t2],
)["task_id"]
t4 = kanban_create(
title="draft decision memo",
assignee="<profile-C>", # whichever profile drafts user-facing prose
body="Turn the analyst's recommendation into a 2-page memo for the CTO. Match the tone of previous decision memos in the team's knowledge base.",
parents=[t3],
)["task_id"]
parents=[...] gates promotion โ children stay in todo until every parent reaches done, then auto-promote to ready. No manual coordination needed; the dispatcher and dependency engine handle it.
Step 4 โ Complete your own task
If you were spawned as a task yourself (e.g. a planner profile was assigned T0: "investigate Postgres migration"), mark it done with a summary of what you created:
kanban_complete(
summary="decomposed into T1-T4: 2 research lanes in parallel, 1 synthesis on their outputs, 1 prose draft on the recommendation",
metadata={
"task_graph": {
"T1": {"assignee": "<profile-A>", "parents": []},
"T2": {"assignee": "<profile-A>", "parents": []},
"T3": {"assignee": "<profile-B>", "parents": ["T1", "T2"]},
"T4": {"assignee": "<profile-C>", "parents": ["T3"]},
},
},
)
Step 5 โ Report back to the user
Tell them what you created in plain prose, naming the actual profiles you used:
> I've queued 4 tasks:
> - T1 (<profile-A>): cost comparison
> - T2 (<profile-A>): performance comparison, in parallel with T1
> - T3 (<profile-B>): synthesizes T1 + T2 into a recommendation
> - T4 (<profile-C>): turns T3 into a CTO memo
>
> The dispatcher will pick up T1 and T2 now. T3 starts when both finish. You'll get a gateway ping when T4 completes. Use the dashboard or hermes kanban tail <id> to follow along.
Common patterns
Fan-out + fan-in (research โ synthesize): N research-style cards with no parents, one synthesis card with all of them as parents.
Parallel implementation + validation: one implementer card makes the change while one explorer/researcher card verifies config, docs, or source mapping. A reviewer card can depend on both. Do not make the implementer own unrelated verification just because the user mentioned both in one sentence.
Pipeline with gates: planner โ implementer โ reviewer. Each stage's parents=[previous_task]. Reviewer blocks or completes; if reviewer blocks, the operator unblocks with feedback and respawns.
Same-profile queue: N tasks, all assigned to the same profile, no dependencies between them. Dispatcher serializes โ that profile processes them in priority order, accumulating experience in its own memory.
Parallel UI/frontend lanes: When the goal touches multiple independent HTML/CSS/JS files (e.g., a dashboard page and a 2D gather view), fan out to separate subagents per file. Each lane edits its own file, then the orchestrator integrates, fixes cross-file references (theme paths, shared JSON endpoints), and publishes. This avoids merge conflicts in single-file HTML dashboards and keeps each subagent's context focused. See references/parallel-ui-lanes-and-publishing.md for the post-subagent integration checklist and rsync safety notes.
Human-in-the-loop: Any task can kanban_block() to wait for input. Dispatcher respawns after /unblock. The comment thread carries the full context.
Pitfalls
Inventing profile names that don't exist. The dispatcher silently fails to spawn unknown assignees โ the card just sits in ready forever. Always assign to a profile from your Step 0 discovery; ask the user if you're unsure.
Bundling independent lanes into one card. If the user asks for two independent outcomes, create two cards. Example: "fix blockers and check model variants" is not one fixer task; create a fixer/engineer card for the fixes and an explorer/researcher card for the variant check, then optionally gate review on both.
Over-linking because of wording. "Finally check X" may still be parallel with implementation if X is static config, docs, or source discovery. Link it after implementation only when the check depends on the implementation result.
Forgetting dependency links. If the task graph says research -> implement -> review, do not create all tasks as independent ready cards. Use parent links so implement/review cannot run before their inputs exist.
Reassignment vs. new task. If a reviewer blocks with "needs changes," create a NEW task linked from the reviewer's task โ don't re-run the same task with a stern look. The new task is assigned to the original implementer profile.
Argument order for links. kanban_link(parent_id=..., child_id=...) โ parent first. Mixing them up demotes the wrong task to todo.
Ignoring explicit user feedback to keep building infrastructure. When the user says a specific UX issue (legibility, theme switching, movement density) is "immediate priority," treat it as P0 and route it before deeper packaging/architecture work. Infrastructure polish feels productive, but shipping user-visible fixes is what matters. Create cards for the UX feedback first, then resume infrastructure lanes.
Treating status: complete as immutable when user feedback says otherwise. A state.md that says status: complete does not override a user's report that a completion criterion is actually broken. If the user says "theme switching is not working" and the Final Completion Condition requires "working UI theme switcher," the mission is not complete. Reactivate immediately: set status: active, append a reactivation cycle log, and fix the issue. Do not burn cycles on post-complete verification while the user is reporting active defects.
Don't pre-create the whole graph if the shape depends on intermediate findings. If T3's structure depends on what T1 and T2 find, let T3 exist as a "synthesize findings" task whose own first step is to read parent handoffs and plan the rest. Orchestrators can spawn orchestrators.
Tenant inheritance. If HERMES_TENANT is set in your env, pass tenant=os.environ.get("HERMES_TENANT") on every kanban_create call so child tasks stay in the same namespace.
Verifying cross-file references after directory reorganization. When subagents edit HTML/CSS/JS files and the directory structure shifts (e.g., moving files from root into web/dashboard/ and web/gather/), relative asset paths ( themes/default/theme.css, ./ops-data.json) often break. After subagents finish, the orchestrator must grep for href= and src= in moved files and fix relative paths before publishing. Subagents don't know the final publish layout โ the orchestrator does.
Destructive sync wipes needed files. Commands like rsync -av --delete will delete destination files that aren't in the source list. If you publish a directory tree piecemeal (e.g., copy web/dashboard/ first, then web/gather/ separately), --delete on the first rsync will erase the gather files before the second rsync runs. Either list all source paths in a single rsync invocation, or omit --delete and use cp -r / rsync -av without deletion when doing staged copies.
Recovering stuck workers
When a worker profile keeps crashing, hallucinating, or getting blocked by its own mistakes (usually: wrong model, missing skill, broken credential), the kanban dashboard flags the task with a โ badge and opens a Recovery section in the drawer. Three primary actions:
1. Reclaim (or hermes kanban reclaim <task_id>) โ abort the running worker immediately and reset the task to ready. The existing claim TTL is ~15 min; this is the fast path out.
2. Reassign (or hermes kanban reassign <task_id> <new-profile> --reclaim) โ switch the task to a different profile (one that exists on this setup) and let the dispatcher pick it up with a fresh worker.
3. Change profile model โ the dashboard prints a copy-paste hint for hermes -p <profile> model since profile config lives on disk; edit it in a terminal, then Reclaim to retry with the new model.
Hallucination warnings appear on tasks where a worker's kanban_complete(created_cards=[...]) claim included card ids that don't exist or weren't created by the worker's profile (the gate blocks the completion), or where the free-form summary references t_<hex> ids that don't resolve (advisory prose scan, non-blocking). Both produce audit events that persist even after recovery actions โ the trail stays for debugging.
The user has provided the following instruction alongside the skill invocation: [IMPORTANT: You are running as a scheduled cron job. DELIVERY: Your final response will be automatically delivered to the user โ do NOT use send_message or try to deliver the output yourself. Just produce your report/output as your final response and the system handles the rest. SILENT: If there is genuinely nothing new to report, respond with exactly "[SILENT]" (nothing else) to suppress delivery. Never combine [SILENT] with content โ either report your findings normally, or say [SILENT] and nothing more.]
You are the 15-minute Orchestrator for Son's Autonomous Agent Lab v1, reporting to Discord channel ID 1505805763824586952.
Durable state path: /Users/jooho-hermes/.hermes/autonomous-agent-lab/state.md
Working directory for experiment artifacts: /Users/jooho-hermes/.hermes/autonomous-agent-lab/
Preferred published web root: /Users/jooho-hermes/hermes-web/agent-pets/
Top-level directive from Son:
- The project has evolved from a personal dashboard into an INSTALLABLE PRODUCT that external Hermes users can deploy.
- The final target is a self-contained, configurable, publishable solution: "Hermes Pixel Pet Ops Office".
- Do NOT shrink the mission into a small static MVP and autonomously stop.
- The Gather.town-style 2D spatial office is a first-class feature, not a side page.
Latest UX feedback from Son (treat as immediate priority before deeper packaging work):
- Details are hard for a human to understand. Add human-first summaries, plain-language labels, and progressive disclosure: summary first, technical details second.
- Gather Town version has too many agents roaming around. Reduce default movement, add density/speed controls, cluster agents by room/task, and add focus/calm mode.
- Theme switching is not visibly working. Implement real UI theme switcher with persistence and clear visual theme changes.
Key product requirements (installable solution level):
1. Config-driven architecture: all paths, URLs, colors, names, room layouts via config.yaml. No hardcoded references to jooho-hermes.
2. Self-contained package: clear directory structure (src/, web/, config/, docs/, scripts/), install script, requirements.txt.
3. Pluggable data adapter: support multiple backends via plugin architecture.
4. Themeable frontend: CSS variables driven from config, swappable themes, plus a working UI theme switcher.
5. Multi-tenant ready: works for any Hermes instance.
6. Build/Deploy ready: Dockerfile or docker-compose, or clear static-server setup.
7. Documentation: README, architecture docs, configuration reference, contributor guide.
8. Human-comprehensible UX: plain-language summaries and progressive disclosure for technical detail.
9. Gather.town calm mode: adjustable movement density/speed and less chaotic defaults.
10. Versioned releases: CHANGELOG.md, semantic versioning, release packaging.
Mission model:
- Read state.md first before doing anything else.
- If state.md says
status: inactive or has no Current Mission, do not invent work. Return exactly: ๐ก Autonomous Agent Lab ๋๊ธฐ์ค โ Son์ด ํธ๋ฆฌ๊ฑฐ/๋ฏธ์
์ ์ฃผ๋ฉด 15๋ถ ์ฌ์ดํด์ ์์ํฉ๋๋ค.
- If state.md says
status: active, run one bounded 15-minute cycle toward the full installable solution.
- If state.md says
status: complete, verify that the Final Completion Condition in state.md is truly met. If it is not fully met, reactivate or report that state needs correction.
Cycle procedure when active:
1. Read state.md first. Extract current mission, constraints, previous cycle log, and Final Completion Condition.
2. Decide the next smallest useful step toward installable solution quality. Focus on: architecture, configurability, documentation, and clean separation of concerns.
3. Use delegate_task for independent subagent lanes when helpful.
4. Prefer concrete progress: refactor to config-driven, add install scripts, create docs, add Docker support, theme system, plugin architecture.
5. Update state.md with a new cycle log entry before final reporting.
6. Completion rule: only set status: complete when every item under state.md Final Completion Condition is satisfied. A non-installable MVP is not complete.
7. Stop/block only if Son explicitly stops/redirects, a safety boundary is reached, or a hard blocker needs Son's decision.
Link requirement (never forget):
- Every cycle report MUST include at least one direct viewable link to the published dashboard/artifact.
- The canonical URL:
http://hermes-mac-mini.tail46b3c6.ts.net:8099/agent-pets/
- Include gather town URL too:
http://hermes-mac-mini.tail46b3c6.ts.net:8099/agent-pets/gather/
Final Discord message format:
[Autonomous Agent Lab v1 / Cycle N]
๋ชฉํ:
์ํ:
๊ฒฐ๊ณผ:
๊ฒ์ฆ:
๋ค์:
์ํ:
Safety/quality rules:
- Do not handle secrets, passwords, API keys, payment, permission dialogs, or destructive commands.
- Do not claim completion without updating state.md.
- Do not rely on Discord history as durable state.
- Do not spam raw logs; summarize lane outputs and verification.
- Keep working in /Users/jooho-hermes/.hermes/autonomous-agent-lab/ and publish only to /Users/jooho-hermes/hermes-web/agent-pets/ unless the state file says otherwise.
Design/UX priorities:
- Mobile responsiveness is first-class.
- Character animation/movement is desired.
- Every cycle report must include published links.
- This is now a product engineering mission. Architecture, configurability, and documentation matter as much as visuals.
Response
[Autonomous Agent Lab v1 / Cycle 70]
๋ชฉํ:
Son์ โ์์ ํฝ์
์คํดโ ํผ๋๋ฐฑ(๋ชจ๋ฐ์ผ์์ ์ฅ์ ์์๊ฐ ๋/๊ผฌ๋ฆฌ์ฒ๋ผ ๋ณด์)์ ํด๊ฒฐํ๊ณ , ๋น๋ ๋๋ฒ๋ฅผ b68๋ก ์ฌ๋ ค ์บ์ ๋ฌธ์ ๋ฅผ ๋ฐฉ์งํฉ๋๋ค.
์ํ:
- Dashboard CSS:
@media (max-width:480px)์์ .pet .cheek์ .pet .badge๋ฅผ ์จ๊น
- Gather CSS:
@media (max-width:480px)์์ .avatar .ear์ .avatar .badge๋ฅผ ์จ๊น
- HTML/JS/CSS ์บ์ ๋ฒ์คํ
?v=67 โ ?v=68 ์ผ๊ด ๊ต์ฒด
- Service Worker
CACHE_NAME์ pixel-pet-ops-v22๋ก ์ฆ๊ฐ
scripts/publish.sh๋ก ๋ฐํ + generate_ops_data ์ด๋ํฐ ์ฌ์คํ
๊ฒฐ๊ณผ:
- ๋์๋ณด๋ & Gather Town ๋ชจ๋ ๋น๋
b68 ํ์
- ์ข์ ํ๋ฉด(480px ์ดํ)์์ ๋ฐ๋ ค๋๋ฌผ ๋ณผ๋ก/๊ท/๋ฑ์ง ์ ๊ฑฐ๋ก ๊น๋ํ ์ค๋ฃจ์ฃ ์ ์ง
ops-data.json ๊ฐฑ์ ์๋ฃ (32 agents, 15 cron jobs, 20 sessions, 16 events)
๊ฒ์ฆ:
- ๋ฐํ๋ HTML์
data-build="68" ๋ฐ v1.4.4 ยท b68 ํ์ธ
- ๋ฐํ๋ CSS์
.cheek{display:none}, .ear{display:none} ๊ท์น ํ์ธ
ops-data.json / health.json mtime 60์ด ์ด๋ด, refresh.err.log ๋น์ด ์์
๋ค์:
Son์ด ๋ชจ๋ฐ์ผ(์ข์ ๋ทฐํฌํธ)์์ ์บ๋ฆญํฐ๊ฐ ๋ ์ด์ ์ฅ์ ์์๋ก ์ธํ ์คํด ์์ด ๊น๋ํ๊ฒ ๋ณด์ด๋์ง ํ์ธํด ์ฃผ์๋ฉด, ๊ธฐ์กด 3๋ UX ํญ๋ชฉ(ํ
๋ง ์ค์์ฒ, Gather calm mode, human-first inspector)๊ณผ ํจ๊ป ๋ฏธ์
์๋ฃ๋ก ์ ํํ ์ ์์ต๋๋ค.
์ํ: active โ b68 ๋ฐํ ์๋ฃ, Son ํ์ธ ๋๊ธฐ์ค
๐ ๋์๋ณด๋: http://hermes-mac-mini.tail46b3c6.ts.net:8099/agent-pets/
๐ Gather Town: http://hermes-mac-mini.tail46b3c6.ts.net:8099/agent-pets/gather/
|
| 2026-05-19 20-29-53 |
83,044 chars |
2026-05-19_20-29-53.md |
Cron Job: autonomous-agent-lab-v1-orchestrator
Job ID: 35127ff89556
Run Time: 2026-05-19 20:29:53
Schedule: every 15m
Prompt
[IMPORTANT: The user has invoked the "hermes-agent" skill, indicating they want you to follow its instructions. The full skill content is loaded below.]
---
name: hermes-agent
description: "Configure, extend, or contribute to Hermes Agent."
version: 2.1.0
author: Hermes Agent + Teknium
license: MIT
platforms: [linux, macos, windows]
metadata:
hermes:
tags: [hermes, setup, configuration, multi-agent, spawning, cli, gateway, development]
homepage: https://github.com/NousResearch/hermes-agent
related_skills: [claude-code, codex, opencode]
---
Hermes Agent
Hermes Agent is an open-source AI agent framework by Nous Research that runs in your terminal, messaging platforms, and IDEs. It belongs to the same category as Claude Code (Anthropic), Codex (OpenAI), and OpenClaw โ autonomous coding and task-execution agents that use tool calling to interact with your system. Hermes works with any LLM provider (OpenRouter, Anthropic, OpenAI, DeepSeek, local models, and 15+ others) and runs on Linux, macOS, and WSL.
What makes Hermes different:
- Self-improving through skills โ Hermes learns from experience by saving reusable procedures as skills. When it solves a complex problem, discovers a workflow, or gets corrected, it can persist that knowledge as a skill document that loads into future sessions. Skills accumulate over time, making the agent better at your specific tasks and environment.
- Persistent memory across sessions โ remembers who you are, your preferences, environment details, and lessons learned. Pluggable memory backends (built-in, Honcho, Mem0, and more) let you choose how memory works.
- Multi-platform gateway โ the same agent runs on Telegram, Discord, Slack, WhatsApp, Signal, Matrix, Email, and 10+ other platforms with full tool access, not just chat.
- Provider-agnostic โ swap models and providers mid-workflow without changing anything else. Credential pools rotate across multiple API keys automatically.
- Profiles โ run multiple independent Hermes instances with isolated configs, sessions, skills, and memory.
- Extensible โ plugins, MCP servers, custom tools, webhook triggers, cron scheduling, and the full Python ecosystem.
People use Hermes for software development, research, system administration, data analysis, content creation, home automation, and anything else that benefits from an AI agent with persistent context and full system access.
This skill helps you work with Hermes Agent effectively โ setting it up, configuring features, spawning additional agent instances, troubleshooting issues, finding the right commands and settings, and understanding how the system works when you need to extend or contribute to it.
Docs: https://hermes-agent.nousresearch.com/docs/
Quick Start
Install
curl -fsSL https://raw.githubusercontent.com/NousResearch/hermes-agent/main/scripts/install.sh | bash
Interactive chat (default)
hermes
Single query
hermes chat -q "What is the capital of France?"
Setup wizard
hermes setup
Change model/provider
hermes model
Check health
hermes doctor
---
CLI Reference
Global Flags
hermes [flags] [command]
--version, -V Show version
--resume, -r SESSION Resume session by ID or title
--continue, -c [NAME] Resume by name, or most recent session
--worktree, -w Isolated git worktree mode (parallel agents)
--skills, -s SKILL Preload skills (comma-separate or repeat)
--profile, -p NAME Use a named profile
--yolo Skip dangerous command approval
--pass-session-id Include session ID in system prompt
No subcommand defaults to chat.
Chat
hermes chat [flags]
-q, --query TEXT Single query, non-interactive
-m, --model MODEL Model (e.g. anthropic/claude-sonnet-4)
-t, --toolsets LIST Comma-separated toolsets
--provider PROVIDER Force provider (openrouter, anthropic, nous, etc.)
-v, --verbose Verbose output
-Q, --quiet Suppress banner, spinner, tool previews
--checkpoints Enable filesystem checkpoints (/rollback)
--source TAG Session source tag (default: cli)
Configuration
hermes setup [section] Interactive wizard (model|terminal|gateway|tools|agent)
hermes model Interactive model/provider picker
hermes config View current config
hermes config edit Open config.yaml in $EDITOR
hermes config set KEY VAL Set a config value
hermes config path Print config.yaml path
hermes config env-path Print .env path
hermes config check Check for missing/outdated config
hermes config migrate Update config with new options
hermes doctor [--fix] Check dependencies and config
Credential Pools
hermes auth add Interactive credential wizard (oauth, api-key)
hermes auth list [PROVIDER] List pooled credentials
hermes auth remove P INDEX Remove by provider + index
hermes auth reset PROVIDER Clear exhaustion status
hermes logout Clear stored auth
Tools & Skills
hermes tools Interactive tool enable/disable (curses UI)
hermes tools list Show all tools and status
hermes tools enable NAME Enable a toolset
hermes tools disable NAME Disable a toolset
hermes skills list List installed skills
hermes skills search QUERY Search the skills hub
hermes skills install ID Install a skill (ID can be a hub identifier OR a direct https://โฆ/SKILL.md URL; pass --name to override when frontmatter has no name)
hermes skills inspect ID Preview without installing
hermes skills config Enable/disable skills per platform
hermes skills check Check for updates
hermes skills update Update outdated skills
hermes skills uninstall N Remove a hub skill
hermes skills publish PATH Publish to registry
hermes skills browse Browse all available skills
hermes skills tap add REPO Add a GitHub repo as skill source
MCP Servers
hermes mcp serve Run Hermes as an MCP server
hermes mcp add NAME Add an MCP server (--url or --command)
hermes mcp remove NAME Remove an MCP server
hermes mcp list List configured servers
hermes mcp test NAME Test connection
hermes mcp configure NAME Toggle tool selection
Gateway (Messaging Platforms)
hermes gateway run Start gateway foreground
hermes gateway install Install as background service
hermes gateway start/stop Control the service
hermes gateway restart Restart the service
hermes gateway status Check status
hermes gateway setup Configure platforms
Supported platforms: Telegram, Discord, Slack, WhatsApp, Signal, Email, SMS, Matrix, Mattermost, Home Assistant, DingTalk, Feishu, WeCom, BlueBubbles (iMessage), Weixin (WeChat), API Server, Webhooks. Open WebUI connects via the API Server adapter.
Platform docs: https://hermes-agent.nousresearch.com/docs/user-guide/messaging/
Discord-specific walkthrough (token, intents, service install, access control): see references/discord-gateway-setup.md in this skill.
- Per-channel personas and skill bindings: see
references/gateway-channel-personas.md (works on Discord, Slack, Telegram, Mattermost, Matrix).
- For long-running Discord-first operations, purpose-specific channel routing, periodic summaries, weekly Dreaming/audit reports, and log-safety patterns: see
references/discord-operating-planes.md.
- For broad Hermes/LifeOS/SQAF ecosystem audits (cron inventory, live services, dashboards, provider/model warnings, and control-plane gaps), see
references/ecosystem-audit.md.
Sessions
hermes sessions list List recent sessions
hermes sessions browse Interactive picker
hermes sessions export OUT Export to JSONL
hermes sessions rename ID T Rename a session
hermes sessions delete ID Delete a session
hermes sessions prune Clean up old sessions (--older-than N days)
hermes sessions stats Session store statistics
For browser-based viewing of existing Hermes CLI/Discord/cron session transcripts, prefer a lightweight static export from ~/.hermes/state.db into a private web root instead of assuming Open WebUI can browse Hermes' native session store. See references/hermes-session-static-web-viewer.md for the SQLite schema, static HTML export workflow, redaction/truncation cautions, and the user's Mac mini deployment (/hermes-sessions/ under the Tailscale-only ~/hermes-web site).
For cron job execution history, the same static-export pattern applies to ~/.hermes/cron/jobs.json and ~/.hermes/cron/output/{job_id}/*.md. See references/cron-history-web-viewer.md for the cron data model, schedule-dict pitfall, and the user's deployed /cron-history/ dashboard.
Cron Jobs
hermes cron list List jobs (--all for disabled)
hermes cron create SCHED Create: '30m', 'every 2h', '0 9 *'
hermes cron edit ID Edit schedule, prompt, delivery
hermes cron pause/resume ID Control job state
hermes cron run ID Trigger on next tick
hermes cron remove ID Delete a job
hermes cron status Scheduler status
For bounded autonomous lab/orchestrator cron jobs that use file-based state, subagent lanes, artifact publishing, and status transitions (active โ complete/blocked/inactive), see references/autonomous-agent-lab-cron-cycle.md. A reusable verification script template lives at scripts/verify-completion-template.py.
For a worked example of evolving an autonomous lab into a config-driven, themeable, Docker-ready installable product, see references/autonomous-lab-product-architecture.md. For CI, integration testing, pluggable adapter architecture, bounded cycle orchestration, and post-productization patterns, see references/product-maturity-patterns.md.
For the final completion verification checklist โ the explicit audit pattern to run before marking status: complete on an installable-solution mission, see references/autonomous-lab-completion-verification.md.
For the reactivation protocol when a completed lab receives new P0 feedback or the user contradicts a completion claim, see references/autonomous-lab-reactivation-protocol.md.
For the config/CHANGELOG version drift pitfall that occurs when autonomous labs evolve over many cycles, and for the related source vs. published file drift problem where the live web root diverges from the project source, see references/autonomous-lab-version-drift.md.
For adding historical trend tracking (SQLite-backed agent status transitions + vanilla JS SVG sparklines) to an autonomous lab dashboard, see references/history-tracking-sparkline-pattern.md.
For reusable dashboard UX patterns (onboarding tours, data freshness badges, keyboard shortcuts, progressive disclosure inspectors, cross-linking between views), see references/dashboard-ux-patterns.md.
For the aggressive human-first inspector refinement โ when users report that details are hard to understand and the fix is to strip technical labels from the default view โ see references/progressive-disclosure-human-first.md.
For programmatic verification of CSS custom-property theme systems โ catching scoping bugs, confirming theme distinctness, and validating JS switching logic โ see references/theme-system-verification.md.
- For Son's Discord-first autonomous experiments where a channel hosts a repeated multi-agent loop, use the Autonomous Discord Agent Lab pattern: create file-based durable state, a paused cron orchestrator delivered to
discord:<channel_id>, then activate it from a user mission trigger. See references/autonomous-discord-agent-lab.md.
- For verifying that a release package (
tar.gz) is actually installable by third parties and contains no stale artifacts or hardcoded references, see references/release-package-verification.md and the reusable script at scripts/release-verify.sh.
Webhooks
hermes webhook subscribe N Create route at /webhooks/<name>
hermes webhook list List subscriptions
hermes webhook remove NAME Remove a subscription
hermes webhook test NAME Send a test POST
Profiles
hermes profile list List all profiles
hermes profile create NAME Create (--clone, --clone-all, --clone-from)
hermes profile use NAME Set sticky default
hermes profile delete NAME Delete a profile
hermes profile show NAME Show details
hermes profile alias NAME Manage wrapper scripts
hermes profile rename A B Rename a profile
hermes profile export NAME Export to tar.gz
hermes profile import FILE Import from archive
Credential Pools
hermes auth add Interactive credential wizard
hermes auth list [PROVIDER] List pooled credentials
hermes auth remove P INDEX Remove by provider + index
hermes auth reset PROVIDER Clear exhaustion status
Other
hermes insights [--days N] Usage analytics
hermes update Update to latest version
hermes pairing list/approve/revoke DM authorization
hermes plugins list/install/remove Plugin management
hermes honcho setup/status Honcho memory integration (requires honcho plugin)
hermes memory setup/status/off Memory provider config
hermes completion bash|zsh Shell completions
hermes acp ACP server (IDE integration)
hermes claw migrate Migrate from OpenClaw
hermes uninstall Uninstall Hermes
---
Slash Commands (In-Session)
Type these during an interactive chat session. New commands land fairly
often; if something below looks stale, run /help in-session for the
authoritative list or see the [live slash commands reference](https://hermes-agent.nousresearch.com/docs/reference/slash-commands).
The registry of record is hermes_cli/commands.py โ every consumer
(autocomplete, Telegram menu, Slack mapping, /help) derives from it.
Session Control
/new (/reset) Fresh session
/clear Clear screen + new session (CLI)
/retry Resend last message
/undo Remove last exchange
/title [name] Name the session
/compress Manually compress context
/stop Kill background processes
/rollback [N] Restore filesystem checkpoint
/snapshot [sub] Create or restore state snapshots of Hermes config/state (CLI)
/background <prompt> Run prompt in background
/queue <prompt> Queue for next turn
/steer <prompt> Inject a message after the next tool call without interrupting
/agents (/tasks) Show active agents and running tasks
/resume [name] Resume a named session
/goal [text|sub] Set a standing goal Hermes works on across turns until achieved
(subcommands: status, pause, resume, clear)
/redraw Force a full UI repaint (CLI)
Configuration
/config Show config (CLI)
/model [name] Show or change model
/personality [name] Set personality
/reasoning [level] Set reasoning (none|minimal|low|medium|high|xhigh|show|hide)
/verbose Cycle: off โ new โ all โ verbose
/voice [on|off|tts] Voice mode
/yolo Toggle approval bypass
/busy [sub] Control what Enter does while Hermes is working (CLI)
(subcommands: queue, steer, interrupt, status)
/indicator [style] Pick the TUI busy-indicator style (CLI)
(styles: kaomoji, emoji, unicode, ascii)
/footer [on|off] Toggle gateway runtime-metadata footer on final replies
/skin [name] Change theme (CLI)
/statusbar Toggle status bar (CLI)
Tools & Skills
/tools Manage tools (CLI)
/toolsets List toolsets (CLI)
/skills Search/install skills (CLI)
/skill <name> Load a skill into session
/reload-skills Re-scan ~/.hermes/skills/ for added/removed skills
/reload Reload .env variables into the running session (CLI)
/reload-mcp Reload MCP servers
/cron Manage cron jobs (CLI)
/curator [sub] Background skill maintenance (status, run, pin, archive, โฆ)
/kanban [sub] Multi-profile collaboration board (tasks, links, comments)
/plugins List plugins (CLI)
Gateway
/approve Approve a pending command (gateway)
/deny Deny a pending command (gateway)
/restart Restart gateway (gateway)
/sethome Set current chat as home channel (gateway)
/update Update Hermes to latest (gateway)
/topic [sub] Enable or inspect Telegram DM topic sessions (gateway)
/platforms (/gateway) Show platform connection status (gateway)
Utility
/branch (/fork) Branch the current session
/fast Toggle priority/fast processing
/browser Open CDP browser connection
/history Show conversation history (CLI)
/save Save conversation to file (CLI)
/copy [N] Copy the last assistant response to clipboard (CLI)
/paste Attach clipboard image (CLI)
/image Attach local image file (CLI)
Info
/help Show commands
/commands [page] Browse all commands (gateway)
/usage Token usage
/insights [days] Usage analytics
/gquota Show Google Gemini Code Assist quota usage (CLI)
/status Session info (gateway)
/profile Active profile info
/debug Upload debug report (system info + logs) and get shareable links
Exit
/quit (/exit, /q) Exit CLI
---
Key Paths & Config
~/.hermes/config.yaml Main configuration
~/.hermes/.env API keys and secrets
$HERMES_HOME/skills/ Installed skills
~/.hermes/sessions/ Session transcripts
~/.hermes/logs/ Gateway and error logs
~/.hermes/auth.json OAuth tokens and credential pools
~/.hermes/hermes-agent/ Source code (if git-installed)
Profiles use ~/.hermes/profiles/<name>/ with the same layout.
Config Sections
Edit with hermes config edit or hermes config set section.key value.
| Section | Key options |
|---------|-------------|
| model | default, provider, base_url, api_key, context_length |
| agent | max_turns (90), tool_use_enforcement |
| terminal | backend (local/docker/ssh/modal), cwd, timeout (180) |
| compression | enabled, threshold (0.50), target_ratio (0.20) |
| display | skin, tool_progress, show_reasoning, show_cost |
| stt | enabled, provider (local/groq/openai/mistral) |
| tts | provider (edge/elevenlabs/openai/minimax/mistral/neutts) |
| memory | memory_enabled, user_profile_enabled, provider |
| security | tirith_enabled, website_blocklist |
| delegation | model, provider, base_url, api_key, max_iterations (50), reasoning_effort |
| checkpoints | enabled, max_snapshots (50) |
| fallback_model | provider, model, base_url, key_env |
Fallback Providers
Hermes can automatically fail over to a backup provider:model when the primary is unavailable. This is turn-scoped โ each new user message starts with the primary restored; fallback only activates mid-turn when the primary fails.
Configuration ( ~/.hermes/config.yaml):
fallback_model:
provider: opencode-go
model: kimi-k2.6
Or use the interactive manager:
hermes fallback add # interactive picker
hermes fallback list # show fallback chain
hermes fallback remove # remove by index
Legacy note: fallback_model (singular) is the legacy single-fallback key. fallback_providers (list) supports multiple ordered fallbacks. When both exist, fallback_providers takes priority.
Trigger conditions (after exhausting retries where applicable):
- Rate limits (HTTP 429)
- Server errors (HTTP 500, 502, 503)
- Auth failures (HTTP 401, 403) โ immediately
- Not found (HTTP 404) โ immediately
- Invalid / empty responses repeatedly
Supported providers include all standard providers (OpenRouter, Anthropic, OpenCode Go/ Zen, Kimi, etc.) plus custom endpoints with base_url + key_env. Full provider docs: https://hermes-agent.nousresearch.com/docs/integrations/providers
Limitations:
- Subagent delegation does not inherit fallback config
- Cron jobs do not use fallback (use per-job provider/model overrides)
- Auxiliary tasks (vision, compression, etc.) use their own
auxiliary.* provider chain
For a deep-dive with worked examples and model lists, see references/fallback-providers.md.
Full config reference: https://hermes-agent.nousresearch.com/docs/user-guide/configuration
Providers
20+ providers supported. Set via hermes model or hermes setup.
| Provider | Auth | Key env var |
|----------|------|-------------|
| OpenRouter | API key | OPENROUTER_API_KEY |
| Anthropic | API key | ANTHROPIC_API_KEY |
| Nous Portal | OAuth | hermes auth |
| OpenAI Codex | OAuth | hermes auth |
| GitHub Copilot | Token | COPILOT_GITHUB_TOKEN |
| Google Gemini | API key | GOOGLE_API_KEY or GEMINI_API_KEY |
| DeepSeek | API key | DEEPSEEK_API_KEY |
| xAI / Grok | API key | XAI_API_KEY |
| Hugging Face | Token | HF_TOKEN |
| Z.AI / GLM | API key | GLM_API_KEY |
| MiniMax | API key | MINIMAX_API_KEY |
| MiniMax CN | API key | MINIMAX_CN_API_KEY |
| Kimi / Moonshot | API key | KIMI_API_KEY |
| Alibaba / DashScope | API key | DASHSCOPE_API_KEY |
| Xiaomi MiMo | API key | XIAOMI_API_KEY |
| Kilo Code | API key | KILOCODE_API_KEY |
| AI Gateway (Vercel) | API key | AI_GATEWAY_API_KEY |
| OpenCode Zen | API key | OPENCODE_ZEN_API_KEY |
| OpenCode Go | API key | OPENCODE_GO_API_KEY |
| Qwen OAuth | OAuth | hermes auth add qwen-oauth |
| Custom endpoint | Config | model.base_url + model.api_key in config.yaml |
| GitHub Copilot ACP | External | COPILOT_CLI_PATH or Copilot CLI |
Full provider docs: https://hermes-agent.nousresearch.com/docs/integrations/providers
Toolsets
Enable/disable via hermes tools (interactive) or hermes tools enable/disable NAME.
| Toolset | What it provides |
|---------|-----------------|
| web | Web search and content extraction |
| search | Web search only (subset of web) |
| browser | Browser automation (Browserbase, Camofox, or local Chromium) |
| terminal | Shell commands and process management |
| file | File read/write/search/patch |
| code_execution | Sandboxed Python execution |
| vision | Image analysis |
| image_gen | AI image generation |
| video | Video analysis and generation |
| tts | Text-to-speech |
| skills | Skill browsing and management |
| memory | Persistent cross-session memory |
| session_search | Search past conversations |
| delegation | Subagent task delegation |
| cronjob | Scheduled task management |
| clarify | Ask user clarifying questions |
| messaging | Cross-platform message sending |
| todo | In-session task planning and tracking |
| kanban | Multi-agent work-queue tools (gated to workers) |
| debugging | Extra introspection/debug tools (off by default) |
| safe | Minimal, low-risk toolset for locked-down sessions |
| spotify | Spotify playback and playlist control |
| homeassistant | Smart home control (off by default) |
| discord | Discord integration tools |
| discord_admin | Discord admin/moderation tools |
| feishu_doc | Feishu (Lark) document tools |
| feishu_drive | Feishu (Lark) drive tools |
| yuanbao | Yuanbao integration tools |
| rl | Reinforcement learning tools (off by default) |
| moa | Mixture of Agents (off by default) |
Full enumeration lives in toolsets.py as the TOOLSETS dict; _HERMES_CORE_TOOLS is the default bundle most platforms inherit from.
Tool changes take effect on /reset (new session). They do NOT apply mid-conversation to preserve prompt caching.
---
Security & Privacy Toggles
Common "why is Hermes doing X to my output / tool calls / commands?" toggles โ and the exact commands to change them. Most of these need a fresh session (/reset in chat, or start a new hermes invocation) because they're read once at startup.
Secret redaction in tool output
Secret redaction is off by default โ tool output (terminal stdout, read_file, web content, subagent summaries, etc.) passes through unmodified. If the user wants Hermes to auto-mask strings that look like API keys, tokens, and secrets before they enter the conversation context and logs:
hermes config set security.redact_secrets true # enable globally
Restart required. security.redact_secrets is snapshotted at import time โ toggling it mid-session (e.g. via export HERMES_REDACT_SECRETS=true from a tool call) will NOT take effect for the running process. Tell the user to run hermes config set security.redact_secrets true in a terminal, then start a new session. This is deliberate โ it prevents an LLM from flipping the toggle on itself mid-task.
Disable again with:
hermes config set security.redact_secrets false
PII redaction in gateway messages
Separate from secret redaction. When enabled, the gateway hashes user IDs and strips phone numbers from the session context before it reaches the model:
hermes config set privacy.redact_pii true # enable
hermes config set privacy.redact_pii false # disable (default)
Command approval prompts
By default (approvals.mode: manual), Hermes prompts the user before running shell commands flagged as destructive (rm -rf, git reset --hard, etc.). The modes are:
manual โ always prompt (default)
smart โ use an auxiliary LLM to auto-approve low-risk commands, prompt on high-risk
off โ skip all approval prompts (equivalent to --yolo)
hermes config set approvals.mode smart # recommended middle ground
hermes config set approvals.mode off # bypass everything (not recommended)
Per-invocation bypass without changing config:
hermes --yolo โฆ
export HERMES_YOLO_MODE=1
Note: YOLO / approvals.mode: off does NOT turn off secret redaction. They are independent.
Shell hooks allowlist
Some shell-hook integrations require explicit allowlisting before they fire. Managed via ~/.hermes/shell-hooks-allowlist.json โ prompted interactively the first time a hook wants to run.
Disabling the web/browser/image-gen tools
To keep the model away from network or media tools entirely, open hermes tools and toggle per-platform. Takes effect on next session (/reset). See the Tools & Skills section above.
---
Voice & Transcription
STT (Voice โ Text)
Voice messages from messaging platforms are auto-transcribed.
Provider priority (auto-detected):
1. Local faster-whisper โ free, no API key: pip install faster-whisper
2. Groq Whisper โ free tier: set GROQ_API_KEY
3. OpenAI Whisper โ paid: set VOICE_TOOLS_OPENAI_KEY
4. Mistral Voxtral โ set MISTRAL_API_KEY
Config:
stt:
enabled: true
provider: local # local, groq, openai, mistral
local:
model: base # tiny, base, small, medium, large-v3
TTS (Text โ Voice)
| Provider | Env var | Free? |
|----------|---------|-------|
| Edge TTS | None | Yes (default) |
| ElevenLabs | ELEVENLABS_API_KEY | Free tier |
| OpenAI | VOICE_TOOLS_OPENAI_KEY | Paid |
| MiniMax | MINIMAX_API_KEY | Paid |
| Mistral (Voxtral) | MISTRAL_API_KEY | Paid |
| NeuTTS (local) | None (pip install neutts[all] + espeak-ng) | Free |
Voice commands: /voice on (voice-to-voice), /voice tts (always voice), /voice off.
---
Spawning Additional Hermes Instances
Run additional Hermes processes as fully independent subprocesses โ separate sessions, tools, and environments.
When to Use This vs delegate_task
| | delegate_task | Spawning hermes process |
|-|-----------------|--------------------------|
| Isolation | Separate conversation, shared process | Fully independent process |
| Duration | Minutes (bounded by parent loop) | Hours/days |
| Tool access | Subset of parent's tools | Full tool access |
| Interactive | No | Yes (PTY mode) |
| Use case | Quick parallel subtasks | Long autonomous missions |
One-Shot Mode
terminal(command="hermes chat -q 'Research GRPO papers and write summary to ~/research/grpo.md'", timeout=300)
Background for long tasks:
terminal(command="hermes chat -q 'Set up CI/CD for ~/myapp'", background=true)
Interactive PTY Mode (via tmux)
Hermes uses prompt_toolkit, which requires a real terminal. Use tmux for interactive spawning:
Start
terminal(command="tmux new-session -d -s agent1 -x 120 -y 40 'hermes'", timeout=10)
Wait for startup, then send a message
terminal(command="sleep 8 && tmux send-keys -t agent1 'Build a FastAPI auth service' Enter", timeout=15)
Read output
terminal(command="sleep 20 && tmux capture-pane -t agent1 -p", timeout=5)
Send follow-up
terminal(command="tmux send-keys -t agent1 'Add rate limiting middleware' Enter", timeout=5)
Exit
terminal(command="tmux send-keys -t agent1 '/exit' Enter && sleep 2 && tmux kill-session -t agent1", timeout=10)
Multi-Agent Coordination
Agent A: backend
terminal(command="tmux new-session -d -s backend -x 120 -y 40 'hermes -w'", timeout=10)
terminal(command="sleep 8 && tmux send-keys -t backend 'Build REST API for user management' Enter", timeout=15)
Agent B: frontend
terminal(command="tmux new-session -d -s frontend -x 120 -y 40 'hermes -w'", timeout=10)
terminal(command="sleep 8 && tmux send-keys -t frontend 'Build React dashboard for user management' Enter", timeout=15)
Check progress, relay context between them
terminal(command="tmux capture-pane -t backend -p | tail -30", timeout=5)
terminal(command="tmux send-keys -t frontend 'Here is the API schema from the backend agent: ...' Enter", timeout=5)
Session Resume
Resume most recent session
terminal(command="tmux new-session -d -s resumed 'hermes --continue'", timeout=10)
Resume specific session
terminal(command="tmux new-session -d -s resumed 'hermes --resume 20260225_143052_a1b2c3'", timeout=10)
Tips
- Prefer
delegate_task for quick subtasks โ less overhead than spawning a full process
- Use
-w (worktree mode) when spawning agents that edit code โ prevents git conflicts
- Set timeouts for one-shot mode โ complex tasks can take 5-10 minutes
- Use
hermes chat -q for fire-and-forget โ no PTY needed
- Use tmux for interactive sessions โ raw PTY mode has
\r vs \n issues with prompt_toolkit
- For scheduled tasks, use the
cronjob tool instead of spawning โ handles delivery and retry
---
Durable & Background Systems
Four systems run alongside the main conversation loop. Quick reference
here; full developer notes live in AGENTS.md, user-facing docs under
website/docs/user-guide/features/.
Delegation (delegate_task)
Synchronous subagent spawn โ the parent waits for the child's summary
before continuing its own loop. Isolated context + terminal session.
- Single:
delegate_task(goal, context, toolsets).
- Batch:
delegate_task(tasks=[{goal, ...}, ...]) runs children in
parallel, capped by delegation.max_concurrent_children (default 3).
- Roles:
leaf (default; cannot re-delegate) vs orchestrator
(can spawn its own workers, bounded by delegation.max_spawn_depth).
- Not durable. If the parent is interrupted, the child is
cancelled. For work that must outlive the turn, use cronjob or
terminal(background=True, notify_on_complete=True).
Config: delegation.* in config.yaml.
Tuning max_concurrent_children
Default is 3. Rule of thumb for raising it:
- Light tasks (web search, file grep): up to
6-8
- Medium tasks (code execution, browser):
4-5
- Heavy tasks (builds, large data):
2-3
- Actual bottleneck is usually the API rate limit, not local CPU/RAM. On a 10-core M4 with 16GB RAM, CPU is rarely the constraint.
- Formula: start at
5, raise only if profiling shows idle time between API responses.
Cron (scheduled jobs)
Durable scheduler โ cron/jobs.py + cron/scheduler.py. Drive it via
the cronjob tool, the hermes cron CLI (list, add, edit,
pause, resume, run, remove), or the /cron slash command.
- Schedules: duration (
"30m", "2h"), "every" phrase
( "every monday 9am"), 5-field cron ( "0 9 *"), or ISO timestamp.
- Per-job knobs:
skills, model/provider override, script
(pre-run data collection; no_agent=True makes the script the whole
job), context_from (chain job A's output into job B), workdir
(run in a specific dir with its AGENTS.md / CLAUDE.md loaded),
multi-platform delivery.
- Invariants: 3-minute hard interrupt per run,
.tick.lock file
prevents duplicate ticks across processes, cron sessions pass
skip_memory=True by default, and cron deliveries are framed with a
header/footer instead of being mirrored into the target gateway
session (keeps role alternation intact).
User docs: https://hermes-agent.nousresearch.com/docs/user-guide/features/cron
Curator (skill lifecycle)
Background maintenance for agent-created skills. Tracks usage, marks
idle skills stale, archives stale ones, keeps a pre-run tar.gz backup
so nothing is lost.
- CLI:
hermes curator <verb> โ status, run, pause, resume,
pin, unpin, archive, restore, prune, backup, rollback.
- Slash:
/curator <subcommand> mirrors the CLI.
- Scope: only touches skills with
created_by: "agent" provenance.
Bundled + hub-installed skills are off-limits. Never deletes โ
max destructive action is archive. Pinned skills are exempt from
every auto-transition and every LLM review pass.
- Telemetry: sidecar at
~/.hermes/skills/.usage.json holds
per-skill use_count, view_count, patch_count,
last_activity_at, state, pinned.
Config: curator.* (enabled, interval_hours, min_idle_hours,
stale_after_days, archive_after_days, backup.*).
User docs: https://hermes-agent.nousresearch.com/docs/user-guide/features/curator
Dreaming (periodic memory/skill consolidation)
For Anthropic-style "dreaming" workflows, combine cron + session_search + memory + skills + curator into a scheduled review loop. Start with a weekly, proposal-only report that audits recent sessions, repeated user corrections, memory conflicts, skill patch candidates, and cron/automation improvements. Do not automatically delete/replace memory or patch/archive skills unless the user explicitly approves the proposed changes. See references/weekly-dreaming-routine.md for the recommended prompt, report format, safety policy, and cron creation pattern.
Kanban (multi-agent work queue)
Durable SQLite board for multi-profile / multi-worker collaboration.
Users drive it via hermes kanban <verb>; dispatcher-spawned workers
see a focused kanban_* toolset gated by HERMES_KANBAN_TASK so the
schema footprint is zero outside worker processes.
- CLI verbs (common):
init, create, list (alias ls),
show, assign, link, unlink, comment, complete, block,
unblock, archive, tail. Less common: watch, stats, runs,
log, dispatch, daemon, gc.
- Worker toolset:
kanban_show, kanban_complete, kanban_block,
kanban_heartbeat, kanban_comment, kanban_create, kanban_link.
- Dispatcher runs inside the gateway by default
( kanban.dispatch_in_gateway: true) โ reclaims stale claims,
promotes ready tasks, atomically claims, spawns assigned profiles.
Auto-blocks a task after ~5 consecutive spawn failures.
- Isolation: board is the hard boundary (workers get
HERMES_KANBAN_BOARD pinned in env); tenant is a soft namespace
within a board for workspace-path + memory-key isolation.
User docs: https://hermes-agent.nousresearch.com/docs/user-guide/features/kanban
Log Relay (Hermes โ Discord)
A background Python script that tails ~/.hermes/logs/*.log and batches lines to a Discord channel. Includes session-ID extraction, rate-limit handling, and auto-restart via launchd/systemd. Useful for remote monitoring and audit trails.
- Reference:
references/discord-log-relay.md โ full setup, tuning, macOS/Linux service install, pitfalls.
- Template:
templates/discord-log-relay.py โ copy, set CHANNEL_ID, and deploy.
- Discord operations:
references/discord-operating-planes.md โ channel-purpose routing, periodic-summary vs Dreaming report formats, and safety/cost notes for Discord-first Hermes deployments.
Key pitfall: ask the user about batch frequency upfront rather than defaulting to real-time streaming. Most users prefer 10-minute or hourly batches. High-volume raw logs should be batched, summarized, or stored out-of-band; avoid Discord message storms during error loops.
Weekly Dreaming / Memory Curation
For long-running Hermes deployments, users may want an Anthropic-style "Dreaming" loop: a scheduled review that consolidates experience, proposes memory/skill/cron changes, and identifies what to keep, weaken, archive, or delete. Hermes has the building blocks (sessions, session_search, memory, skills, curator, cron), but the safe default is proposal mode:
1. Inspect recent usage and sessions.
2. Extract repeated success patterns, failure patterns, and user corrections.
3. Propose memory updates/removals without applying them silently.
4. Propose skill patches/archive candidates and cron/reporting improvements.
5. End with explicit approval checkboxes.
Do not silently rewrite or delete memory/skills from a Dreaming report unless the user explicitly authorized automatic application. See references/discord-operating-planes.md for a report template and routing heuristics.
---
Windows-Specific Quirks
Hermes runs natively on Windows (PowerShell, cmd, Windows Terminal, git-bash
mintty, VS Code integrated terminal). Most of it just works, but a handful
of differences between Win32 and POSIX have bitten us โ document new ones
here as you hit them so the next person (or the next session) doesn't
rediscover them from scratch.
Input / Keybindings
Alt+Enter doesn't insert a newline. Windows Terminal intercepts Alt+Enter
at the terminal layer to toggle fullscreen โ the keystroke never reaches
prompt_toolkit. Use Ctrl+Enter instead. Windows Terminal delivers
Ctrl+Enter as LF ( c-j), distinct from plain Enter ( c-m / CR), and the
CLI binds c-j to newline insertion on win32 only (see
_bind_prompt_submit_keys + the Windows-only c-j binding in cli.py).
Side effect: the raw Ctrl+J keystroke also inserts a newline on Windows โ
unavoidable, because Windows Terminal collapses Ctrl+Enter and Ctrl+J to
the same keycode at the Win32 console API layer. No conflicting binding
existed for Ctrl+J on Windows, so this is a harmless side effect.
mintty / git-bash behaves the same (fullscreen on Alt+Enter) unless you
disable Alt+Fn shortcuts in Options โ Keys. Easier to just use Ctrl+Enter.
Diagnosing keybindings. Run python scripts/keystroke_diagnostic.py
(repo root) to see exactly how prompt_toolkit identifies each keystroke
in the current terminal. Answers questions like "does Shift+Enter come
through as a distinct key?" (almost never โ most terminals collapse it
to plain Enter) or "what byte sequence is my terminal sending for
Ctrl+Enter?" This is how the Ctrl+Enter = c-j fact was established.
Config / Files
HTTP 400 "No models provided" on first run. config.yaml was saved
with a UTF-8 BOM (common when Windows apps write it). Re-save as UTF-8
without BOM. hermes config edit writes without BOM; manual edits in
Notepad are the usual culprit.
execute_code / Sandbox
WinError 10106 ("The requested service provider could not be loaded
or initialized") from the sandbox child process โ it can't create an
AF_INET socket, so the loopback-TCP RPC fallback fails before
connect(). Root cause is usually not a broken Winsock LSP; it's
Hermes's own env scrubber dropping SYSTEMROOT / WINDIR / COMSPEC
from the child env. Python's socket module needs SYSTEMROOT to locate
mswsock.dll. Fixed via the _WINDOWS_ESSENTIAL_ENV_VARS allowlist in
tools/code_execution_tool.py. If you still hit it, echo os.environ
inside an execute_code block to confirm SYSTEMROOT is set. Full
diagnostic recipe in references/execute-code-sandbox-env-windows.md.
Testing / Contributing
scripts/run_tests.sh doesn't work as-is on Windows โ it looks for
POSIX venv layouts ( .venv/bin/activate). The Hermes-installed venv at
venv/Scripts/ has no pip or pytest either (stripped for install size).
Workaround: install pytest + pytest-xdist + pyyaml into a system Python
3.11 user site, then invoke pytest directly with PYTHONPATH set:
"/c/Program Files/Python311/python" -m pip install --user pytest pytest-xdist pyyaml
export PYTHONPATH="$(pwd)"
"/c/Program Files/Python311/python" -m pytest tests/foo/test_bar.py -v --tb=short -n 0
Use -n 0, not -n 4 โ pyproject.toml's default addopts already
includes -n, and the wrapper's CI-parity guarantees don't apply off POSIX.
POSIX-only tests need skip guards. Common markers already in the codebase:
- Symlinks โ elevated privileges on Windows
0o600 file modes โ POSIX mode bits not enforced on NTFS by default
signal.SIGALRM โ Unix-only (see tests/conftest.py::_enforce_test_timeout)
- Winsock / Windows-specific regressions โ
@pytest.mark.skipif(sys.platform != "win32", ...)
Use the existing skip-pattern style (sys.platform == "win32" or
sys.platform.startswith("win")) to stay consistent with the rest of the
suite.
Path / Filesystem
Line endings. Git may warn LF will be replaced by CRLF the next time
Git touches it. Cosmetic โ the repo's .gitattributes normalizes. Don't
let editors auto-convert committed POSIX-newline files to CRLF.
Forward slashes work almost everywhere. C:/Users/... is accepted by
every Hermes tool and most Windows APIs. Prefer forward slashes in code
and logs โ avoids shell-escaping backslashes in bash.
---
Troubleshooting
Voice not working
1. Check stt.enabled: true in config.yaml
2. Verify provider: pip install faster-whisper or set API key
3. In gateway: /restart. In CLI: exit and relaunch.
Tool not available
1. hermes tools โ check if toolset is enabled for your platform
2. Some tools need env vars (check .env)
3. /reset after enabling tools
Model/provider issues
1. hermes doctor โ check config and dependencies
2. hermes auth add <provider> โ re-authenticate OAuth providers (use --type oauth)
3. Check .env has the right API key
4. Copilot 403: gh auth login tokens do NOT work for Copilot API. You must use the Copilot-specific OAuth device code flow via hermes model โ GitHub Copilot.
Changes not taking effect
- Tools/skills:
/reset starts a new session with updated toolset
- Config changes: In gateway:
/restart. In CLI: exit and relaunch.
- Code changes: Restart the CLI or gateway process
Deployed web dashboard shows stale CSS or theme changes
- Browser cache: Add
?v=N cache-busting query strings to CSS/JS/theme links in HTML.
- Service Worker cache: Bump
CACHE_NAME in sw.js to invalidate old shell caches.
- Data freshness: Use
fetch(url, {cache:'no-store'}) for live JSON feeds.
- Auto-detection: Embed
data-build in <html> and compare server build vs loaded build on page load to show a "new version available" banner. See references/static-site-cache-invalidation.md for the full diagnostic recipe and auto-detection pattern.
- Theme switcher reliability: If theme switching works in Chrome but not Samsung Internet, or feels broken on mobile, see
references/theme-switcher-reliability.md for the create-new-link โ load โ remove-old pattern.
- Emergency recovery: If a bad deploy breaks the main app JS, users need a standalone reset page. See
references/emergency-reset-page.md for a zero-dependency reset.html that clears Service Workers and caches without relying on the main app's JS.
Dashboard inspector feels too technical
- The default inspector view should contain only plain-language sentences: headline, "what they're doing now", "why it matters", and a silent visual progress bar (no text label).
- Move all technical fields (source IDs, confidence scores, progress labels, status slugs, badges) behind a "Show technical details" toggle.
- If users say "details are hard to understand," the fix is to remove more fields from the default view, not to add explanations. Explanations of technical fields are still technical.
- See
references/progressive-disclosure-human-first.md for the aggressive simplification pattern.
Skills not showing
1. hermes skills list โ verify installed
2. hermes skills config โ check platform enablement
3. Load explicitly: /skill name or hermes -s name
Gateway issues
Check logs first:
grep -i "failed to send\|error" ~/.hermes/logs/gateway.log | tail -20
Common gateway problems:
- Gateway dies on SSH logout: Enable linger:
sudo loginctl enable-linger $USER
- Gateway dies on WSL2 close: WSL2 requires
systemd=true in /etc/wsl.conf for systemd services to work. Without it, gateway falls back to nohup (dies when session closes).
- Gateway crash loop: Reset the failed state:
systemctl --user reset-failed hermes-gateway
- macOS: bot shows offline after idle time: The gateway runs as a user agent (
LimitLoadToSessionType=Aqua), so macOS suspends it when the system sleeps. The platform websocket drops and the bot appears offline until the network returns. Fix: keep the Mac awake (System Settings -> Energy -> Prevent automatic sleeping, or caffeinate -d -i -s -u &). Low Power Mode makes this worse, not better. See references/macos-gateway-sleep-disconnect.md for the full diagnostic recipe.
Platform-specific issues
- Discord bot silent: Must enable Message Content Intent in Bot โ Privileged Gateway Intents. See full Discord setup reference:
references/discord-gateway-setup.md.
- Slack bot only works in DMs: Must subscribe to
message.channels event. Without it, the bot ignores public channels.
- Windows-specific issues (
Alt+Enter newline, WinError 10106, UTF-8 BOM config, test suite, line endings): see the dedicated Windows-Specific Quirks section above.
Auxiliary models not working
If auxiliary tasks (vision, compression, session_search) fail silently, the auto provider can't find a backend. Either set OPENROUTER_API_KEY or GOOGLE_API_KEY, or explicitly configure each auxiliary task's provider:
hermes config set auxiliary.vision.provider <your_provider>
hermes config set auxiliary.vision.model <model_name>
Full system auth provisioning
For a one-shot workflow to maximize available credentials โ installing gh, generating SSH keys, configuring git, enabling all Hermes toolsets, and auditing current auth state โ see references/system-auth-setup.md.
Editing large files with patch
When a file is read with read_file(offset=...) (pagination), the tool warns that the view is partial. If you attempt patch without re-reading the full file first, you will likely hit non-unique match errors or corrupt the file. Fix: always call read_file without offset to load the whole file before patching. The tool explicitly warns: "โฆwas last read with offset/limit pagination (partial view). Re-read the whole file before overwriting it." โ heed this warning. For append-only updates (e.g., adding a cycle log entry to state.md), do not use terminal(command="cat >> file << 'EOF'...EOF") โ the terminal tool on macOS/Linux misinterprets heredoc << as backgrounding and fails. Instead, write a short Python script via write_file and execute it with terminal(command="python3 /tmp/script.py"). See references/terminal-heredoc-workaround.md for the full pattern.
Sibling subagent file overwrites
When multiple subagents are running in parallel (e.g. via delegate_task batch mode or kanban worker lanes), a file may be modified by one subagent while another is about to write to it. If you use write_file or patch on a file that was last read before a sibling subagent modified it, your write may silently truncate or revert the sibling's changes. The tool may show a warning like "this file was modified by sibling subagent X but this agent never read it."
Fix:
1. Heed the warning. If the tool reports a sibling modification, re-read the file with read_file before writing.
2. Prefer patch over write_file for partial updates โ patch only changes the matched region and is less likely to wipe unrelated content.
3. If the file is already published/deployed, and the local working copy gets corrupted, recover from the published copy:
cp ~/hermes-web/agent-pets/css/dashboard.css ~/.hermes/autonomous-agent-lab/pixel-pet-ops/web/css/dashboard.css
4. For append-only updates, write a small Python script and execute it rather than using write_file on the whole file.
Prevention: In kanban/multi-agent workflows, assign file-level ownership so only one worker touches each file. If parallel workers must edit the same file, have them write to separate temp files and let the orchestrator merge.
---
Windows-Specific Quirks
| Looking for... | Location |
|----------------|----------|
| Config options | hermes config edit or [Configuration docs](https://hermes-agent.nousresearch.com/docs/user-guide/configuration) |
| Available tools | hermes tools list or [Tools reference](https://hermes-agent.nousresearch.com/docs/reference/tools-reference) |
| Slash commands | /help in session or [Slash commands reference](https://hermes-agent.nousresearch.com/docs/reference/slash-commands) |
| Skills catalog | hermes skills browse or [Skills catalog](https://hermes-agent.nousresearch.com/docs/reference/skills-catalog) |
| Provider setup | hermes model or [Providers guide](https://hermes-agent.nousresearch.com/docs/integrations/providers) |
| Platform setup | hermes gateway setup or [Messaging docs](https://hermes-agent.nousresearch.com/docs/user-guide/messaging/) |
| MCP servers | hermes mcp list or [MCP guide](https://hermes-agent.nousresearch.com/docs/user-guide/features/mcp) |
| Profiles | hermes profile list or [Profiles docs](https://hermes-agent.nousresearch.com/docs/user-guide/profiles) |
| Cron jobs | hermes cron list or [Cron docs](https://hermes-agent.nousresearch.com/docs/user-guide/features/cron) |
| Memory | hermes memory status or [Memory docs](https://hermes-agent.nousresearch.com/docs/user-guide/features/memory) |
| Env variables | hermes config env-path or [Env vars reference](https://hermes-agent.nousresearch.com/docs/reference/environment-variables) |
| CLI commands | hermes --help or [CLI reference](https://hermes-agent.nousresearch.com/docs/reference/cli-commands) |
| Gateway logs | ~/.hermes/logs/gateway.log |
| Session files | ~/.hermes/sessions/ or hermes sessions browse |
| Source code | ~/.hermes/hermes-agent/ |
---
Contributor Quick Reference
For occasional contributors and PR authors. Full developer docs: https://hermes-agent.nousresearch.com/docs/developer-guide/
Project Layout
hermes-agent/
โโโ run_agent.py # AIAgent โ core conversation loop
โโโ model_tools.py # Tool discovery and dispatch
โโโ toolsets.py # Toolset definitions
โโโ cli.py # Interactive CLI (HermesCLI)
โโโ hermes_state.py # SQLite session store
โโโ agent/ # Prompt builder, context compression, memory, model routing, credential pooling, skill dispatch
โโโ hermes_cli/ # CLI subcommands, config, setup, commands
โ โโโ commands.py # Slash command registry (CommandDef)
โ โโโ config.py # DEFAULT_CONFIG, env var definitions
โ โโโ main.py # CLI entry point and argparse
โโโ tools/ # One file per tool
โ โโโ registry.py # Central tool registry
โโโ gateway/ # Messaging gateway
โ โโโ platforms/ # Platform adapters (telegram, discord, etc.)
โโโ cron/ # Job scheduler
โโโ tests/ # ~3000 pytest tests
โโโ website/ # Docusaurus docs site
Config: ~/.hermes/config.yaml (settings), ~/.hermes/.env (API keys).
Adding a Tool (3 files)
1. Create tools/your_tool.py:
import json, os
from tools.registry import registry
def check_requirements() -> bool:
return bool(os.getenv("EXAMPLE_API_KEY"))
def example_tool(param: str, task_id: str = None) -> str:
return json.dumps({"success": True, "data": "..."})
registry.register(
name="example_tool",
toolset="example",
schema={"name": "example_tool", "description": "...", "parameters": {...}},
handler=lambda args, **kw: example_tool(
param=args.get("param", ""), task_id=kw.get("task_id")),
check_fn=check_requirements,
requires_env=["EXAMPLE_API_KEY"],
)
2. Add to toolsets.py โ _HERMES_CORE_TOOLS list.
Auto-discovery: any tools/*.py file with a top-level registry.register() call is imported automatically โ no manual list needed.
All handlers must return JSON strings. Use get_hermes_home() for paths, never hardcode ~/.hermes.
Adding a Slash Command
1. Add CommandDef to COMMAND_REGISTRY in hermes_cli/commands.py
2. Add handler in cli.py โ process_command()
3. (Optional) Add gateway handler in gateway/run.py
All consumers (help text, autocomplete, Telegram menu, Slack mapping) derive from the central registry automatically.
Agent Loop (High Level)
run_conversation():
1. Build system prompt
2. Loop while iterations < max:
a. Call LLM (OpenAI-format messages + tool schemas)
b. If tool_calls โ dispatch each via handle_function_call() โ append results โ continue
c. If text response โ return
3. Context compression triggers automatically near token limit
Testing
python -m pytest tests/ -o 'addopts=' -q # Full suite
python -m pytest tests/tools/ -q # Specific area
- Tests auto-redirect
HERMES_HOME to temp dirs โ never touch real ~/.hermes/
- Run full suite before pushing any change
- Use
-o 'addopts=' to clear any baked-in pytest flags
Windows contributors: scripts/run_tests.sh currently looks for POSIX venvs ( .venv/bin/activate / venv/bin/activate) and will error out on Windows where the layout is venv/Scripts/activate + python.exe. The Hermes-installed venv at venv/Scripts/ also has no pip or pytest โ it's stripped for end-user install size. Workaround: install pytest + pytest-xdist + pyyaml into a system Python 3.11 user site ( /c/Program Files/Python311/python -m pip install --user pytest pytest-xdist pyyaml), then run tests directly:
export PYTHONPATH="$(pwd)"
"/c/Program Files/Python311/python" -m pytest tests/tools/test_foo.py -v --tb=short -n 0
Use -n 0 (not -n 4) because pyproject.toml's default addopts already includes -n, and the wrapper's CI-parity story doesn't apply off-POSIX.
Cross-platform test guards: tests that use POSIX-only syscalls need a skip marker. Common ones already in the codebase:
- Symlink creation โ
@pytest.mark.skipif(sys.platform == "win32", reason="Symlinks require elevated privileges on Windows") (see tests/cron/test_cron_script.py)
- POSIX file modes (0o600, etc.) โ
@pytest.mark.skipif(sys.platform.startswith("win"), reason="POSIX mode bits not enforced on Windows") (see tests/hermes_cli/test_auth_toctou_file_modes.py)
signal.SIGALRM โ Unix-only (see tests/conftest.py::_enforce_test_timeout)
- Live Winsock / Windows-specific regression tests โ
@pytest.mark.skipif(sys.platform != "win32", reason="Windows-specific regression")
Monkeypatching sys.platform is not enough when the code under test also calls platform.system() / platform.release() / platform.mac_ver(). Those functions re-read the real OS independently, so a test that sets sys.platform = "linux" on a Windows runner will still see platform.system() == "Windows" and route through the Windows branch. Patch all three together:
monkeypatch.setattr(sys, "platform", "linux")
monkeypatch.setattr(platform, "system", lambda: "Linux")
monkeypatch.setattr(platform, "release", lambda: "6.8.0-generic")
See tests/agent/test_prompt_builder.py::TestEnvironmentHints for a worked example.
Extending the system prompt's execution-environment block
Factual guidance about the host OS, user home, cwd, terminal backend, and shell (bash vs. PowerShell on Windows) is emitted from agent/prompt_builder.py::build_environment_hints(). This is also where the WSL hint and per-backend probe logic live. The convention:
- Local terminal backend โ emit host info (OS,
$HOME, cwd) + Windows-specific notes (hostname โ username, terminal uses bash not PowerShell).
- Remote terminal backend (anything in
_REMOTE_TERMINAL_BACKENDS: docker, singularity, modal, daytona, ssh, vercel_sandbox, managed_modal) โ suppress host info entirely and describe only the backend. A live uname/whoami/pwd probe runs inside the backend via tools.environments.get_environment(...).execute(...), cached per process in _BACKEND_PROBE_CACHE, with a static fallback if the probe times out.
- Key fact for prompt authoring: when
TERMINAL_ENV != "local", every file tool (read_file, write_file, patch, search_files) runs inside the backend container, not on the host. The system prompt must never describe the host in that case โ the agent can't touch it.
Full design notes, the exact emitted strings, and testing pitfalls:
references/prompt-builder-environment-hints.md.
Refactor-safety pattern (POSIX-equivalence guard): when you extract inline logic into a helper that adds Windows/platform-specific behavior, keep a _legacy_<name> oracle function in the test file that's a verbatim copy of the old code, then parametrize-diff against it. Example: tests/tools/test_code_execution_windows_env.py::TestPosixEquivalence. This locks in the invariant that POSIX behavior is bit-for-bit identical and makes any future drift fail loudly with a clear diff.
Commit Conventions
type: concise subject line
Optional body.
Types: fix:, feat:, refactor:, docs:, chore:
Key Rules
- Never break prompt caching โ don't change context, tools, or system prompt mid-conversation
- Message role alternation โ never two assistant or two user messages in a row
- Use
get_hermes_home() from hermes_constants for all paths (profile-safe)
- Config values go in
config.yaml, secrets go in .env
- New tools need a
check_fn so they only appear when requirements are met
[IMPORTANT: The user has invoked the "kanban-orchestrator" skill, indicating they want you to follow its instructions. The full skill content is loaded below.]
---
name: kanban-orchestrator
description: Decomposition playbook + anti-temptation rules for an orchestrator profile routing work through Kanban. The "don't do the work yourself" rule and the basic lifecycle are auto-injected into every kanban worker's system prompt; this skill is the deeper playbook when you're specifically playing the orchestrator role.
version: 3.0.0
platforms: [linux, macos, windows]
metadata:
hermes:
tags: [kanban, multi-agent, orchestration, routing]
related_skills: [kanban-worker]
---
Kanban Orchestrator โ Decomposition Playbook
> The core worker lifecycle (including the kanban_create fan-out pattern and the "decompose, don't execute" rule) is auto-injected into every kanban process via the KANBAN_GUIDANCE system-prompt block. This skill is the deeper playbook when you're an orchestrator profile whose whole job is routing.
Profiles are user-configured โ not a fixed roster
Hermes setups vary widely. Some users run a single profile that does everything; some run a small fleet (docker-worker, cron-worker); some run a curated specialist team they've named themselves. There is no default specialist roster โ the orchestrator skill does not know what profiles exist on this machine.
Before fanning out, you must ground the decomposition in the profiles that actually exist. The dispatcher silently fails to spawn unknown assignee names โ it doesn't autocorrect, doesn't suggest, doesn't fall back. So a card assigned to researcher on a setup that only has docker-worker just sits in ready forever.
Step 0: discover available profiles before planning.
Use one of these:
hermes profile list โ prints the table of profiles configured on this machine. Run it through your terminal tool if you have one; otherwise ask the user.
kanban_list(assignee="<some-name>") โ sanity-check a single name. Returns an empty list (rather than an error) for an unknown assignee, so this only confirms a name you're already considering.
- Just ask the user. "What profiles do you have set up?" is a fine first turn when the goal needs more than one specialist.
Cache the result in your working memory for the rest of the conversation. Re-asking every turn wastes a tool call.
When to use the board (vs. just doing the work)
Create Kanban tasks when any of these are true:
1. Multiple specialists are needed. Research + analysis + writing is three profiles.
2. The work should survive a crash or restart. Long-running, recurring, or important.
3. The user might want to interject. Human-in-the-loop at any step.
4. Multiple subtasks can run in parallel. Fan-out for speed.
5. Review / iteration is expected. A reviewer profile loops on drafter output.
6. The audit trail matters. Board rows persist in SQLite forever.
If none of those apply โ it's a small one-shot reasoning task โ use delegate_task instead or answer the user directly.
The anti-temptation rules
Your job description says "route, don't execute." The rules that enforce that:
- Do not execute the work yourself. Your restricted toolset usually doesn't even include terminal/file/code/web for implementation. If you find yourself "just fixing this quickly" โ stop and create a task for the right specialist.
- For any concrete task, create a Kanban task and assign it. Every single time.
- Split multi-lane requests before creating cards. A user prompt can contain several independent workstreams. Extract those lanes first, then create one card per lane instead of bundling unrelated work into a single implementer card.
- Run independent lanes in parallel. If two cards do not need each other's output, leave them unlinked so the dispatcher can fan them out. Link only true data dependencies.
- If no specialist fits the available profiles, ask the user which profile to create or which existing profile to use. Do not invent profile names; the dispatcher will silently drop unknown assignees.
- Decompose, route, and summarize โ that's the whole job.
Exception: micro-UI polish cycles
There is one narrow exception where the orchestrator may execute directly instead of creating Kanban cards: tiny UI-only polish cycles (e.g., adding a CSS class, a theme preview dot, a hover state, a cross-link, or a HUD button) that are purely presentational, require no cross-file logic changes, and fit comfortably inside a single bounded cycle with no need for review or parallel work. If the change is limited to HTML/CSS/JS cosmetics, no other profile has a stake in it, and the user did not ask for a design review, the orchestrator should just edit and publish rather than paying the kanban-overhead tax. This exception does NOT apply to architecture changes, adapter logic, plugin interfaces, or anything that touches the data layer.
Decomposition playbook
Step 1 โ Understand the goal
Ask clarifying questions if the goal is ambiguous. Cheap to ask; expensive to spawn the wrong fleet.
Step 2 โ Sketch the task graph
Before creating anything, draft the graph out loud (in your response to the user). Treat every concrete workstream as a candidate card:
1. Extract the lanes from the request.
2. Map each lane to one of the profiles you discovered in Step 0. If a lane doesn't fit any existing profile, ask the user which to use or create.
3. Decide whether each lane is independent or gated by another lane.
4. Create independent lanes as parallel cards with no parent links.
5. Create synthesis/review/integration cards with parent links to the lanes they depend on.
Examples of prompts that should fan out (using placeholder profile names โ substitute whatever exists on the user's setup):
- "Build an app" โ one card to a design-oriented profile for product/UI direction, one or two cards to engineering profiles for implementation, plus a later integration/review card if the user has a reviewer profile.
- "Fix blockers and check model variants" โ one implementation card for the blocker fixes plus one discovery/research card for config/source verification. A final reviewer card can depend on both.
- "Research docs and implement" โ a docs-research card can run in parallel with a codebase-discovery card; implementation waits only if it truly needs those findings.
- "Analyze this screenshot and find the related code" โ one card to a vision-capable profile for the visual analysis while another searches the codebase.
Words like "also," "finally," or "and" do not automatically imply a dependency. They often mean "make sure this is covered before reporting back." Only link tasks when one card cannot start until another card's output exists.
Show the graph to the user before creating cards. Let them correct it โ including which actual profile name should own each lane.
Step 3 โ Create tasks and link
Use the profile names from Step 0. The example below uses placeholders <profile-A>, <profile-B>, <profile-C> โ replace them with what the user actually has.
t1 = kanban_create(
title="research: Postgres cost vs current",
assignee="<profile-A>", # whichever profile handles research on this setup
body="Compare estimated infrastructure costs, migration costs, and ongoing ops costs over a 3-year window. Sources: AWS/GCP pricing, team time estimates, current Postgres bills from peers.",
tenant=os.environ.get("HERMES_TENANT"),
)["task_id"]
t2 = kanban_create(
title="research: Postgres performance vs current",
assignee="<profile-A>", # same profile, run in parallel
body="Compare query latency, throughput, and scaling characteristics at our expected data volume (~500GB, 10k QPS peak). Sources: benchmark papers, public case studies, pgbench results if easy.",
)["task_id"]
t3 = kanban_create(
title="synthesize migration recommendation",
assignee="<profile-B>", # whichever profile does synthesis/analysis
body="Read the findings from T1 (cost) and T2 (performance). Produce a 1-page recommendation with explicit trade-offs and a go/no-go call.",
parents=[t1, t2],
)["task_id"]
t4 = kanban_create(
title="draft decision memo",
assignee="<profile-C>", # whichever profile drafts user-facing prose
body="Turn the analyst's recommendation into a 2-page memo for the CTO. Match the tone of previous decision memos in the team's knowledge base.",
parents=[t3],
)["task_id"]
parents=[...] gates promotion โ children stay in todo until every parent reaches done, then auto-promote to ready. No manual coordination needed; the dispatcher and dependency engine handle it.
Step 4 โ Complete your own task
If you were spawned as a task yourself (e.g. a planner profile was assigned T0: "investigate Postgres migration"), mark it done with a summary of what you created:
kanban_complete(
summary="decomposed into T1-T4: 2 research lanes in parallel, 1 synthesis on their outputs, 1 prose draft on the recommendation",
metadata={
"task_graph": {
"T1": {"assignee": "<profile-A>", "parents": []},
"T2": {"assignee": "<profile-A>", "parents": []},
"T3": {"assignee": "<profile-B>", "parents": ["T1", "T2"]},
"T4": {"assignee": "<profile-C>", "parents": ["T3"]},
},
},
)
Step 5 โ Report back to the user
Tell them what you created in plain prose, naming the actual profiles you used:
> I've queued 4 tasks:
> - T1 (<profile-A>): cost comparison
> - T2 (<profile-A>): performance comparison, in parallel with T1
> - T3 (<profile-B>): synthesizes T1 + T2 into a recommendation
> - T4 (<profile-C>): turns T3 into a CTO memo
>
> The dispatcher will pick up T1 and T2 now. T3 starts when both finish. You'll get a gateway ping when T4 completes. Use the dashboard or hermes kanban tail <id> to follow along.
Common patterns
Fan-out + fan-in (research โ synthesize): N research-style cards with no parents, one synthesis card with all of them as parents.
Parallel implementation + validation: one implementer card makes the change while one explorer/researcher card verifies config, docs, or source mapping. A reviewer card can depend on both. Do not make the implementer own unrelated verification just because the user mentioned both in one sentence.
Pipeline with gates: planner โ implementer โ reviewer. Each stage's parents=[previous_task]. Reviewer blocks or completes; if reviewer blocks, the operator unblocks with feedback and respawns.
Same-profile queue: N tasks, all assigned to the same profile, no dependencies between them. Dispatcher serializes โ that profile processes them in priority order, accumulating experience in its own memory.
Parallel UI/frontend lanes: When the goal touches multiple independent HTML/CSS/JS files (e.g., a dashboard page and a 2D gather view), fan out to separate subagents per file. Each lane edits its own file, then the orchestrator integrates, fixes cross-file references (theme paths, shared JSON endpoints), and publishes. This avoids merge conflicts in single-file HTML dashboards and keeps each subagent's context focused. See references/parallel-ui-lanes-and-publishing.md for the post-subagent integration checklist and rsync safety notes.
Human-in-the-loop: Any task can kanban_block() to wait for input. Dispatcher respawns after /unblock. The comment thread carries the full context.
Pitfalls
Inventing profile names that don't exist. The dispatcher silently fails to spawn unknown assignees โ the card just sits in ready forever. Always assign to a profile from your Step 0 discovery; ask the user if you're unsure.
Bundling independent lanes into one card. If the user asks for two independent outcomes, create two cards. Example: "fix blockers and check model variants" is not one fixer task; create a fixer/engineer card for the fixes and an explorer/researcher card for the variant check, then optionally gate review on both.
Over-linking because of wording. "Finally check X" may still be parallel with implementation if X is static config, docs, or source discovery. Link it after implementation only when the check depends on the implementation result.
Forgetting dependency links. If the task graph says research -> implement -> review, do not create all tasks as independent ready cards. Use parent links so implement/review cannot run before their inputs exist.
Reassignment vs. new task. If a reviewer blocks with "needs changes," create a NEW task linked from the reviewer's task โ don't re-run the same task with a stern look. The new task is assigned to the original implementer profile.
Argument order for links. kanban_link(parent_id=..., child_id=...) โ parent first. Mixing them up demotes the wrong task to todo.
Ignoring explicit user feedback to keep building infrastructure. When the user says a specific UX issue (legibility, theme switching, movement density) is "immediate priority," treat it as P0 and route it before deeper packaging/architecture work. Infrastructure polish feels productive, but shipping user-visible fixes is what matters. Create cards for the UX feedback first, then resume infrastructure lanes.
Treating status: complete as immutable when user feedback says otherwise. A state.md that says status: complete does not override a user's report that a completion criterion is actually broken. If the user says "theme switching is not working" and the Final Completion Condition requires "working UI theme switcher," the mission is not complete. Reactivate immediately: set status: active, append a reactivation cycle log, and fix the issue. Do not burn cycles on post-complete verification while the user is reporting active defects.
Don't pre-create the whole graph if the shape depends on intermediate findings. If T3's structure depends on what T1 and T2 find, let T3 exist as a "synthesize findings" task whose own first step is to read parent handoffs and plan the rest. Orchestrators can spawn orchestrators.
Tenant inheritance. If HERMES_TENANT is set in your env, pass tenant=os.environ.get("HERMES_TENANT") on every kanban_create call so child tasks stay in the same namespace.
Verifying cross-file references after directory reorganization. When subagents edit HTML/CSS/JS files and the directory structure shifts (e.g., moving files from root into web/dashboard/ and web/gather/), relative asset paths ( themes/default/theme.css, ./ops-data.json) often break. After subagents finish, the orchestrator must grep for href= and src= in moved files and fix relative paths before publishing. Subagents don't know the final publish layout โ the orchestrator does.
Destructive sync wipes needed files. Commands like rsync -av --delete will delete destination files that aren't in the source list. If you publish a directory tree piecemeal (e.g., copy web/dashboard/ first, then web/gather/ separately), --delete on the first rsync will erase the gather files before the second rsync runs. Either list all source paths in a single rsync invocation, or omit --delete and use cp -r / rsync -av without deletion when doing staged copies.
Recovering stuck workers
When a worker profile keeps crashing, hallucinating, or getting blocked by its own mistakes (usually: wrong model, missing skill, broken credential), the kanban dashboard flags the task with a โ badge and opens a Recovery section in the drawer. Three primary actions:
1. Reclaim (or hermes kanban reclaim <task_id>) โ abort the running worker immediately and reset the task to ready. The existing claim TTL is ~15 min; this is the fast path out.
2. Reassign (or hermes kanban reassign <task_id> <new-profile> --reclaim) โ switch the task to a different profile (one that exists on this setup) and let the dispatcher pick it up with a fresh worker.
3. Change profile model โ the dashboard prints a copy-paste hint for hermes -p <profile> model since profile config lives on disk; edit it in a terminal, then Reclaim to retry with the new model.
Hallucination warnings appear on tasks where a worker's kanban_complete(created_cards=[...]) claim included card ids that don't exist or weren't created by the worker's profile (the gate blocks the completion), or where the free-form summary references t_<hex> ids that don't resolve (advisory prose scan, non-blocking). Both produce audit events that persist even after recovery actions โ the trail stays for debugging.
The user has provided the following instruction alongside the skill invocation: [IMPORTANT: You are running as a scheduled cron job. DELIVERY: Your final response will be automatically delivered to the user โ do NOT use send_message or try to deliver the output yourself. Just produce your report/output as your final response and the system handles the rest. SILENT: If there is genuinely nothing new to report, respond with exactly "[SILENT]" (nothing else) to suppress delivery. Never combine [SILENT] with content โ either report your findings normally, or say [SILENT] and nothing more.]
You are the 15-minute Orchestrator for Son's Autonomous Agent Lab v1, reporting to Discord channel ID 1505805763824586952.
Durable state path: /Users/jooho-hermes/.hermes/autonomous-agent-lab/state.md
Working directory for experiment artifacts: /Users/jooho-hermes/.hermes/autonomous-agent-lab/
Preferred published web root: /Users/jooho-hermes/hermes-web/agent-pets/
Top-level directive from Son:
- The project has evolved from a personal dashboard into an INSTALLABLE PRODUCT that external Hermes users can deploy.
- The final target is a self-contained, configurable, publishable solution: "Hermes Pixel Pet Ops Office".
- Do NOT shrink the mission into a small static MVP and autonomously stop.
- The Gather.town-style 2D spatial office is a first-class feature, not a side page.
Latest UX feedback from Son (treat as immediate priority before deeper packaging work):
- Details are hard for a human to understand. Add human-first summaries, plain-language labels, and progressive disclosure: summary first, technical details second.
- Gather Town version has too many agents roaming around. Reduce default movement, add density/speed controls, cluster agents by room/task, and add focus/calm mode.
- Theme switching is not visibly working. Implement real UI theme switcher with persistence and clear visual theme changes.
Key product requirements (installable solution level):
1. Config-driven architecture: all paths, URLs, colors, names, room layouts via config.yaml. No hardcoded references to jooho-hermes.
2. Self-contained package: clear directory structure (src/, web/, config/, docs/, scripts/), install script, requirements.txt.
3. Pluggable data adapter: support multiple backends via plugin architecture.
4. Themeable frontend: CSS variables driven from config, swappable themes, plus a working UI theme switcher.
5. Multi-tenant ready: works for any Hermes instance.
6. Build/Deploy ready: Dockerfile or docker-compose, or clear static-server setup.
7. Documentation: README, architecture docs, configuration reference, contributor guide.
8. Human-comprehensible UX: plain-language summaries and progressive disclosure for technical detail.
9. Gather.town calm mode: adjustable movement density/speed and less chaotic defaults.
10. Versioned releases: CHANGELOG.md, semantic versioning, release packaging.
Mission model:
- Read state.md first before doing anything else.
- If state.md says
status: inactive or has no Current Mission, do not invent work. Return exactly: ๐ก Autonomous Agent Lab ๋๊ธฐ์ค โ Son์ด ํธ๋ฆฌ๊ฑฐ/๋ฏธ์
์ ์ฃผ๋ฉด 15๋ถ ์ฌ์ดํด์ ์์ํฉ๋๋ค.
- If state.md says
status: active, run one bounded 15-minute cycle toward the full installable solution.
- If state.md says
status: complete, verify that the Final Completion Condition in state.md is truly met. If it is not fully met, reactivate or report that state needs correction.
Cycle procedure when active:
1. Read state.md first. Extract current mission, constraints, previous cycle log, and Final Completion Condition.
2. Decide the next smallest useful step toward installable solution quality. Focus on: architecture, configurability, documentation, and clean separation of concerns.
3. Use delegate_task for independent subagent lanes when helpful.
4. Prefer concrete progress: refactor to config-driven, add install scripts, create docs, add Docker support, theme system, plugin architecture.
5. Update state.md with a new cycle log entry before final reporting.
6. Completion rule: only set status: complete when every item under state.md Final Completion Condition is satisfied. A non-installable MVP is not complete.
7. Stop/block only if Son explicitly stops/redirects, a safety boundary is reached, or a hard blocker needs Son's decision.
Link requirement (never forget):
- Every cycle report MUST include at least one direct viewable link to the published dashboard/artifact.
- The canonical URL:
http://hermes-mac-mini.tail46b3c6.ts.net:8099/agent-pets/
- Include gather town URL too:
http://hermes-mac-mini.tail46b3c6.ts.net:8099/agent-pets/gather/
Final Discord message format:
[Autonomous Agent Lab v1 / Cycle N]
๋ชฉํ:
์ํ:
๊ฒฐ๊ณผ:
๊ฒ์ฆ:
๋ค์:
์ํ:
Safety/quality rules:
- Do not handle secrets, passwords, API keys, payment, permission dialogs, or destructive commands.
- Do not claim completion without updating state.md.
- Do not rely on Discord history as durable state.
- Do not spam raw logs; summarize lane outputs and verification.
- Keep working in /Users/jooho-hermes/.hermes/autonomous-agent-lab/ and publish only to /Users/jooho-hermes/hermes-web/agent-pets/ unless the state file says otherwise.
Design/UX priorities:
- Mobile responsiveness is first-class.
- Character animation/movement is desired.
- Every cycle report must include published links.
- This is now a product engineering mission. Architecture, configurability, and documentation matter as much as visuals.
Response
[Autonomous Agent Lab v1 / Cycle 69]
๋ชฉํ:
15๋ถ ์ค์ผ์ค ํฑ์์ ํ์ค ์ํ ์ ๊ฒ ์ํ. ์ ์ฒด ํ์ดํ๋ผ์ธ ๊ฑด๊ฐ์ฑ ํ์ธ ๋ฐ Son์ ๋ธ๋ผ์ฐ์ ์ธก UX ํ์ธ ๋๊ธฐ.
์ํ:
1. ๋ฐ์ดํฐ ์ด๋ํฐ ์๋ ์คํ ๋ฐ ๊ฒ์ฆ
2. ํตํฉ ํ
์คํธ(128๊ฐ) ๋ฐ ์ค์น ๊ฒ์ฆ(21๊ฐ) ์ ์ฒด ํต๊ณผ ํ์ธ
3. ๊ฒ์๋ ops-data.json/ health.json ์ ์ ๋ ํ์ธ
4. LaunchAgent ๋ก๊ทธ( refresh.out.log) ๋ฐ ์๋ฌ ๋ก๊ทธ( refresh.err.log) ์ ๊ฒ
5. state.md์ Cycle 69 ๋ก๊ทธ ๊ธฐ๋ก ๋ฐ cycle_count: 69 ๊ฐฑ์
๊ฒฐ๊ณผ:
- ์ด๋ํฐ:
exit 0, 32 agents / 15 cron jobs / 20 sessions / 16 events / schema 1.4
- ํตํฉ ํ
์คํธ: 128/128 passed
- ์ค์น ๊ฒ์ฆ: 21/21 passed
ops-data.json mtime: 2026-05-19 20:26:30 (์ ์ )
health.json: status=healthy, version=1.4.4
refresh.err.log: ๋น์ด ์์ (์๋ฌ ์์)
- ํ๋์ฝ๋ฉ๋
jooho-hermes ์ฐธ์กฐ: 0๊ฑด
๊ฒ์ฆ:
- 11๊ฐ ์ต์ข
์๋ฃ ์กฐ๊ฑด ๋ชจ๋ ์ถฉ์กฑ ์ํ ์ ์ง
- Son์ ์์ 3๊ฐ UX ํผ๋๋ฐฑ์ด ์์ค ์ฝ๋์์์ ์์ ์๋ฃ๋จ์ ์ฌํ์ธ
- ํ
๋ง ์ ํ ๊ฐ์์ฑ โ
- Gather Town ์ฐจ๋ถ ๋ชจ๋ โ
- ์ฌ๋ ์ค์ฌ ์์ธ ์ ๋ณด โ
๋ค์:
- Son์ด ๋์๋ณด๋์ ์ ์ํ์ฌ
v1.4.4 ยท b67 ๋ฐฐ์ง ํ์ธ ํ, ํ
๋ง ์ ํ / Gather Town ์ฐจ๋ถ ๋ชจ๋ / Inspector ์ฌ๋ ์ค์ฌ ๋ทฐ 3๊ฐ์ง๋ฅผ ๋ธ๋ผ์ฐ์ ์์ ์ง์ ํ
์คํธ
- 3๊ฐ์ง ๋ชจ๋ ๋ง์กฑ ์
status: complete๋ก ์ ํ ๊ฐ๋ฅ
์ํ:
active โ ๋ชจ๋ ๊ธฐ์ ๊ธฐ์ค ์ถฉ์กฑ. Son์ ๋ธ๋ผ์ฐ์ ์ธก ํ์ธ ๋๊ธฐ ์ค.
๋งํฌ:
- ๋์๋ณด๋: http://hermes-mac-mini.tail46b3c6.ts.net:8099/agent-pets/
- Gather Town: http://hermes-mac-mini.tail46b3c6.ts.net:8099/agent-pets/gather/
|
| 2026-05-19 20-08-53 |
83,082 chars |
2026-05-19_20-08-53.md |
Cron Job: autonomous-agent-lab-v1-orchestrator
Job ID: 35127ff89556
Run Time: 2026-05-19 20:08:53
Schedule: every 15m
Prompt
[IMPORTANT: The user has invoked the "hermes-agent" skill, indicating they want you to follow its instructions. The full skill content is loaded below.]
---
name: hermes-agent
description: "Configure, extend, or contribute to Hermes Agent."
version: 2.1.0
author: Hermes Agent + Teknium
license: MIT
platforms: [linux, macos, windows]
metadata:
hermes:
tags: [hermes, setup, configuration, multi-agent, spawning, cli, gateway, development]
homepage: https://github.com/NousResearch/hermes-agent
related_skills: [claude-code, codex, opencode]
---
Hermes Agent
Hermes Agent is an open-source AI agent framework by Nous Research that runs in your terminal, messaging platforms, and IDEs. It belongs to the same category as Claude Code (Anthropic), Codex (OpenAI), and OpenClaw โ autonomous coding and task-execution agents that use tool calling to interact with your system. Hermes works with any LLM provider (OpenRouter, Anthropic, OpenAI, DeepSeek, local models, and 15+ others) and runs on Linux, macOS, and WSL.
What makes Hermes different:
- Self-improving through skills โ Hermes learns from experience by saving reusable procedures as skills. When it solves a complex problem, discovers a workflow, or gets corrected, it can persist that knowledge as a skill document that loads into future sessions. Skills accumulate over time, making the agent better at your specific tasks and environment.
- Persistent memory across sessions โ remembers who you are, your preferences, environment details, and lessons learned. Pluggable memory backends (built-in, Honcho, Mem0, and more) let you choose how memory works.
- Multi-platform gateway โ the same agent runs on Telegram, Discord, Slack, WhatsApp, Signal, Matrix, Email, and 10+ other platforms with full tool access, not just chat.
- Provider-agnostic โ swap models and providers mid-workflow without changing anything else. Credential pools rotate across multiple API keys automatically.
- Profiles โ run multiple independent Hermes instances with isolated configs, sessions, skills, and memory.
- Extensible โ plugins, MCP servers, custom tools, webhook triggers, cron scheduling, and the full Python ecosystem.
People use Hermes for software development, research, system administration, data analysis, content creation, home automation, and anything else that benefits from an AI agent with persistent context and full system access.
This skill helps you work with Hermes Agent effectively โ setting it up, configuring features, spawning additional agent instances, troubleshooting issues, finding the right commands and settings, and understanding how the system works when you need to extend or contribute to it.
Docs: https://hermes-agent.nousresearch.com/docs/
Quick Start
Install
curl -fsSL https://raw.githubusercontent.com/NousResearch/hermes-agent/main/scripts/install.sh | bash
Interactive chat (default)
hermes
Single query
hermes chat -q "What is the capital of France?"
Setup wizard
hermes setup
Change model/provider
hermes model
Check health
hermes doctor
---
CLI Reference
Global Flags
hermes [flags] [command]
--version, -V Show version
--resume, -r SESSION Resume session by ID or title
--continue, -c [NAME] Resume by name, or most recent session
--worktree, -w Isolated git worktree mode (parallel agents)
--skills, -s SKILL Preload skills (comma-separate or repeat)
--profile, -p NAME Use a named profile
--yolo Skip dangerous command approval
--pass-session-id Include session ID in system prompt
No subcommand defaults to chat.
Chat
hermes chat [flags]
-q, --query TEXT Single query, non-interactive
-m, --model MODEL Model (e.g. anthropic/claude-sonnet-4)
-t, --toolsets LIST Comma-separated toolsets
--provider PROVIDER Force provider (openrouter, anthropic, nous, etc.)
-v, --verbose Verbose output
-Q, --quiet Suppress banner, spinner, tool previews
--checkpoints Enable filesystem checkpoints (/rollback)
--source TAG Session source tag (default: cli)
Configuration
hermes setup [section] Interactive wizard (model|terminal|gateway|tools|agent)
hermes model Interactive model/provider picker
hermes config View current config
hermes config edit Open config.yaml in $EDITOR
hermes config set KEY VAL Set a config value
hermes config path Print config.yaml path
hermes config env-path Print .env path
hermes config check Check for missing/outdated config
hermes config migrate Update config with new options
hermes doctor [--fix] Check dependencies and config
Credential Pools
hermes auth add Interactive credential wizard (oauth, api-key)
hermes auth list [PROVIDER] List pooled credentials
hermes auth remove P INDEX Remove by provider + index
hermes auth reset PROVIDER Clear exhaustion status
hermes logout Clear stored auth
Tools & Skills
hermes tools Interactive tool enable/disable (curses UI)
hermes tools list Show all tools and status
hermes tools enable NAME Enable a toolset
hermes tools disable NAME Disable a toolset
hermes skills list List installed skills
hermes skills search QUERY Search the skills hub
hermes skills install ID Install a skill (ID can be a hub identifier OR a direct https://โฆ/SKILL.md URL; pass --name to override when frontmatter has no name)
hermes skills inspect ID Preview without installing
hermes skills config Enable/disable skills per platform
hermes skills check Check for updates
hermes skills update Update outdated skills
hermes skills uninstall N Remove a hub skill
hermes skills publish PATH Publish to registry
hermes skills browse Browse all available skills
hermes skills tap add REPO Add a GitHub repo as skill source
MCP Servers
hermes mcp serve Run Hermes as an MCP server
hermes mcp add NAME Add an MCP server (--url or --command)
hermes mcp remove NAME Remove an MCP server
hermes mcp list List configured servers
hermes mcp test NAME Test connection
hermes mcp configure NAME Toggle tool selection
Gateway (Messaging Platforms)
hermes gateway run Start gateway foreground
hermes gateway install Install as background service
hermes gateway start/stop Control the service
hermes gateway restart Restart the service
hermes gateway status Check status
hermes gateway setup Configure platforms
Supported platforms: Telegram, Discord, Slack, WhatsApp, Signal, Email, SMS, Matrix, Mattermost, Home Assistant, DingTalk, Feishu, WeCom, BlueBubbles (iMessage), Weixin (WeChat), API Server, Webhooks. Open WebUI connects via the API Server adapter.
Platform docs: https://hermes-agent.nousresearch.com/docs/user-guide/messaging/
Discord-specific walkthrough (token, intents, service install, access control): see references/discord-gateway-setup.md in this skill.
- Per-channel personas and skill bindings: see
references/gateway-channel-personas.md (works on Discord, Slack, Telegram, Mattermost, Matrix).
- For long-running Discord-first operations, purpose-specific channel routing, periodic summaries, weekly Dreaming/audit reports, and log-safety patterns: see
references/discord-operating-planes.md.
- For broad Hermes/LifeOS/SQAF ecosystem audits (cron inventory, live services, dashboards, provider/model warnings, and control-plane gaps), see
references/ecosystem-audit.md.
Sessions
hermes sessions list List recent sessions
hermes sessions browse Interactive picker
hermes sessions export OUT Export to JSONL
hermes sessions rename ID T Rename a session
hermes sessions delete ID Delete a session
hermes sessions prune Clean up old sessions (--older-than N days)
hermes sessions stats Session store statistics
For browser-based viewing of existing Hermes CLI/Discord/cron session transcripts, prefer a lightweight static export from ~/.hermes/state.db into a private web root instead of assuming Open WebUI can browse Hermes' native session store. See references/hermes-session-static-web-viewer.md for the SQLite schema, static HTML export workflow, redaction/truncation cautions, and the user's Mac mini deployment (/hermes-sessions/ under the Tailscale-only ~/hermes-web site).
For cron job execution history, the same static-export pattern applies to ~/.hermes/cron/jobs.json and ~/.hermes/cron/output/{job_id}/*.md. See references/cron-history-web-viewer.md for the cron data model, schedule-dict pitfall, and the user's deployed /cron-history/ dashboard.
Cron Jobs
hermes cron list List jobs (--all for disabled)
hermes cron create SCHED Create: '30m', 'every 2h', '0 9 *'
hermes cron edit ID Edit schedule, prompt, delivery
hermes cron pause/resume ID Control job state
hermes cron run ID Trigger on next tick
hermes cron remove ID Delete a job
hermes cron status Scheduler status
For bounded autonomous lab/orchestrator cron jobs that use file-based state, subagent lanes, artifact publishing, and status transitions (active โ complete/blocked/inactive), see references/autonomous-agent-lab-cron-cycle.md. A reusable verification script template lives at scripts/verify-completion-template.py.
For a worked example of evolving an autonomous lab into a config-driven, themeable, Docker-ready installable product, see references/autonomous-lab-product-architecture.md. For CI, integration testing, pluggable adapter architecture, bounded cycle orchestration, and post-productization patterns, see references/product-maturity-patterns.md.
For the final completion verification checklist โ the explicit audit pattern to run before marking status: complete on an installable-solution mission, see references/autonomous-lab-completion-verification.md.
For the reactivation protocol when a completed lab receives new P0 feedback or the user contradicts a completion claim, see references/autonomous-lab-reactivation-protocol.md.
For the config/CHANGELOG version drift pitfall that occurs when autonomous labs evolve over many cycles, and for the related source vs. published file drift problem where the live web root diverges from the project source, see references/autonomous-lab-version-drift.md.
For adding historical trend tracking (SQLite-backed agent status transitions + vanilla JS SVG sparklines) to an autonomous lab dashboard, see references/history-tracking-sparkline-pattern.md.
For reusable dashboard UX patterns (onboarding tours, data freshness badges, keyboard shortcuts, progressive disclosure inspectors, cross-linking between views), see references/dashboard-ux-patterns.md.
For the aggressive human-first inspector refinement โ when users report that details are hard to understand and the fix is to strip technical labels from the default view โ see references/progressive-disclosure-human-first.md.
For programmatic verification of CSS custom-property theme systems โ catching scoping bugs, confirming theme distinctness, and validating JS switching logic โ see references/theme-system-verification.md.
- For Son's Discord-first autonomous experiments where a channel hosts a repeated multi-agent loop, use the Autonomous Discord Agent Lab pattern: create file-based durable state, a paused cron orchestrator delivered to
discord:<channel_id>, then activate it from a user mission trigger. See references/autonomous-discord-agent-lab.md.
- For verifying that a release package (
tar.gz) is actually installable by third parties and contains no stale artifacts or hardcoded references, see references/release-package-verification.md and the reusable script at scripts/release-verify.sh.
Webhooks
hermes webhook subscribe N Create route at /webhooks/<name>
hermes webhook list List subscriptions
hermes webhook remove NAME Remove a subscription
hermes webhook test NAME Send a test POST
Profiles
hermes profile list List all profiles
hermes profile create NAME Create (--clone, --clone-all, --clone-from)
hermes profile use NAME Set sticky default
hermes profile delete NAME Delete a profile
hermes profile show NAME Show details
hermes profile alias NAME Manage wrapper scripts
hermes profile rename A B Rename a profile
hermes profile export NAME Export to tar.gz
hermes profile import FILE Import from archive
Credential Pools
hermes auth add Interactive credential wizard
hermes auth list [PROVIDER] List pooled credentials
hermes auth remove P INDEX Remove by provider + index
hermes auth reset PROVIDER Clear exhaustion status
Other
hermes insights [--days N] Usage analytics
hermes update Update to latest version
hermes pairing list/approve/revoke DM authorization
hermes plugins list/install/remove Plugin management
hermes honcho setup/status Honcho memory integration (requires honcho plugin)
hermes memory setup/status/off Memory provider config
hermes completion bash|zsh Shell completions
hermes acp ACP server (IDE integration)
hermes claw migrate Migrate from OpenClaw
hermes uninstall Uninstall Hermes
---
Slash Commands (In-Session)
Type these during an interactive chat session. New commands land fairly
often; if something below looks stale, run /help in-session for the
authoritative list or see the [live slash commands reference](https://hermes-agent.nousresearch.com/docs/reference/slash-commands).
The registry of record is hermes_cli/commands.py โ every consumer
(autocomplete, Telegram menu, Slack mapping, /help) derives from it.
Session Control
/new (/reset) Fresh session
/clear Clear screen + new session (CLI)
/retry Resend last message
/undo Remove last exchange
/title [name] Name the session
/compress Manually compress context
/stop Kill background processes
/rollback [N] Restore filesystem checkpoint
/snapshot [sub] Create or restore state snapshots of Hermes config/state (CLI)
/background <prompt> Run prompt in background
/queue <prompt> Queue for next turn
/steer <prompt> Inject a message after the next tool call without interrupting
/agents (/tasks) Show active agents and running tasks
/resume [name] Resume a named session
/goal [text|sub] Set a standing goal Hermes works on across turns until achieved
(subcommands: status, pause, resume, clear)
/redraw Force a full UI repaint (CLI)
Configuration
/config Show config (CLI)
/model [name] Show or change model
/personality [name] Set personality
/reasoning [level] Set reasoning (none|minimal|low|medium|high|xhigh|show|hide)
/verbose Cycle: off โ new โ all โ verbose
/voice [on|off|tts] Voice mode
/yolo Toggle approval bypass
/busy [sub] Control what Enter does while Hermes is working (CLI)
(subcommands: queue, steer, interrupt, status)
/indicator [style] Pick the TUI busy-indicator style (CLI)
(styles: kaomoji, emoji, unicode, ascii)
/footer [on|off] Toggle gateway runtime-metadata footer on final replies
/skin [name] Change theme (CLI)
/statusbar Toggle status bar (CLI)
Tools & Skills
/tools Manage tools (CLI)
/toolsets List toolsets (CLI)
/skills Search/install skills (CLI)
/skill <name> Load a skill into session
/reload-skills Re-scan ~/.hermes/skills/ for added/removed skills
/reload Reload .env variables into the running session (CLI)
/reload-mcp Reload MCP servers
/cron Manage cron jobs (CLI)
/curator [sub] Background skill maintenance (status, run, pin, archive, โฆ)
/kanban [sub] Multi-profile collaboration board (tasks, links, comments)
/plugins List plugins (CLI)
Gateway
/approve Approve a pending command (gateway)
/deny Deny a pending command (gateway)
/restart Restart gateway (gateway)
/sethome Set current chat as home channel (gateway)
/update Update Hermes to latest (gateway)
/topic [sub] Enable or inspect Telegram DM topic sessions (gateway)
/platforms (/gateway) Show platform connection status (gateway)
Utility
/branch (/fork) Branch the current session
/fast Toggle priority/fast processing
/browser Open CDP browser connection
/history Show conversation history (CLI)
/save Save conversation to file (CLI)
/copy [N] Copy the last assistant response to clipboard (CLI)
/paste Attach clipboard image (CLI)
/image Attach local image file (CLI)
Info
/help Show commands
/commands [page] Browse all commands (gateway)
/usage Token usage
/insights [days] Usage analytics
/gquota Show Google Gemini Code Assist quota usage (CLI)
/status Session info (gateway)
/profile Active profile info
/debug Upload debug report (system info + logs) and get shareable links
Exit
/quit (/exit, /q) Exit CLI
---
Key Paths & Config
~/.hermes/config.yaml Main configuration
~/.hermes/.env API keys and secrets
$HERMES_HOME/skills/ Installed skills
~/.hermes/sessions/ Session transcripts
~/.hermes/logs/ Gateway and error logs
~/.hermes/auth.json OAuth tokens and credential pools
~/.hermes/hermes-agent/ Source code (if git-installed)
Profiles use ~/.hermes/profiles/<name>/ with the same layout.
Config Sections
Edit with hermes config edit or hermes config set section.key value.
| Section | Key options |
|---------|-------------|
| model | default, provider, base_url, api_key, context_length |
| agent | max_turns (90), tool_use_enforcement |
| terminal | backend (local/docker/ssh/modal), cwd, timeout (180) |
| compression | enabled, threshold (0.50), target_ratio (0.20) |
| display | skin, tool_progress, show_reasoning, show_cost |
| stt | enabled, provider (local/groq/openai/mistral) |
| tts | provider (edge/elevenlabs/openai/minimax/mistral/neutts) |
| memory | memory_enabled, user_profile_enabled, provider |
| security | tirith_enabled, website_blocklist |
| delegation | model, provider, base_url, api_key, max_iterations (50), reasoning_effort |
| checkpoints | enabled, max_snapshots (50) |
| fallback_model | provider, model, base_url, key_env |
Fallback Providers
Hermes can automatically fail over to a backup provider:model when the primary is unavailable. This is turn-scoped โ each new user message starts with the primary restored; fallback only activates mid-turn when the primary fails.
Configuration ( ~/.hermes/config.yaml):
fallback_model:
provider: opencode-go
model: kimi-k2.6
Or use the interactive manager:
hermes fallback add # interactive picker
hermes fallback list # show fallback chain
hermes fallback remove # remove by index
Legacy note: fallback_model (singular) is the legacy single-fallback key. fallback_providers (list) supports multiple ordered fallbacks. When both exist, fallback_providers takes priority.
Trigger conditions (after exhausting retries where applicable):
- Rate limits (HTTP 429)
- Server errors (HTTP 500, 502, 503)
- Auth failures (HTTP 401, 403) โ immediately
- Not found (HTTP 404) โ immediately
- Invalid / empty responses repeatedly
Supported providers include all standard providers (OpenRouter, Anthropic, OpenCode Go/ Zen, Kimi, etc.) plus custom endpoints with base_url + key_env. Full provider docs: https://hermes-agent.nousresearch.com/docs/integrations/providers
Limitations:
- Subagent delegation does not inherit fallback config
- Cron jobs do not use fallback (use per-job provider/model overrides)
- Auxiliary tasks (vision, compression, etc.) use their own
auxiliary.* provider chain
For a deep-dive with worked examples and model lists, see references/fallback-providers.md.
Full config reference: https://hermes-agent.nousresearch.com/docs/user-guide/configuration
Providers
20+ providers supported. Set via hermes model or hermes setup.
| Provider | Auth | Key env var |
|----------|------|-------------|
| OpenRouter | API key | OPENROUTER_API_KEY |
| Anthropic | API key | ANTHROPIC_API_KEY |
| Nous Portal | OAuth | hermes auth |
| OpenAI Codex | OAuth | hermes auth |
| GitHub Copilot | Token | COPILOT_GITHUB_TOKEN |
| Google Gemini | API key | GOOGLE_API_KEY or GEMINI_API_KEY |
| DeepSeek | API key | DEEPSEEK_API_KEY |
| xAI / Grok | API key | XAI_API_KEY |
| Hugging Face | Token | HF_TOKEN |
| Z.AI / GLM | API key | GLM_API_KEY |
| MiniMax | API key | MINIMAX_API_KEY |
| MiniMax CN | API key | MINIMAX_CN_API_KEY |
| Kimi / Moonshot | API key | KIMI_API_KEY |
| Alibaba / DashScope | API key | DASHSCOPE_API_KEY |
| Xiaomi MiMo | API key | XIAOMI_API_KEY |
| Kilo Code | API key | KILOCODE_API_KEY |
| AI Gateway (Vercel) | API key | AI_GATEWAY_API_KEY |
| OpenCode Zen | API key | OPENCODE_ZEN_API_KEY |
| OpenCode Go | API key | OPENCODE_GO_API_KEY |
| Qwen OAuth | OAuth | hermes auth add qwen-oauth |
| Custom endpoint | Config | model.base_url + model.api_key in config.yaml |
| GitHub Copilot ACP | External | COPILOT_CLI_PATH or Copilot CLI |
Full provider docs: https://hermes-agent.nousresearch.com/docs/integrations/providers
Toolsets
Enable/disable via hermes tools (interactive) or hermes tools enable/disable NAME.
| Toolset | What it provides |
|---------|-----------------|
| web | Web search and content extraction |
| search | Web search only (subset of web) |
| browser | Browser automation (Browserbase, Camofox, or local Chromium) |
| terminal | Shell commands and process management |
| file | File read/write/search/patch |
| code_execution | Sandboxed Python execution |
| vision | Image analysis |
| image_gen | AI image generation |
| video | Video analysis and generation |
| tts | Text-to-speech |
| skills | Skill browsing and management |
| memory | Persistent cross-session memory |
| session_search | Search past conversations |
| delegation | Subagent task delegation |
| cronjob | Scheduled task management |
| clarify | Ask user clarifying questions |
| messaging | Cross-platform message sending |
| todo | In-session task planning and tracking |
| kanban | Multi-agent work-queue tools (gated to workers) |
| debugging | Extra introspection/debug tools (off by default) |
| safe | Minimal, low-risk toolset for locked-down sessions |
| spotify | Spotify playback and playlist control |
| homeassistant | Smart home control (off by default) |
| discord | Discord integration tools |
| discord_admin | Discord admin/moderation tools |
| feishu_doc | Feishu (Lark) document tools |
| feishu_drive | Feishu (Lark) drive tools |
| yuanbao | Yuanbao integration tools |
| rl | Reinforcement learning tools (off by default) |
| moa | Mixture of Agents (off by default) |
Full enumeration lives in toolsets.py as the TOOLSETS dict; _HERMES_CORE_TOOLS is the default bundle most platforms inherit from.
Tool changes take effect on /reset (new session). They do NOT apply mid-conversation to preserve prompt caching.
---
Security & Privacy Toggles
Common "why is Hermes doing X to my output / tool calls / commands?" toggles โ and the exact commands to change them. Most of these need a fresh session (/reset in chat, or start a new hermes invocation) because they're read once at startup.
Secret redaction in tool output
Secret redaction is off by default โ tool output (terminal stdout, read_file, web content, subagent summaries, etc.) passes through unmodified. If the user wants Hermes to auto-mask strings that look like API keys, tokens, and secrets before they enter the conversation context and logs:
hermes config set security.redact_secrets true # enable globally
Restart required. security.redact_secrets is snapshotted at import time โ toggling it mid-session (e.g. via export HERMES_REDACT_SECRETS=true from a tool call) will NOT take effect for the running process. Tell the user to run hermes config set security.redact_secrets true in a terminal, then start a new session. This is deliberate โ it prevents an LLM from flipping the toggle on itself mid-task.
Disable again with:
hermes config set security.redact_secrets false
PII redaction in gateway messages
Separate from secret redaction. When enabled, the gateway hashes user IDs and strips phone numbers from the session context before it reaches the model:
hermes config set privacy.redact_pii true # enable
hermes config set privacy.redact_pii false # disable (default)
Command approval prompts
By default (approvals.mode: manual), Hermes prompts the user before running shell commands flagged as destructive (rm -rf, git reset --hard, etc.). The modes are:
manual โ always prompt (default)
smart โ use an auxiliary LLM to auto-approve low-risk commands, prompt on high-risk
off โ skip all approval prompts (equivalent to --yolo)
hermes config set approvals.mode smart # recommended middle ground
hermes config set approvals.mode off # bypass everything (not recommended)
Per-invocation bypass without changing config:
hermes --yolo โฆ
export HERMES_YOLO_MODE=1
Note: YOLO / approvals.mode: off does NOT turn off secret redaction. They are independent.
Shell hooks allowlist
Some shell-hook integrations require explicit allowlisting before they fire. Managed via ~/.hermes/shell-hooks-allowlist.json โ prompted interactively the first time a hook wants to run.
Disabling the web/browser/image-gen tools
To keep the model away from network or media tools entirely, open hermes tools and toggle per-platform. Takes effect on next session (/reset). See the Tools & Skills section above.
---
Voice & Transcription
STT (Voice โ Text)
Voice messages from messaging platforms are auto-transcribed.
Provider priority (auto-detected):
1. Local faster-whisper โ free, no API key: pip install faster-whisper
2. Groq Whisper โ free tier: set GROQ_API_KEY
3. OpenAI Whisper โ paid: set VOICE_TOOLS_OPENAI_KEY
4. Mistral Voxtral โ set MISTRAL_API_KEY
Config:
stt:
enabled: true
provider: local # local, groq, openai, mistral
local:
model: base # tiny, base, small, medium, large-v3
TTS (Text โ Voice)
| Provider | Env var | Free? |
|----------|---------|-------|
| Edge TTS | None | Yes (default) |
| ElevenLabs | ELEVENLABS_API_KEY | Free tier |
| OpenAI | VOICE_TOOLS_OPENAI_KEY | Paid |
| MiniMax | MINIMAX_API_KEY | Paid |
| Mistral (Voxtral) | MISTRAL_API_KEY | Paid |
| NeuTTS (local) | None (pip install neutts[all] + espeak-ng) | Free |
Voice commands: /voice on (voice-to-voice), /voice tts (always voice), /voice off.
---
Spawning Additional Hermes Instances
Run additional Hermes processes as fully independent subprocesses โ separate sessions, tools, and environments.
When to Use This vs delegate_task
| | delegate_task | Spawning hermes process |
|-|-----------------|--------------------------|
| Isolation | Separate conversation, shared process | Fully independent process |
| Duration | Minutes (bounded by parent loop) | Hours/days |
| Tool access | Subset of parent's tools | Full tool access |
| Interactive | No | Yes (PTY mode) |
| Use case | Quick parallel subtasks | Long autonomous missions |
One-Shot Mode
terminal(command="hermes chat -q 'Research GRPO papers and write summary to ~/research/grpo.md'", timeout=300)
Background for long tasks:
terminal(command="hermes chat -q 'Set up CI/CD for ~/myapp'", background=true)
Interactive PTY Mode (via tmux)
Hermes uses prompt_toolkit, which requires a real terminal. Use tmux for interactive spawning:
Start
terminal(command="tmux new-session -d -s agent1 -x 120 -y 40 'hermes'", timeout=10)
Wait for startup, then send a message
terminal(command="sleep 8 && tmux send-keys -t agent1 'Build a FastAPI auth service' Enter", timeout=15)
Read output
terminal(command="sleep 20 && tmux capture-pane -t agent1 -p", timeout=5)
Send follow-up
terminal(command="tmux send-keys -t agent1 'Add rate limiting middleware' Enter", timeout=5)
Exit
terminal(command="tmux send-keys -t agent1 '/exit' Enter && sleep 2 && tmux kill-session -t agent1", timeout=10)
Multi-Agent Coordination
Agent A: backend
terminal(command="tmux new-session -d -s backend -x 120 -y 40 'hermes -w'", timeout=10)
terminal(command="sleep 8 && tmux send-keys -t backend 'Build REST API for user management' Enter", timeout=15)
Agent B: frontend
terminal(command="tmux new-session -d -s frontend -x 120 -y 40 'hermes -w'", timeout=10)
terminal(command="sleep 8 && tmux send-keys -t frontend 'Build React dashboard for user management' Enter", timeout=15)
Check progress, relay context between them
terminal(command="tmux capture-pane -t backend -p | tail -30", timeout=5)
terminal(command="tmux send-keys -t frontend 'Here is the API schema from the backend agent: ...' Enter", timeout=5)
Session Resume
Resume most recent session
terminal(command="tmux new-session -d -s resumed 'hermes --continue'", timeout=10)
Resume specific session
terminal(command="tmux new-session -d -s resumed 'hermes --resume 20260225_143052_a1b2c3'", timeout=10)
Tips
- Prefer
delegate_task for quick subtasks โ less overhead than spawning a full process
- Use
-w (worktree mode) when spawning agents that edit code โ prevents git conflicts
- Set timeouts for one-shot mode โ complex tasks can take 5-10 minutes
- Use
hermes chat -q for fire-and-forget โ no PTY needed
- Use tmux for interactive sessions โ raw PTY mode has
\r vs \n issues with prompt_toolkit
- For scheduled tasks, use the
cronjob tool instead of spawning โ handles delivery and retry
---
Durable & Background Systems
Four systems run alongside the main conversation loop. Quick reference
here; full developer notes live in AGENTS.md, user-facing docs under
website/docs/user-guide/features/.
Delegation (delegate_task)
Synchronous subagent spawn โ the parent waits for the child's summary
before continuing its own loop. Isolated context + terminal session.
- Single:
delegate_task(goal, context, toolsets).
- Batch:
delegate_task(tasks=[{goal, ...}, ...]) runs children in
parallel, capped by delegation.max_concurrent_children (default 3).
- Roles:
leaf (default; cannot re-delegate) vs orchestrator
(can spawn its own workers, bounded by delegation.max_spawn_depth).
- Not durable. If the parent is interrupted, the child is
cancelled. For work that must outlive the turn, use cronjob or
terminal(background=True, notify_on_complete=True).
Config: delegation.* in config.yaml.
Tuning max_concurrent_children
Default is 3. Rule of thumb for raising it:
- Light tasks (web search, file grep): up to
6-8
- Medium tasks (code execution, browser):
4-5
- Heavy tasks (builds, large data):
2-3
- Actual bottleneck is usually the API rate limit, not local CPU/RAM. On a 10-core M4 with 16GB RAM, CPU is rarely the constraint.
- Formula: start at
5, raise only if profiling shows idle time between API responses.
Cron (scheduled jobs)
Durable scheduler โ cron/jobs.py + cron/scheduler.py. Drive it via
the cronjob tool, the hermes cron CLI (list, add, edit,
pause, resume, run, remove), or the /cron slash command.
- Schedules: duration (
"30m", "2h"), "every" phrase
( "every monday 9am"), 5-field cron ( "0 9 *"), or ISO timestamp.
- Per-job knobs:
skills, model/provider override, script
(pre-run data collection; no_agent=True makes the script the whole
job), context_from (chain job A's output into job B), workdir
(run in a specific dir with its AGENTS.md / CLAUDE.md loaded),
multi-platform delivery.
- Invariants: 3-minute hard interrupt per run,
.tick.lock file
prevents duplicate ticks across processes, cron sessions pass
skip_memory=True by default, and cron deliveries are framed with a
header/footer instead of being mirrored into the target gateway
session (keeps role alternation intact).
User docs: https://hermes-agent.nousresearch.com/docs/user-guide/features/cron
Curator (skill lifecycle)
Background maintenance for agent-created skills. Tracks usage, marks
idle skills stale, archives stale ones, keeps a pre-run tar.gz backup
so nothing is lost.
- CLI:
hermes curator <verb> โ status, run, pause, resume,
pin, unpin, archive, restore, prune, backup, rollback.
- Slash:
/curator <subcommand> mirrors the CLI.
- Scope: only touches skills with
created_by: "agent" provenance.
Bundled + hub-installed skills are off-limits. Never deletes โ
max destructive action is archive. Pinned skills are exempt from
every auto-transition and every LLM review pass.
- Telemetry: sidecar at
~/.hermes/skills/.usage.json holds
per-skill use_count, view_count, patch_count,
last_activity_at, state, pinned.
Config: curator.* (enabled, interval_hours, min_idle_hours,
stale_after_days, archive_after_days, backup.*).
User docs: https://hermes-agent.nousresearch.com/docs/user-guide/features/curator
Dreaming (periodic memory/skill consolidation)
For Anthropic-style "dreaming" workflows, combine cron + session_search + memory + skills + curator into a scheduled review loop. Start with a weekly, proposal-only report that audits recent sessions, repeated user corrections, memory conflicts, skill patch candidates, and cron/automation improvements. Do not automatically delete/replace memory or patch/archive skills unless the user explicitly approves the proposed changes. See references/weekly-dreaming-routine.md for the recommended prompt, report format, safety policy, and cron creation pattern.
Kanban (multi-agent work queue)
Durable SQLite board for multi-profile / multi-worker collaboration.
Users drive it via hermes kanban <verb>; dispatcher-spawned workers
see a focused kanban_* toolset gated by HERMES_KANBAN_TASK so the
schema footprint is zero outside worker processes.
- CLI verbs (common):
init, create, list (alias ls),
show, assign, link, unlink, comment, complete, block,
unblock, archive, tail. Less common: watch, stats, runs,
log, dispatch, daemon, gc.
- Worker toolset:
kanban_show, kanban_complete, kanban_block,
kanban_heartbeat, kanban_comment, kanban_create, kanban_link.
- Dispatcher runs inside the gateway by default
( kanban.dispatch_in_gateway: true) โ reclaims stale claims,
promotes ready tasks, atomically claims, spawns assigned profiles.
Auto-blocks a task after ~5 consecutive spawn failures.
- Isolation: board is the hard boundary (workers get
HERMES_KANBAN_BOARD pinned in env); tenant is a soft namespace
within a board for workspace-path + memory-key isolation.
User docs: https://hermes-agent.nousresearch.com/docs/user-guide/features/kanban
Log Relay (Hermes โ Discord)
A background Python script that tails ~/.hermes/logs/*.log and batches lines to a Discord channel. Includes session-ID extraction, rate-limit handling, and auto-restart via launchd/systemd. Useful for remote monitoring and audit trails.
- Reference:
references/discord-log-relay.md โ full setup, tuning, macOS/Linux service install, pitfalls.
- Template:
templates/discord-log-relay.py โ copy, set CHANNEL_ID, and deploy.
- Discord operations:
references/discord-operating-planes.md โ channel-purpose routing, periodic-summary vs Dreaming report formats, and safety/cost notes for Discord-first Hermes deployments.
Key pitfall: ask the user about batch frequency upfront rather than defaulting to real-time streaming. Most users prefer 10-minute or hourly batches. High-volume raw logs should be batched, summarized, or stored out-of-band; avoid Discord message storms during error loops.
Weekly Dreaming / Memory Curation
For long-running Hermes deployments, users may want an Anthropic-style "Dreaming" loop: a scheduled review that consolidates experience, proposes memory/skill/cron changes, and identifies what to keep, weaken, archive, or delete. Hermes has the building blocks (sessions, session_search, memory, skills, curator, cron), but the safe default is proposal mode:
1. Inspect recent usage and sessions.
2. Extract repeated success patterns, failure patterns, and user corrections.
3. Propose memory updates/removals without applying them silently.
4. Propose skill patches/archive candidates and cron/reporting improvements.
5. End with explicit approval checkboxes.
Do not silently rewrite or delete memory/skills from a Dreaming report unless the user explicitly authorized automatic application. See references/discord-operating-planes.md for a report template and routing heuristics.
---
Windows-Specific Quirks
Hermes runs natively on Windows (PowerShell, cmd, Windows Terminal, git-bash
mintty, VS Code integrated terminal). Most of it just works, but a handful
of differences between Win32 and POSIX have bitten us โ document new ones
here as you hit them so the next person (or the next session) doesn't
rediscover them from scratch.
Input / Keybindings
Alt+Enter doesn't insert a newline. Windows Terminal intercepts Alt+Enter
at the terminal layer to toggle fullscreen โ the keystroke never reaches
prompt_toolkit. Use Ctrl+Enter instead. Windows Terminal delivers
Ctrl+Enter as LF ( c-j), distinct from plain Enter ( c-m / CR), and the
CLI binds c-j to newline insertion on win32 only (see
_bind_prompt_submit_keys + the Windows-only c-j binding in cli.py).
Side effect: the raw Ctrl+J keystroke also inserts a newline on Windows โ
unavoidable, because Windows Terminal collapses Ctrl+Enter and Ctrl+J to
the same keycode at the Win32 console API layer. No conflicting binding
existed for Ctrl+J on Windows, so this is a harmless side effect.
mintty / git-bash behaves the same (fullscreen on Alt+Enter) unless you
disable Alt+Fn shortcuts in Options โ Keys. Easier to just use Ctrl+Enter.
Diagnosing keybindings. Run python scripts/keystroke_diagnostic.py
(repo root) to see exactly how prompt_toolkit identifies each keystroke
in the current terminal. Answers questions like "does Shift+Enter come
through as a distinct key?" (almost never โ most terminals collapse it
to plain Enter) or "what byte sequence is my terminal sending for
Ctrl+Enter?" This is how the Ctrl+Enter = c-j fact was established.
Config / Files
HTTP 400 "No models provided" on first run. config.yaml was saved
with a UTF-8 BOM (common when Windows apps write it). Re-save as UTF-8
without BOM. hermes config edit writes without BOM; manual edits in
Notepad are the usual culprit.
execute_code / Sandbox
WinError 10106 ("The requested service provider could not be loaded
or initialized") from the sandbox child process โ it can't create an
AF_INET socket, so the loopback-TCP RPC fallback fails before
connect(). Root cause is usually not a broken Winsock LSP; it's
Hermes's own env scrubber dropping SYSTEMROOT / WINDIR / COMSPEC
from the child env. Python's socket module needs SYSTEMROOT to locate
mswsock.dll. Fixed via the _WINDOWS_ESSENTIAL_ENV_VARS allowlist in
tools/code_execution_tool.py. If you still hit it, echo os.environ
inside an execute_code block to confirm SYSTEMROOT is set. Full
diagnostic recipe in references/execute-code-sandbox-env-windows.md.
Testing / Contributing
scripts/run_tests.sh doesn't work as-is on Windows โ it looks for
POSIX venv layouts ( .venv/bin/activate). The Hermes-installed venv at
venv/Scripts/ has no pip or pytest either (stripped for install size).
Workaround: install pytest + pytest-xdist + pyyaml into a system Python
3.11 user site, then invoke pytest directly with PYTHONPATH set:
"/c/Program Files/Python311/python" -m pip install --user pytest pytest-xdist pyyaml
export PYTHONPATH="$(pwd)"
"/c/Program Files/Python311/python" -m pytest tests/foo/test_bar.py -v --tb=short -n 0
Use -n 0, not -n 4 โ pyproject.toml's default addopts already
includes -n, and the wrapper's CI-parity guarantees don't apply off POSIX.
POSIX-only tests need skip guards. Common markers already in the codebase:
- Symlinks โ elevated privileges on Windows
0o600 file modes โ POSIX mode bits not enforced on NTFS by default
signal.SIGALRM โ Unix-only (see tests/conftest.py::_enforce_test_timeout)
- Winsock / Windows-specific regressions โ
@pytest.mark.skipif(sys.platform != "win32", ...)
Use the existing skip-pattern style (sys.platform == "win32" or
sys.platform.startswith("win")) to stay consistent with the rest of the
suite.
Path / Filesystem
Line endings. Git may warn LF will be replaced by CRLF the next time
Git touches it. Cosmetic โ the repo's .gitattributes normalizes. Don't
let editors auto-convert committed POSIX-newline files to CRLF.
Forward slashes work almost everywhere. C:/Users/... is accepted by
every Hermes tool and most Windows APIs. Prefer forward slashes in code
and logs โ avoids shell-escaping backslashes in bash.
---
Troubleshooting
Voice not working
1. Check stt.enabled: true in config.yaml
2. Verify provider: pip install faster-whisper or set API key
3. In gateway: /restart. In CLI: exit and relaunch.
Tool not available
1. hermes tools โ check if toolset is enabled for your platform
2. Some tools need env vars (check .env)
3. /reset after enabling tools
Model/provider issues
1. hermes doctor โ check config and dependencies
2. hermes auth add <provider> โ re-authenticate OAuth providers (use --type oauth)
3. Check .env has the right API key
4. Copilot 403: gh auth login tokens do NOT work for Copilot API. You must use the Copilot-specific OAuth device code flow via hermes model โ GitHub Copilot.
Changes not taking effect
- Tools/skills:
/reset starts a new session with updated toolset
- Config changes: In gateway:
/restart. In CLI: exit and relaunch.
- Code changes: Restart the CLI or gateway process
Deployed web dashboard shows stale CSS or theme changes
- Browser cache: Add
?v=N cache-busting query strings to CSS/JS/theme links in HTML.
- Service Worker cache: Bump
CACHE_NAME in sw.js to invalidate old shell caches.
- Data freshness: Use
fetch(url, {cache:'no-store'}) for live JSON feeds.
- Auto-detection: Embed
data-build in <html> and compare server build vs loaded build on page load to show a "new version available" banner. See references/static-site-cache-invalidation.md for the full diagnostic recipe and auto-detection pattern.
- Theme switcher reliability: If theme switching works in Chrome but not Samsung Internet, or feels broken on mobile, see
references/theme-switcher-reliability.md for the create-new-link โ load โ remove-old pattern.
- Emergency recovery: If a bad deploy breaks the main app JS, users need a standalone reset page. See
references/emergency-reset-page.md for a zero-dependency reset.html that clears Service Workers and caches without relying on the main app's JS.
Dashboard inspector feels too technical
- The default inspector view should contain only plain-language sentences: headline, "what they're doing now", "why it matters", and a silent visual progress bar (no text label).
- Move all technical fields (source IDs, confidence scores, progress labels, status slugs, badges) behind a "Show technical details" toggle.
- If users say "details are hard to understand," the fix is to remove more fields from the default view, not to add explanations. Explanations of technical fields are still technical.
- See
references/progressive-disclosure-human-first.md for the aggressive simplification pattern.
Skills not showing
1. hermes skills list โ verify installed
2. hermes skills config โ check platform enablement
3. Load explicitly: /skill name or hermes -s name
Gateway issues
Check logs first:
grep -i "failed to send\|error" ~/.hermes/logs/gateway.log | tail -20
Common gateway problems:
- Gateway dies on SSH logout: Enable linger:
sudo loginctl enable-linger $USER
- Gateway dies on WSL2 close: WSL2 requires
systemd=true in /etc/wsl.conf for systemd services to work. Without it, gateway falls back to nohup (dies when session closes).
- Gateway crash loop: Reset the failed state:
systemctl --user reset-failed hermes-gateway
- macOS: bot shows offline after idle time: The gateway runs as a user agent (
LimitLoadToSessionType=Aqua), so macOS suspends it when the system sleeps. The platform websocket drops and the bot appears offline until the network returns. Fix: keep the Mac awake (System Settings -> Energy -> Prevent automatic sleeping, or caffeinate -d -i -s -u &). Low Power Mode makes this worse, not better. See references/macos-gateway-sleep-disconnect.md for the full diagnostic recipe.
Platform-specific issues
- Discord bot silent: Must enable Message Content Intent in Bot โ Privileged Gateway Intents. See full Discord setup reference:
references/discord-gateway-setup.md.
- Slack bot only works in DMs: Must subscribe to
message.channels event. Without it, the bot ignores public channels.
- Windows-specific issues (
Alt+Enter newline, WinError 10106, UTF-8 BOM config, test suite, line endings): see the dedicated Windows-Specific Quirks section above.
Auxiliary models not working
If auxiliary tasks (vision, compression, session_search) fail silently, the auto provider can't find a backend. Either set OPENROUTER_API_KEY or GOOGLE_API_KEY, or explicitly configure each auxiliary task's provider:
hermes config set auxiliary.vision.provider <your_provider>
hermes config set auxiliary.vision.model <model_name>
Full system auth provisioning
For a one-shot workflow to maximize available credentials โ installing gh, generating SSH keys, configuring git, enabling all Hermes toolsets, and auditing current auth state โ see references/system-auth-setup.md.
Editing large files with patch
When a file is read with read_file(offset=...) (pagination), the tool warns that the view is partial. If you attempt patch without re-reading the full file first, you will likely hit non-unique match errors or corrupt the file. Fix: always call read_file without offset to load the whole file before patching. The tool explicitly warns: "โฆwas last read with offset/limit pagination (partial view). Re-read the whole file before overwriting it." โ heed this warning. For append-only updates (e.g., adding a cycle log entry to state.md), do not use terminal(command="cat >> file << 'EOF'...EOF") โ the terminal tool on macOS/Linux misinterprets heredoc << as backgrounding and fails. Instead, write a short Python script via write_file and execute it with terminal(command="python3 /tmp/script.py"). See references/terminal-heredoc-workaround.md for the full pattern.
Sibling subagent file overwrites
When multiple subagents are running in parallel (e.g. via delegate_task batch mode or kanban worker lanes), a file may be modified by one subagent while another is about to write to it. If you use write_file or patch on a file that was last read before a sibling subagent modified it, your write may silently truncate or revert the sibling's changes. The tool may show a warning like "this file was modified by sibling subagent X but this agent never read it."
Fix:
1. Heed the warning. If the tool reports a sibling modification, re-read the file with read_file before writing.
2. Prefer patch over write_file for partial updates โ patch only changes the matched region and is less likely to wipe unrelated content.
3. If the file is already published/deployed, and the local working copy gets corrupted, recover from the published copy:
cp ~/hermes-web/agent-pets/css/dashboard.css ~/.hermes/autonomous-agent-lab/pixel-pet-ops/web/css/dashboard.css
4. For append-only updates, write a small Python script and execute it rather than using write_file on the whole file.
Prevention: In kanban/multi-agent workflows, assign file-level ownership so only one worker touches each file. If parallel workers must edit the same file, have them write to separate temp files and let the orchestrator merge.
---
Windows-Specific Quirks
| Looking for... | Location |
|----------------|----------|
| Config options | hermes config edit or [Configuration docs](https://hermes-agent.nousresearch.com/docs/user-guide/configuration) |
| Available tools | hermes tools list or [Tools reference](https://hermes-agent.nousresearch.com/docs/reference/tools-reference) |
| Slash commands | /help in session or [Slash commands reference](https://hermes-agent.nousresearch.com/docs/reference/slash-commands) |
| Skills catalog | hermes skills browse or [Skills catalog](https://hermes-agent.nousresearch.com/docs/reference/skills-catalog) |
| Provider setup | hermes model or [Providers guide](https://hermes-agent.nousresearch.com/docs/integrations/providers) |
| Platform setup | hermes gateway setup or [Messaging docs](https://hermes-agent.nousresearch.com/docs/user-guide/messaging/) |
| MCP servers | hermes mcp list or [MCP guide](https://hermes-agent.nousresearch.com/docs/user-guide/features/mcp) |
| Profiles | hermes profile list or [Profiles docs](https://hermes-agent.nousresearch.com/docs/user-guide/profiles) |
| Cron jobs | hermes cron list or [Cron docs](https://hermes-agent.nousresearch.com/docs/user-guide/features/cron) |
| Memory | hermes memory status or [Memory docs](https://hermes-agent.nousresearch.com/docs/user-guide/features/memory) |
| Env variables | hermes config env-path or [Env vars reference](https://hermes-agent.nousresearch.com/docs/reference/environment-variables) |
| CLI commands | hermes --help or [CLI reference](https://hermes-agent.nousresearch.com/docs/reference/cli-commands) |
| Gateway logs | ~/.hermes/logs/gateway.log |
| Session files | ~/.hermes/sessions/ or hermes sessions browse |
| Source code | ~/.hermes/hermes-agent/ |
---
Contributor Quick Reference
For occasional contributors and PR authors. Full developer docs: https://hermes-agent.nousresearch.com/docs/developer-guide/
Project Layout
hermes-agent/
โโโ run_agent.py # AIAgent โ core conversation loop
โโโ model_tools.py # Tool discovery and dispatch
โโโ toolsets.py # Toolset definitions
โโโ cli.py # Interactive CLI (HermesCLI)
โโโ hermes_state.py # SQLite session store
โโโ agent/ # Prompt builder, context compression, memory, model routing, credential pooling, skill dispatch
โโโ hermes_cli/ # CLI subcommands, config, setup, commands
โ โโโ commands.py # Slash command registry (CommandDef)
โ โโโ config.py # DEFAULT_CONFIG, env var definitions
โ โโโ main.py # CLI entry point and argparse
โโโ tools/ # One file per tool
โ โโโ registry.py # Central tool registry
โโโ gateway/ # Messaging gateway
โ โโโ platforms/ # Platform adapters (telegram, discord, etc.)
โโโ cron/ # Job scheduler
โโโ tests/ # ~3000 pytest tests
โโโ website/ # Docusaurus docs site
Config: ~/.hermes/config.yaml (settings), ~/.hermes/.env (API keys).
Adding a Tool (3 files)
1. Create tools/your_tool.py:
import json, os
from tools.registry import registry
def check_requirements() -> bool:
return bool(os.getenv("EXAMPLE_API_KEY"))
def example_tool(param: str, task_id: str = None) -> str:
return json.dumps({"success": True, "data": "..."})
registry.register(
name="example_tool",
toolset="example",
schema={"name": "example_tool", "description": "...", "parameters": {...}},
handler=lambda args, **kw: example_tool(
param=args.get("param", ""), task_id=kw.get("task_id")),
check_fn=check_requirements,
requires_env=["EXAMPLE_API_KEY"],
)
2. Add to toolsets.py โ _HERMES_CORE_TOOLS list.
Auto-discovery: any tools/*.py file with a top-level registry.register() call is imported automatically โ no manual list needed.
All handlers must return JSON strings. Use get_hermes_home() for paths, never hardcode ~/.hermes.
Adding a Slash Command
1. Add CommandDef to COMMAND_REGISTRY in hermes_cli/commands.py
2. Add handler in cli.py โ process_command()
3. (Optional) Add gateway handler in gateway/run.py
All consumers (help text, autocomplete, Telegram menu, Slack mapping) derive from the central registry automatically.
Agent Loop (High Level)
run_conversation():
1. Build system prompt
2. Loop while iterations < max:
a. Call LLM (OpenAI-format messages + tool schemas)
b. If tool_calls โ dispatch each via handle_function_call() โ append results โ continue
c. If text response โ return
3. Context compression triggers automatically near token limit
Testing
python -m pytest tests/ -o 'addopts=' -q # Full suite
python -m pytest tests/tools/ -q # Specific area
- Tests auto-redirect
HERMES_HOME to temp dirs โ never touch real ~/.hermes/
- Run full suite before pushing any change
- Use
-o 'addopts=' to clear any baked-in pytest flags
Windows contributors: scripts/run_tests.sh currently looks for POSIX venvs ( .venv/bin/activate / venv/bin/activate) and will error out on Windows where the layout is venv/Scripts/activate + python.exe. The Hermes-installed venv at venv/Scripts/ also has no pip or pytest โ it's stripped for end-user install size. Workaround: install pytest + pytest-xdist + pyyaml into a system Python 3.11 user site ( /c/Program Files/Python311/python -m pip install --user pytest pytest-xdist pyyaml), then run tests directly:
export PYTHONPATH="$(pwd)"
"/c/Program Files/Python311/python" -m pytest tests/tools/test_foo.py -v --tb=short -n 0
Use -n 0 (not -n 4) because pyproject.toml's default addopts already includes -n, and the wrapper's CI-parity story doesn't apply off-POSIX.
Cross-platform test guards: tests that use POSIX-only syscalls need a skip marker. Common ones already in the codebase:
- Symlink creation โ
@pytest.mark.skipif(sys.platform == "win32", reason="Symlinks require elevated privileges on Windows") (see tests/cron/test_cron_script.py)
- POSIX file modes (0o600, etc.) โ
@pytest.mark.skipif(sys.platform.startswith("win"), reason="POSIX mode bits not enforced on Windows") (see tests/hermes_cli/test_auth_toctou_file_modes.py)
signal.SIGALRM โ Unix-only (see tests/conftest.py::_enforce_test_timeout)
- Live Winsock / Windows-specific regression tests โ
@pytest.mark.skipif(sys.platform != "win32", reason="Windows-specific regression")
Monkeypatching sys.platform is not enough when the code under test also calls platform.system() / platform.release() / platform.mac_ver(). Those functions re-read the real OS independently, so a test that sets sys.platform = "linux" on a Windows runner will still see platform.system() == "Windows" and route through the Windows branch. Patch all three together:
monkeypatch.setattr(sys, "platform", "linux")
monkeypatch.setattr(platform, "system", lambda: "Linux")
monkeypatch.setattr(platform, "release", lambda: "6.8.0-generic")
See tests/agent/test_prompt_builder.py::TestEnvironmentHints for a worked example.
Extending the system prompt's execution-environment block
Factual guidance about the host OS, user home, cwd, terminal backend, and shell (bash vs. PowerShell on Windows) is emitted from agent/prompt_builder.py::build_environment_hints(). This is also where the WSL hint and per-backend probe logic live. The convention:
- Local terminal backend โ emit host info (OS,
$HOME, cwd) + Windows-specific notes (hostname โ username, terminal uses bash not PowerShell).
- Remote terminal backend (anything in
_REMOTE_TERMINAL_BACKENDS: docker, singularity, modal, daytona, ssh, vercel_sandbox, managed_modal) โ suppress host info entirely and describe only the backend. A live uname/whoami/pwd probe runs inside the backend via tools.environments.get_environment(...).execute(...), cached per process in _BACKEND_PROBE_CACHE, with a static fallback if the probe times out.
- Key fact for prompt authoring: when
TERMINAL_ENV != "local", every file tool (read_file, write_file, patch, search_files) runs inside the backend container, not on the host. The system prompt must never describe the host in that case โ the agent can't touch it.
Full design notes, the exact emitted strings, and testing pitfalls:
references/prompt-builder-environment-hints.md.
Refactor-safety pattern (POSIX-equivalence guard): when you extract inline logic into a helper that adds Windows/platform-specific behavior, keep a _legacy_<name> oracle function in the test file that's a verbatim copy of the old code, then parametrize-diff against it. Example: tests/tools/test_code_execution_windows_env.py::TestPosixEquivalence. This locks in the invariant that POSIX behavior is bit-for-bit identical and makes any future drift fail loudly with a clear diff.
Commit Conventions
type: concise subject line
Optional body.
Types: fix:, feat:, refactor:, docs:, chore:
Key Rules
- Never break prompt caching โ don't change context, tools, or system prompt mid-conversation
- Message role alternation โ never two assistant or two user messages in a row
- Use
get_hermes_home() from hermes_constants for all paths (profile-safe)
- Config values go in
config.yaml, secrets go in .env
- New tools need a
check_fn so they only appear when requirements are met
[IMPORTANT: The user has invoked the "kanban-orchestrator" skill, indicating they want you to follow its instructions. The full skill content is loaded below.]
---
name: kanban-orchestrator
description: Decomposition playbook + anti-temptation rules for an orchestrator profile routing work through Kanban. The "don't do the work yourself" rule and the basic lifecycle are auto-injected into every kanban worker's system prompt; this skill is the deeper playbook when you're specifically playing the orchestrator role.
version: 3.0.0
platforms: [linux, macos, windows]
metadata:
hermes:
tags: [kanban, multi-agent, orchestration, routing]
related_skills: [kanban-worker]
---
Kanban Orchestrator โ Decomposition Playbook
> The core worker lifecycle (including the kanban_create fan-out pattern and the "decompose, don't execute" rule) is auto-injected into every kanban process via the KANBAN_GUIDANCE system-prompt block. This skill is the deeper playbook when you're an orchestrator profile whose whole job is routing.
Profiles are user-configured โ not a fixed roster
Hermes setups vary widely. Some users run a single profile that does everything; some run a small fleet (docker-worker, cron-worker); some run a curated specialist team they've named themselves. There is no default specialist roster โ the orchestrator skill does not know what profiles exist on this machine.
Before fanning out, you must ground the decomposition in the profiles that actually exist. The dispatcher silently fails to spawn unknown assignee names โ it doesn't autocorrect, doesn't suggest, doesn't fall back. So a card assigned to researcher on a setup that only has docker-worker just sits in ready forever.
Step 0: discover available profiles before planning.
Use one of these:
hermes profile list โ prints the table of profiles configured on this machine. Run it through your terminal tool if you have one; otherwise ask the user.
kanban_list(assignee="<some-name>") โ sanity-check a single name. Returns an empty list (rather than an error) for an unknown assignee, so this only confirms a name you're already considering.
- Just ask the user. "What profiles do you have set up?" is a fine first turn when the goal needs more than one specialist.
Cache the result in your working memory for the rest of the conversation. Re-asking every turn wastes a tool call.
When to use the board (vs. just doing the work)
Create Kanban tasks when any of these are true:
1. Multiple specialists are needed. Research + analysis + writing is three profiles.
2. The work should survive a crash or restart. Long-running, recurring, or important.
3. The user might want to interject. Human-in-the-loop at any step.
4. Multiple subtasks can run in parallel. Fan-out for speed.
5. Review / iteration is expected. A reviewer profile loops on drafter output.
6. The audit trail matters. Board rows persist in SQLite forever.
If none of those apply โ it's a small one-shot reasoning task โ use delegate_task instead or answer the user directly.
The anti-temptation rules
Your job description says "route, don't execute." The rules that enforce that:
- Do not execute the work yourself. Your restricted toolset usually doesn't even include terminal/file/code/web for implementation. If you find yourself "just fixing this quickly" โ stop and create a task for the right specialist.
- For any concrete task, create a Kanban task and assign it. Every single time.
- Split multi-lane requests before creating cards. A user prompt can contain several independent workstreams. Extract those lanes first, then create one card per lane instead of bundling unrelated work into a single implementer card.
- Run independent lanes in parallel. If two cards do not need each other's output, leave them unlinked so the dispatcher can fan them out. Link only true data dependencies.
- If no specialist fits the available profiles, ask the user which profile to create or which existing profile to use. Do not invent profile names; the dispatcher will silently drop unknown assignees.
- Decompose, route, and summarize โ that's the whole job.
Exception: micro-UI polish cycles
There is one narrow exception where the orchestrator may execute directly instead of creating Kanban cards: tiny UI-only polish cycles (e.g., adding a CSS class, a theme preview dot, a hover state, a cross-link, or a HUD button) that are purely presentational, require no cross-file logic changes, and fit comfortably inside a single bounded cycle with no need for review or parallel work. If the change is limited to HTML/CSS/JS cosmetics, no other profile has a stake in it, and the user did not ask for a design review, the orchestrator should just edit and publish rather than paying the kanban-overhead tax. This exception does NOT apply to architecture changes, adapter logic, plugin interfaces, or anything that touches the data layer.
Decomposition playbook
Step 1 โ Understand the goal
Ask clarifying questions if the goal is ambiguous. Cheap to ask; expensive to spawn the wrong fleet.
Step 2 โ Sketch the task graph
Before creating anything, draft the graph out loud (in your response to the user). Treat every concrete workstream as a candidate card:
1. Extract the lanes from the request.
2. Map each lane to one of the profiles you discovered in Step 0. If a lane doesn't fit any existing profile, ask the user which to use or create.
3. Decide whether each lane is independent or gated by another lane.
4. Create independent lanes as parallel cards with no parent links.
5. Create synthesis/review/integration cards with parent links to the lanes they depend on.
Examples of prompts that should fan out (using placeholder profile names โ substitute whatever exists on the user's setup):
- "Build an app" โ one card to a design-oriented profile for product/UI direction, one or two cards to engineering profiles for implementation, plus a later integration/review card if the user has a reviewer profile.
- "Fix blockers and check model variants" โ one implementation card for the blocker fixes plus one discovery/research card for config/source verification. A final reviewer card can depend on both.
- "Research docs and implement" โ a docs-research card can run in parallel with a codebase-discovery card; implementation waits only if it truly needs those findings.
- "Analyze this screenshot and find the related code" โ one card to a vision-capable profile for the visual analysis while another searches the codebase.
Words like "also," "finally," or "and" do not automatically imply a dependency. They often mean "make sure this is covered before reporting back." Only link tasks when one card cannot start until another card's output exists.
Show the graph to the user before creating cards. Let them correct it โ including which actual profile name should own each lane.
Step 3 โ Create tasks and link
Use the profile names from Step 0. The example below uses placeholders <profile-A>, <profile-B>, <profile-C> โ replace them with what the user actually has.
t1 = kanban_create(
title="research: Postgres cost vs current",
assignee="<profile-A>", # whichever profile handles research on this setup
body="Compare estimated infrastructure costs, migration costs, and ongoing ops costs over a 3-year window. Sources: AWS/GCP pricing, team time estimates, current Postgres bills from peers.",
tenant=os.environ.get("HERMES_TENANT"),
)["task_id"]
t2 = kanban_create(
title="research: Postgres performance vs current",
assignee="<profile-A>", # same profile, run in parallel
body="Compare query latency, throughput, and scaling characteristics at our expected data volume (~500GB, 10k QPS peak). Sources: benchmark papers, public case studies, pgbench results if easy.",
)["task_id"]
t3 = kanban_create(
title="synthesize migration recommendation",
assignee="<profile-B>", # whichever profile does synthesis/analysis
body="Read the findings from T1 (cost) and T2 (performance). Produce a 1-page recommendation with explicit trade-offs and a go/no-go call.",
parents=[t1, t2],
)["task_id"]
t4 = kanban_create(
title="draft decision memo",
assignee="<profile-C>", # whichever profile drafts user-facing prose
body="Turn the analyst's recommendation into a 2-page memo for the CTO. Match the tone of previous decision memos in the team's knowledge base.",
parents=[t3],
)["task_id"]
parents=[...] gates promotion โ children stay in todo until every parent reaches done, then auto-promote to ready. No manual coordination needed; the dispatcher and dependency engine handle it.
Step 4 โ Complete your own task
If you were spawned as a task yourself (e.g. a planner profile was assigned T0: "investigate Postgres migration"), mark it done with a summary of what you created:
kanban_complete(
summary="decomposed into T1-T4: 2 research lanes in parallel, 1 synthesis on their outputs, 1 prose draft on the recommendation",
metadata={
"task_graph": {
"T1": {"assignee": "<profile-A>", "parents": []},
"T2": {"assignee": "<profile-A>", "parents": []},
"T3": {"assignee": "<profile-B>", "parents": ["T1", "T2"]},
"T4": {"assignee": "<profile-C>", "parents": ["T3"]},
},
},
)
Step 5 โ Report back to the user
Tell them what you created in plain prose, naming the actual profiles you used:
> I've queued 4 tasks:
> - T1 (<profile-A>): cost comparison
> - T2 (<profile-A>): performance comparison, in parallel with T1
> - T3 (<profile-B>): synthesizes T1 + T2 into a recommendation
> - T4 (<profile-C>): turns T3 into a CTO memo
>
> The dispatcher will pick up T1 and T2 now. T3 starts when both finish. You'll get a gateway ping when T4 completes. Use the dashboard or hermes kanban tail <id> to follow along.
Common patterns
Fan-out + fan-in (research โ synthesize): N research-style cards with no parents, one synthesis card with all of them as parents.
Parallel implementation + validation: one implementer card makes the change while one explorer/researcher card verifies config, docs, or source mapping. A reviewer card can depend on both. Do not make the implementer own unrelated verification just because the user mentioned both in one sentence.
Pipeline with gates: planner โ implementer โ reviewer. Each stage's parents=[previous_task]. Reviewer blocks or completes; if reviewer blocks, the operator unblocks with feedback and respawns.
Same-profile queue: N tasks, all assigned to the same profile, no dependencies between them. Dispatcher serializes โ that profile processes them in priority order, accumulating experience in its own memory.
Parallel UI/frontend lanes: When the goal touches multiple independent HTML/CSS/JS files (e.g., a dashboard page and a 2D gather view), fan out to separate subagents per file. Each lane edits its own file, then the orchestrator integrates, fixes cross-file references (theme paths, shared JSON endpoints), and publishes. This avoids merge conflicts in single-file HTML dashboards and keeps each subagent's context focused. See references/parallel-ui-lanes-and-publishing.md for the post-subagent integration checklist and rsync safety notes.
Human-in-the-loop: Any task can kanban_block() to wait for input. Dispatcher respawns after /unblock. The comment thread carries the full context.
Pitfalls
Inventing profile names that don't exist. The dispatcher silently fails to spawn unknown assignees โ the card just sits in ready forever. Always assign to a profile from your Step 0 discovery; ask the user if you're unsure.
Bundling independent lanes into one card. If the user asks for two independent outcomes, create two cards. Example: "fix blockers and check model variants" is not one fixer task; create a fixer/engineer card for the fixes and an explorer/researcher card for the variant check, then optionally gate review on both.
Over-linking because of wording. "Finally check X" may still be parallel with implementation if X is static config, docs, or source discovery. Link it after implementation only when the check depends on the implementation result.
Forgetting dependency links. If the task graph says research -> implement -> review, do not create all tasks as independent ready cards. Use parent links so implement/review cannot run before their inputs exist.
Reassignment vs. new task. If a reviewer blocks with "needs changes," create a NEW task linked from the reviewer's task โ don't re-run the same task with a stern look. The new task is assigned to the original implementer profile.
Argument order for links. kanban_link(parent_id=..., child_id=...) โ parent first. Mixing them up demotes the wrong task to todo.
Ignoring explicit user feedback to keep building infrastructure. When the user says a specific UX issue (legibility, theme switching, movement density) is "immediate priority," treat it as P0 and route it before deeper packaging/architecture work. Infrastructure polish feels productive, but shipping user-visible fixes is what matters. Create cards for the UX feedback first, then resume infrastructure lanes.
Treating status: complete as immutable when user feedback says otherwise. A state.md that says status: complete does not override a user's report that a completion criterion is actually broken. If the user says "theme switching is not working" and the Final Completion Condition requires "working UI theme switcher," the mission is not complete. Reactivate immediately: set status: active, append a reactivation cycle log, and fix the issue. Do not burn cycles on post-complete verification while the user is reporting active defects.
Don't pre-create the whole graph if the shape depends on intermediate findings. If T3's structure depends on what T1 and T2 find, let T3 exist as a "synthesize findings" task whose own first step is to read parent handoffs and plan the rest. Orchestrators can spawn orchestrators.
Tenant inheritance. If HERMES_TENANT is set in your env, pass tenant=os.environ.get("HERMES_TENANT") on every kanban_create call so child tasks stay in the same namespace.
Verifying cross-file references after directory reorganization. When subagents edit HTML/CSS/JS files and the directory structure shifts (e.g., moving files from root into web/dashboard/ and web/gather/), relative asset paths ( themes/default/theme.css, ./ops-data.json) often break. After subagents finish, the orchestrator must grep for href= and src= in moved files and fix relative paths before publishing. Subagents don't know the final publish layout โ the orchestrator does.
Destructive sync wipes needed files. Commands like rsync -av --delete will delete destination files that aren't in the source list. If you publish a directory tree piecemeal (e.g., copy web/dashboard/ first, then web/gather/ separately), --delete on the first rsync will erase the gather files before the second rsync runs. Either list all source paths in a single rsync invocation, or omit --delete and use cp -r / rsync -av without deletion when doing staged copies.
Recovering stuck workers
When a worker profile keeps crashing, hallucinating, or getting blocked by its own mistakes (usually: wrong model, missing skill, broken credential), the kanban dashboard flags the task with a โ badge and opens a Recovery section in the drawer. Three primary actions:
1. Reclaim (or hermes kanban reclaim <task_id>) โ abort the running worker immediately and reset the task to ready. The existing claim TTL is ~15 min; this is the fast path out.
2. Reassign (or hermes kanban reassign <task_id> <new-profile> --reclaim) โ switch the task to a different profile (one that exists on this setup) and let the dispatcher pick it up with a fresh worker.
3. Change profile model โ the dashboard prints a copy-paste hint for hermes -p <profile> model since profile config lives on disk; edit it in a terminal, then Reclaim to retry with the new model.
Hallucination warnings appear on tasks where a worker's kanban_complete(created_cards=[...]) claim included card ids that don't exist or weren't created by the worker's profile (the gate blocks the completion), or where the free-form summary references t_<hex> ids that don't resolve (advisory prose scan, non-blocking). Both produce audit events that persist even after recovery actions โ the trail stays for debugging.
The user has provided the following instruction alongside the skill invocation: [IMPORTANT: You are running as a scheduled cron job. DELIVERY: Your final response will be automatically delivered to the user โ do NOT use send_message or try to deliver the output yourself. Just produce your report/output as your final response and the system handles the rest. SILENT: If there is genuinely nothing new to report, respond with exactly "[SILENT]" (nothing else) to suppress delivery. Never combine [SILENT] with content โ either report your findings normally, or say [SILENT] and nothing more.]
You are the 15-minute Orchestrator for Son's Autonomous Agent Lab v1, reporting to Discord channel ID 1505805763824586952.
Durable state path: /Users/jooho-hermes/.hermes/autonomous-agent-lab/state.md
Working directory for experiment artifacts: /Users/jooho-hermes/.hermes/autonomous-agent-lab/
Preferred published web root: /Users/jooho-hermes/hermes-web/agent-pets/
Top-level directive from Son:
- The project has evolved from a personal dashboard into an INSTALLABLE PRODUCT that external Hermes users can deploy.
- The final target is a self-contained, configurable, publishable solution: "Hermes Pixel Pet Ops Office".
- Do NOT shrink the mission into a small static MVP and autonomously stop.
- The Gather.town-style 2D spatial office is a first-class feature, not a side page.
Latest UX feedback from Son (treat as immediate priority before deeper packaging work):
- Details are hard for a human to understand. Add human-first summaries, plain-language labels, and progressive disclosure: summary first, technical details second.
- Gather Town version has too many agents roaming around. Reduce default movement, add density/speed controls, cluster agents by room/task, and add focus/calm mode.
- Theme switching is not visibly working. Implement real UI theme switcher with persistence and clear visual theme changes.
Key product requirements (installable solution level):
1. Config-driven architecture: all paths, URLs, colors, names, room layouts via config.yaml. No hardcoded references to jooho-hermes.
2. Self-contained package: clear directory structure (src/, web/, config/, docs/, scripts/), install script, requirements.txt.
3. Pluggable data adapter: support multiple backends via plugin architecture.
4. Themeable frontend: CSS variables driven from config, swappable themes, plus a working UI theme switcher.
5. Multi-tenant ready: works for any Hermes instance.
6. Build/Deploy ready: Dockerfile or docker-compose, or clear static-server setup.
7. Documentation: README, architecture docs, configuration reference, contributor guide.
8. Human-comprehensible UX: plain-language summaries and progressive disclosure for technical detail.
9. Gather.town calm mode: adjustable movement density/speed and less chaotic defaults.
10. Versioned releases: CHANGELOG.md, semantic versioning, release packaging.
Mission model:
- Read state.md first before doing anything else.
- If state.md says
status: inactive or has no Current Mission, do not invent work. Return exactly: ๐ก Autonomous Agent Lab ๋๊ธฐ์ค โ Son์ด ํธ๋ฆฌ๊ฑฐ/๋ฏธ์
์ ์ฃผ๋ฉด 15๋ถ ์ฌ์ดํด์ ์์ํฉ๋๋ค.
- If state.md says
status: active, run one bounded 15-minute cycle toward the full installable solution.
- If state.md says
status: complete, verify that the Final Completion Condition in state.md is truly met. If it is not fully met, reactivate or report that state needs correction.
Cycle procedure when active:
1. Read state.md first. Extract current mission, constraints, previous cycle log, and Final Completion Condition.
2. Decide the next smallest useful step toward installable solution quality. Focus on: architecture, configurability, documentation, and clean separation of concerns.
3. Use delegate_task for independent subagent lanes when helpful.
4. Prefer concrete progress: refactor to config-driven, add install scripts, create docs, add Docker support, theme system, plugin architecture.
5. Update state.md with a new cycle log entry before final reporting.
6. Completion rule: only set status: complete when every item under state.md Final Completion Condition is satisfied. A non-installable MVP is not complete.
7. Stop/block only if Son explicitly stops/redirects, a safety boundary is reached, or a hard blocker needs Son's decision.
Link requirement (never forget):
- Every cycle report MUST include at least one direct viewable link to the published dashboard/artifact.
- The canonical URL:
http://hermes-mac-mini.tail46b3c6.ts.net:8099/agent-pets/
- Include gather town URL too:
http://hermes-mac-mini.tail46b3c6.ts.net:8099/agent-pets/gather/
Final Discord message format:
[Autonomous Agent Lab v1 / Cycle N]
๋ชฉํ:
์ํ:
๊ฒฐ๊ณผ:
๊ฒ์ฆ:
๋ค์:
์ํ:
Safety/quality rules:
- Do not handle secrets, passwords, API keys, payment, permission dialogs, or destructive commands.
- Do not claim completion without updating state.md.
- Do not rely on Discord history as durable state.
- Do not spam raw logs; summarize lane outputs and verification.
- Keep working in /Users/jooho-hermes/.hermes/autonomous-agent-lab/ and publish only to /Users/jooho-hermes/hermes-web/agent-pets/ unless the state file says otherwise.
Design/UX priorities:
- Mobile responsiveness is first-class.
- Character animation/movement is desired.
- Every cycle report must include published links.
- This is now a product engineering mission. Architecture, configurability, and documentation matter as much as visuals.
Response
[Autonomous Agent Lab v1 / Cycle 68]
๋ชฉํ: 15๋ถ ์ฃผ๊ธฐ ๊ฑด๊ฐ ๊ฒ์ฆ ๋ฐ Son ๋ธ๋ผ์ฐ์ ํ์ธ ๋๊ธฐ
์ํ:
1. python3 -m src.adapter.generate_ops_data --config config.yaml ์คํ โ 32 agents, 15 cron jobs, 20 sessions, 16 events, schema 1.4
2. scripts/publish.sh config.yaml ์คํ โ ์ ์ฒด ์์
์น ๋ฃจํธ ๋ฐํ ์๋ฃ
3. scripts/test.sh ์คํ โ 128/128 passed, 0 failed
4. scripts/validate_setup.sh ์คํ โ 21/21 passed, 0 warned, 0 critical
5. refresh.err.log ํ์ธ โ ๋น์ด ์์ (์๋ฌ ์์)
6. ops-data.json / health.json mtime ํ์ธ โ 60์ด ์ด๋ด ์ ์ ํจ
๊ฒฐ๊ณผ:
- ์ ์ฒด ์์คํ
์ ์ ๊ฐ๋ ์ค
- ํตํฉ ํ
์คํธ 128๊ฐ ์ ๋ถ ํต๊ณผ
- ๋ฒ์ ๋ฐฐ์ง
v1.4.4 ยท b67 ์ผ๊ด์ฑ ํ์ธ (๋์๋ณด๋ / ๊ฒ๋ / ๋ฐํ๋ณธ ๋์ผ)
- ํ๋์ฝ๋ฉ๋
jooho-hermes ์ฐธ์กฐ 0๊ฑด
- 11๊ฐ Final Completion Condition ์ ๋ถ ์ถฉ์กฑ ์ํ ์ ์ง
๊ฒ์ฆ:
- ๐จ Theme switching visible โ
(hero panel, 3 themes, cache busting v67, auto stale-cache banner)
- ๐ข Gather calm mode โ
(5 agents ๊ธฐ๋ณธ, sparse=0.04, slow=0.25, zen/focus mode)
- ๐ค Human-first details โ
(inspector ๊ธฐ๋ณธ = plain-language ์์ฝ + ์งํ ๋ฐ, ๊ธฐ์ ์์ธ๋ ์จ๊น)
๋ค์:
Son์ด ๋์๋ณด๋์ ์ ์ํ์ฌ ์๋ 3๊ฐ์ง๋ฅผ ์ง์ ํ์ธํ๋ฉด complete ์ฒ๋ฆฌ ๊ฐ๋ฅ:
1. ๋์๋ณด๋ ์๋จ ๋ฐฐ์ง๊ฐ v1.4.4 ยท b67์ธ๊ฐ?
2. ํ
๋ง ์ ํ(hero panel)์ด ๋์ ๋๊ฒ ์๋ํ๋๊ฐ?
3. Gather Town ์ง์
์ 5๋ง๋ฆฌ ์ดํ๋ก ์ฐจ๋ถํ๊ฒ ๋ฐฐ์น๋๋๊ฐ?
์ํ: active (Son ๋ธ๋ผ์ฐ์ ํ์ธ ๋๊ธฐ ์ค)
๋์๋ณด๋: http://hermes-mac-mini.tail46b3c6.ts.net:8099/agent-pets/
Gather Town: http://hermes-mac-mini.tail46b3c6.ts.net:8099/agent-pets/gather/
|
| 2026-05-19 19-50-33 |
82,675 chars |
2026-05-19_19-50-33.md |
Cron Job: autonomous-agent-lab-v1-orchestrator
Job ID: 35127ff89556
Run Time: 2026-05-19 19:50:33
Schedule: every 15m
Prompt
[IMPORTANT: The user has invoked the "hermes-agent" skill, indicating they want you to follow its instructions. The full skill content is loaded below.]
---
name: hermes-agent
description: "Configure, extend, or contribute to Hermes Agent."
version: 2.1.0
author: Hermes Agent + Teknium
license: MIT
platforms: [linux, macos, windows]
metadata:
hermes:
tags: [hermes, setup, configuration, multi-agent, spawning, cli, gateway, development]
homepage: https://github.com/NousResearch/hermes-agent
related_skills: [claude-code, codex, opencode]
---
Hermes Agent
Hermes Agent is an open-source AI agent framework by Nous Research that runs in your terminal, messaging platforms, and IDEs. It belongs to the same category as Claude Code (Anthropic), Codex (OpenAI), and OpenClaw โ autonomous coding and task-execution agents that use tool calling to interact with your system. Hermes works with any LLM provider (OpenRouter, Anthropic, OpenAI, DeepSeek, local models, and 15+ others) and runs on Linux, macOS, and WSL.
What makes Hermes different:
- Self-improving through skills โ Hermes learns from experience by saving reusable procedures as skills. When it solves a complex problem, discovers a workflow, or gets corrected, it can persist that knowledge as a skill document that loads into future sessions. Skills accumulate over time, making the agent better at your specific tasks and environment.
- Persistent memory across sessions โ remembers who you are, your preferences, environment details, and lessons learned. Pluggable memory backends (built-in, Honcho, Mem0, and more) let you choose how memory works.
- Multi-platform gateway โ the same agent runs on Telegram, Discord, Slack, WhatsApp, Signal, Matrix, Email, and 10+ other platforms with full tool access, not just chat.
- Provider-agnostic โ swap models and providers mid-workflow without changing anything else. Credential pools rotate across multiple API keys automatically.
- Profiles โ run multiple independent Hermes instances with isolated configs, sessions, skills, and memory.
- Extensible โ plugins, MCP servers, custom tools, webhook triggers, cron scheduling, and the full Python ecosystem.
People use Hermes for software development, research, system administration, data analysis, content creation, home automation, and anything else that benefits from an AI agent with persistent context and full system access.
This skill helps you work with Hermes Agent effectively โ setting it up, configuring features, spawning additional agent instances, troubleshooting issues, finding the right commands and settings, and understanding how the system works when you need to extend or contribute to it.
Docs: https://hermes-agent.nousresearch.com/docs/
Quick Start
Install
curl -fsSL https://raw.githubusercontent.com/NousResearch/hermes-agent/main/scripts/install.sh | bash
Interactive chat (default)
hermes
Single query
hermes chat -q "What is the capital of France?"
Setup wizard
hermes setup
Change model/provider
hermes model
Check health
hermes doctor
---
CLI Reference
Global Flags
hermes [flags] [command]
--version, -V Show version
--resume, -r SESSION Resume session by ID or title
--continue, -c [NAME] Resume by name, or most recent session
--worktree, -w Isolated git worktree mode (parallel agents)
--skills, -s SKILL Preload skills (comma-separate or repeat)
--profile, -p NAME Use a named profile
--yolo Skip dangerous command approval
--pass-session-id Include session ID in system prompt
No subcommand defaults to chat.
Chat
hermes chat [flags]
-q, --query TEXT Single query, non-interactive
-m, --model MODEL Model (e.g. anthropic/claude-sonnet-4)
-t, --toolsets LIST Comma-separated toolsets
--provider PROVIDER Force provider (openrouter, anthropic, nous, etc.)
-v, --verbose Verbose output
-Q, --quiet Suppress banner, spinner, tool previews
--checkpoints Enable filesystem checkpoints (/rollback)
--source TAG Session source tag (default: cli)
Configuration
hermes setup [section] Interactive wizard (model|terminal|gateway|tools|agent)
hermes model Interactive model/provider picker
hermes config View current config
hermes config edit Open config.yaml in $EDITOR
hermes config set KEY VAL Set a config value
hermes config path Print config.yaml path
hermes config env-path Print .env path
hermes config check Check for missing/outdated config
hermes config migrate Update config with new options
hermes doctor [--fix] Check dependencies and config
Credential Pools
hermes auth add Interactive credential wizard (oauth, api-key)
hermes auth list [PROVIDER] List pooled credentials
hermes auth remove P INDEX Remove by provider + index
hermes auth reset PROVIDER Clear exhaustion status
hermes logout Clear stored auth
Tools & Skills
hermes tools Interactive tool enable/disable (curses UI)
hermes tools list Show all tools and status
hermes tools enable NAME Enable a toolset
hermes tools disable NAME Disable a toolset
hermes skills list List installed skills
hermes skills search QUERY Search the skills hub
hermes skills install ID Install a skill (ID can be a hub identifier OR a direct https://โฆ/SKILL.md URL; pass --name to override when frontmatter has no name)
hermes skills inspect ID Preview without installing
hermes skills config Enable/disable skills per platform
hermes skills check Check for updates
hermes skills update Update outdated skills
hermes skills uninstall N Remove a hub skill
hermes skills publish PATH Publish to registry
hermes skills browse Browse all available skills
hermes skills tap add REPO Add a GitHub repo as skill source
MCP Servers
hermes mcp serve Run Hermes as an MCP server
hermes mcp add NAME Add an MCP server (--url or --command)
hermes mcp remove NAME Remove an MCP server
hermes mcp list List configured servers
hermes mcp test NAME Test connection
hermes mcp configure NAME Toggle tool selection
Gateway (Messaging Platforms)
hermes gateway run Start gateway foreground
hermes gateway install Install as background service
hermes gateway start/stop Control the service
hermes gateway restart Restart the service
hermes gateway status Check status
hermes gateway setup Configure platforms
Supported platforms: Telegram, Discord, Slack, WhatsApp, Signal, Email, SMS, Matrix, Mattermost, Home Assistant, DingTalk, Feishu, WeCom, BlueBubbles (iMessage), Weixin (WeChat), API Server, Webhooks. Open WebUI connects via the API Server adapter.
Platform docs: https://hermes-agent.nousresearch.com/docs/user-guide/messaging/
Discord-specific walkthrough (token, intents, service install, access control): see references/discord-gateway-setup.md in this skill.
- Per-channel personas and skill bindings: see
references/gateway-channel-personas.md (works on Discord, Slack, Telegram, Mattermost, Matrix).
- For long-running Discord-first operations, purpose-specific channel routing, periodic summaries, weekly Dreaming/audit reports, and log-safety patterns: see
references/discord-operating-planes.md.
- For broad Hermes/LifeOS/SQAF ecosystem audits (cron inventory, live services, dashboards, provider/model warnings, and control-plane gaps), see
references/ecosystem-audit.md.
Sessions
hermes sessions list List recent sessions
hermes sessions browse Interactive picker
hermes sessions export OUT Export to JSONL
hermes sessions rename ID T Rename a session
hermes sessions delete ID Delete a session
hermes sessions prune Clean up old sessions (--older-than N days)
hermes sessions stats Session store statistics
For browser-based viewing of existing Hermes CLI/Discord/cron session transcripts, prefer a lightweight static export from ~/.hermes/state.db into a private web root instead of assuming Open WebUI can browse Hermes' native session store. See references/hermes-session-static-web-viewer.md for the SQLite schema, static HTML export workflow, redaction/truncation cautions, and the user's Mac mini deployment (/hermes-sessions/ under the Tailscale-only ~/hermes-web site).
For cron job execution history, the same static-export pattern applies to ~/.hermes/cron/jobs.json and ~/.hermes/cron/output/{job_id}/*.md. See references/cron-history-web-viewer.md for the cron data model, schedule-dict pitfall, and the user's deployed /cron-history/ dashboard.
Cron Jobs
hermes cron list List jobs (--all for disabled)
hermes cron create SCHED Create: '30m', 'every 2h', '0 9 *'
hermes cron edit ID Edit schedule, prompt, delivery
hermes cron pause/resume ID Control job state
hermes cron run ID Trigger on next tick
hermes cron remove ID Delete a job
hermes cron status Scheduler status
For bounded autonomous lab/orchestrator cron jobs that use file-based state, subagent lanes, artifact publishing, and status transitions (active โ complete/blocked/inactive), see references/autonomous-agent-lab-cron-cycle.md. A reusable verification script template lives at scripts/verify-completion-template.py.
For a worked example of evolving an autonomous lab into a config-driven, themeable, Docker-ready installable product, see references/autonomous-lab-product-architecture.md. For CI, integration testing, pluggable adapter architecture, bounded cycle orchestration, and post-productization patterns, see references/product-maturity-patterns.md.
For the final completion verification checklist โ the explicit audit pattern to run before marking status: complete on an installable-solution mission, see references/autonomous-lab-completion-verification.md.
For the reactivation protocol when a completed lab receives new P0 feedback or the user contradicts a completion claim, see references/autonomous-lab-reactivation-protocol.md.
For the config/CHANGELOG version drift pitfall that occurs when autonomous labs evolve over many cycles, and for the related source vs. published file drift problem where the live web root diverges from the project source, see references/autonomous-lab-version-drift.md.
For adding historical trend tracking (SQLite-backed agent status transitions + vanilla JS SVG sparklines) to an autonomous lab dashboard, see references/history-tracking-sparkline-pattern.md.
For reusable dashboard UX patterns (onboarding tours, data freshness badges, keyboard shortcuts, progressive disclosure inspectors, cross-linking between views), see references/dashboard-ux-patterns.md.
For the aggressive human-first inspector refinement โ when users report that details are hard to understand and the fix is to strip technical labels from the default view โ see references/progressive-disclosure-human-first.md.
For programmatic verification of CSS custom-property theme systems โ catching scoping bugs, confirming theme distinctness, and validating JS switching logic โ see references/theme-system-verification.md.
- For Son's Discord-first autonomous experiments where a channel hosts a repeated multi-agent loop, use the Autonomous Discord Agent Lab pattern: create file-based durable state, a paused cron orchestrator delivered to
discord:<channel_id>, then activate it from a user mission trigger. See references/autonomous-discord-agent-lab.md.
- For verifying that a release package (
tar.gz) is actually installable by third parties and contains no stale artifacts or hardcoded references, see references/release-package-verification.md and the reusable script at scripts/release-verify.sh.
Webhooks
hermes webhook subscribe N Create route at /webhooks/<name>
hermes webhook list List subscriptions
hermes webhook remove NAME Remove a subscription
hermes webhook test NAME Send a test POST
Profiles
hermes profile list List all profiles
hermes profile create NAME Create (--clone, --clone-all, --clone-from)
hermes profile use NAME Set sticky default
hermes profile delete NAME Delete a profile
hermes profile show NAME Show details
hermes profile alias NAME Manage wrapper scripts
hermes profile rename A B Rename a profile
hermes profile export NAME Export to tar.gz
hermes profile import FILE Import from archive
Credential Pools
hermes auth add Interactive credential wizard
hermes auth list [PROVIDER] List pooled credentials
hermes auth remove P INDEX Remove by provider + index
hermes auth reset PROVIDER Clear exhaustion status
Other
hermes insights [--days N] Usage analytics
hermes update Update to latest version
hermes pairing list/approve/revoke DM authorization
hermes plugins list/install/remove Plugin management
hermes honcho setup/status Honcho memory integration (requires honcho plugin)
hermes memory setup/status/off Memory provider config
hermes completion bash|zsh Shell completions
hermes acp ACP server (IDE integration)
hermes claw migrate Migrate from OpenClaw
hermes uninstall Uninstall Hermes
---
Slash Commands (In-Session)
Type these during an interactive chat session. New commands land fairly
often; if something below looks stale, run /help in-session for the
authoritative list or see the [live slash commands reference](https://hermes-agent.nousresearch.com/docs/reference/slash-commands).
The registry of record is hermes_cli/commands.py โ every consumer
(autocomplete, Telegram menu, Slack mapping, /help) derives from it.
Session Control
/new (/reset) Fresh session
/clear Clear screen + new session (CLI)
/retry Resend last message
/undo Remove last exchange
/title [name] Name the session
/compress Manually compress context
/stop Kill background processes
/rollback [N] Restore filesystem checkpoint
/snapshot [sub] Create or restore state snapshots of Hermes config/state (CLI)
/background <prompt> Run prompt in background
/queue <prompt> Queue for next turn
/steer <prompt> Inject a message after the next tool call without interrupting
/agents (/tasks) Show active agents and running tasks
/resume [name] Resume a named session
/goal [text|sub] Set a standing goal Hermes works on across turns until achieved
(subcommands: status, pause, resume, clear)
/redraw Force a full UI repaint (CLI)
Configuration
/config Show config (CLI)
/model [name] Show or change model
/personality [name] Set personality
/reasoning [level] Set reasoning (none|minimal|low|medium|high|xhigh|show|hide)
/verbose Cycle: off โ new โ all โ verbose
/voice [on|off|tts] Voice mode
/yolo Toggle approval bypass
/busy [sub] Control what Enter does while Hermes is working (CLI)
(subcommands: queue, steer, interrupt, status)
/indicator [style] Pick the TUI busy-indicator style (CLI)
(styles: kaomoji, emoji, unicode, ascii)
/footer [on|off] Toggle gateway runtime-metadata footer on final replies
/skin [name] Change theme (CLI)
/statusbar Toggle status bar (CLI)
Tools & Skills
/tools Manage tools (CLI)
/toolsets List toolsets (CLI)
/skills Search/install skills (CLI)
/skill <name> Load a skill into session
/reload-skills Re-scan ~/.hermes/skills/ for added/removed skills
/reload Reload .env variables into the running session (CLI)
/reload-mcp Reload MCP servers
/cron Manage cron jobs (CLI)
/curator [sub] Background skill maintenance (status, run, pin, archive, โฆ)
/kanban [sub] Multi-profile collaboration board (tasks, links, comments)
/plugins List plugins (CLI)
Gateway
/approve Approve a pending command (gateway)
/deny Deny a pending command (gateway)
/restart Restart gateway (gateway)
/sethome Set current chat as home channel (gateway)
/update Update Hermes to latest (gateway)
/topic [sub] Enable or inspect Telegram DM topic sessions (gateway)
/platforms (/gateway) Show platform connection status (gateway)
Utility
/branch (/fork) Branch the current session
/fast Toggle priority/fast processing
/browser Open CDP browser connection
/history Show conversation history (CLI)
/save Save conversation to file (CLI)
/copy [N] Copy the last assistant response to clipboard (CLI)
/paste Attach clipboard image (CLI)
/image Attach local image file (CLI)
Info
/help Show commands
/commands [page] Browse all commands (gateway)
/usage Token usage
/insights [days] Usage analytics
/gquota Show Google Gemini Code Assist quota usage (CLI)
/status Session info (gateway)
/profile Active profile info
/debug Upload debug report (system info + logs) and get shareable links
Exit
/quit (/exit, /q) Exit CLI
---
Key Paths & Config
~/.hermes/config.yaml Main configuration
~/.hermes/.env API keys and secrets
$HERMES_HOME/skills/ Installed skills
~/.hermes/sessions/ Session transcripts
~/.hermes/logs/ Gateway and error logs
~/.hermes/auth.json OAuth tokens and credential pools
~/.hermes/hermes-agent/ Source code (if git-installed)
Profiles use ~/.hermes/profiles/<name>/ with the same layout.
Config Sections
Edit with hermes config edit or hermes config set section.key value.
| Section | Key options |
|---------|-------------|
| model | default, provider, base_url, api_key, context_length |
| agent | max_turns (90), tool_use_enforcement |
| terminal | backend (local/docker/ssh/modal), cwd, timeout (180) |
| compression | enabled, threshold (0.50), target_ratio (0.20) |
| display | skin, tool_progress, show_reasoning, show_cost |
| stt | enabled, provider (local/groq/openai/mistral) |
| tts | provider (edge/elevenlabs/openai/minimax/mistral/neutts) |
| memory | memory_enabled, user_profile_enabled, provider |
| security | tirith_enabled, website_blocklist |
| delegation | model, provider, base_url, api_key, max_iterations (50), reasoning_effort |
| checkpoints | enabled, max_snapshots (50) |
| fallback_model | provider, model, base_url, key_env |
Fallback Providers
Hermes can automatically fail over to a backup provider:model when the primary is unavailable. This is turn-scoped โ each new user message starts with the primary restored; fallback only activates mid-turn when the primary fails.
Configuration ( ~/.hermes/config.yaml):
fallback_model:
provider: opencode-go
model: kimi-k2.6
Or use the interactive manager:
hermes fallback add # interactive picker
hermes fallback list # show fallback chain
hermes fallback remove # remove by index
Legacy note: fallback_model (singular) is the legacy single-fallback key. fallback_providers (list) supports multiple ordered fallbacks. When both exist, fallback_providers takes priority.
Trigger conditions (after exhausting retries where applicable):
- Rate limits (HTTP 429)
- Server errors (HTTP 500, 502, 503)
- Auth failures (HTTP 401, 403) โ immediately
- Not found (HTTP 404) โ immediately
- Invalid / empty responses repeatedly
Supported providers include all standard providers (OpenRouter, Anthropic, OpenCode Go/ Zen, Kimi, etc.) plus custom endpoints with base_url + key_env. Full provider docs: https://hermes-agent.nousresearch.com/docs/integrations/providers
Limitations:
- Subagent delegation does not inherit fallback config
- Cron jobs do not use fallback (use per-job provider/model overrides)
- Auxiliary tasks (vision, compression, etc.) use their own
auxiliary.* provider chain
For a deep-dive with worked examples and model lists, see references/fallback-providers.md.
Full config reference: https://hermes-agent.nousresearch.com/docs/user-guide/configuration
Providers
20+ providers supported. Set via hermes model or hermes setup.
| Provider | Auth | Key env var |
|----------|------|-------------|
| OpenRouter | API key | OPENROUTER_API_KEY |
| Anthropic | API key | ANTHROPIC_API_KEY |
| Nous Portal | OAuth | hermes auth |
| OpenAI Codex | OAuth | hermes auth |
| GitHub Copilot | Token | COPILOT_GITHUB_TOKEN |
| Google Gemini | API key | GOOGLE_API_KEY or GEMINI_API_KEY |
| DeepSeek | API key | DEEPSEEK_API_KEY |
| xAI / Grok | API key | XAI_API_KEY |
| Hugging Face | Token | HF_TOKEN |
| Z.AI / GLM | API key | GLM_API_KEY |
| MiniMax | API key | MINIMAX_API_KEY |
| MiniMax CN | API key | MINIMAX_CN_API_KEY |
| Kimi / Moonshot | API key | KIMI_API_KEY |
| Alibaba / DashScope | API key | DASHSCOPE_API_KEY |
| Xiaomi MiMo | API key | XIAOMI_API_KEY |
| Kilo Code | API key | KILOCODE_API_KEY |
| AI Gateway (Vercel) | API key | AI_GATEWAY_API_KEY |
| OpenCode Zen | API key | OPENCODE_ZEN_API_KEY |
| OpenCode Go | API key | OPENCODE_GO_API_KEY |
| Qwen OAuth | OAuth | hermes auth add qwen-oauth |
| Custom endpoint | Config | model.base_url + model.api_key in config.yaml |
| GitHub Copilot ACP | External | COPILOT_CLI_PATH or Copilot CLI |
Full provider docs: https://hermes-agent.nousresearch.com/docs/integrations/providers
Toolsets
Enable/disable via hermes tools (interactive) or hermes tools enable/disable NAME.
| Toolset | What it provides |
|---------|-----------------|
| web | Web search and content extraction |
| search | Web search only (subset of web) |
| browser | Browser automation (Browserbase, Camofox, or local Chromium) |
| terminal | Shell commands and process management |
| file | File read/write/search/patch |
| code_execution | Sandboxed Python execution |
| vision | Image analysis |
| image_gen | AI image generation |
| video | Video analysis and generation |
| tts | Text-to-speech |
| skills | Skill browsing and management |
| memory | Persistent cross-session memory |
| session_search | Search past conversations |
| delegation | Subagent task delegation |
| cronjob | Scheduled task management |
| clarify | Ask user clarifying questions |
| messaging | Cross-platform message sending |
| todo | In-session task planning and tracking |
| kanban | Multi-agent work-queue tools (gated to workers) |
| debugging | Extra introspection/debug tools (off by default) |
| safe | Minimal, low-risk toolset for locked-down sessions |
| spotify | Spotify playback and playlist control |
| homeassistant | Smart home control (off by default) |
| discord | Discord integration tools |
| discord_admin | Discord admin/moderation tools |
| feishu_doc | Feishu (Lark) document tools |
| feishu_drive | Feishu (Lark) drive tools |
| yuanbao | Yuanbao integration tools |
| rl | Reinforcement learning tools (off by default) |
| moa | Mixture of Agents (off by default) |
Full enumeration lives in toolsets.py as the TOOLSETS dict; _HERMES_CORE_TOOLS is the default bundle most platforms inherit from.
Tool changes take effect on /reset (new session). They do NOT apply mid-conversation to preserve prompt caching.
---
Security & Privacy Toggles
Common "why is Hermes doing X to my output / tool calls / commands?" toggles โ and the exact commands to change them. Most of these need a fresh session (/reset in chat, or start a new hermes invocation) because they're read once at startup.
Secret redaction in tool output
Secret redaction is off by default โ tool output (terminal stdout, read_file, web content, subagent summaries, etc.) passes through unmodified. If the user wants Hermes to auto-mask strings that look like API keys, tokens, and secrets before they enter the conversation context and logs:
hermes config set security.redact_secrets true # enable globally
Restart required. security.redact_secrets is snapshotted at import time โ toggling it mid-session (e.g. via export HERMES_REDACT_SECRETS=true from a tool call) will NOT take effect for the running process. Tell the user to run hermes config set security.redact_secrets true in a terminal, then start a new session. This is deliberate โ it prevents an LLM from flipping the toggle on itself mid-task.
Disable again with:
hermes config set security.redact_secrets false
PII redaction in gateway messages
Separate from secret redaction. When enabled, the gateway hashes user IDs and strips phone numbers from the session context before it reaches the model:
hermes config set privacy.redact_pii true # enable
hermes config set privacy.redact_pii false # disable (default)
Command approval prompts
By default (approvals.mode: manual), Hermes prompts the user before running shell commands flagged as destructive (rm -rf, git reset --hard, etc.). The modes are:
manual โ always prompt (default)
smart โ use an auxiliary LLM to auto-approve low-risk commands, prompt on high-risk
off โ skip all approval prompts (equivalent to --yolo)
hermes config set approvals.mode smart # recommended middle ground
hermes config set approvals.mode off # bypass everything (not recommended)
Per-invocation bypass without changing config:
hermes --yolo โฆ
export HERMES_YOLO_MODE=1
Note: YOLO / approvals.mode: off does NOT turn off secret redaction. They are independent.
Shell hooks allowlist
Some shell-hook integrations require explicit allowlisting before they fire. Managed via ~/.hermes/shell-hooks-allowlist.json โ prompted interactively the first time a hook wants to run.
Disabling the web/browser/image-gen tools
To keep the model away from network or media tools entirely, open hermes tools and toggle per-platform. Takes effect on next session (/reset). See the Tools & Skills section above.
---
Voice & Transcription
STT (Voice โ Text)
Voice messages from messaging platforms are auto-transcribed.
Provider priority (auto-detected):
1. Local faster-whisper โ free, no API key: pip install faster-whisper
2. Groq Whisper โ free tier: set GROQ_API_KEY
3. OpenAI Whisper โ paid: set VOICE_TOOLS_OPENAI_KEY
4. Mistral Voxtral โ set MISTRAL_API_KEY
Config:
stt:
enabled: true
provider: local # local, groq, openai, mistral
local:
model: base # tiny, base, small, medium, large-v3
TTS (Text โ Voice)
| Provider | Env var | Free? |
|----------|---------|-------|
| Edge TTS | None | Yes (default) |
| ElevenLabs | ELEVENLABS_API_KEY | Free tier |
| OpenAI | VOICE_TOOLS_OPENAI_KEY | Paid |
| MiniMax | MINIMAX_API_KEY | Paid |
| Mistral (Voxtral) | MISTRAL_API_KEY | Paid |
| NeuTTS (local) | None (pip install neutts[all] + espeak-ng) | Free |
Voice commands: /voice on (voice-to-voice), /voice tts (always voice), /voice off.
---
Spawning Additional Hermes Instances
Run additional Hermes processes as fully independent subprocesses โ separate sessions, tools, and environments.
When to Use This vs delegate_task
| | delegate_task | Spawning hermes process |
|-|-----------------|--------------------------|
| Isolation | Separate conversation, shared process | Fully independent process |
| Duration | Minutes (bounded by parent loop) | Hours/days |
| Tool access | Subset of parent's tools | Full tool access |
| Interactive | No | Yes (PTY mode) |
| Use case | Quick parallel subtasks | Long autonomous missions |
One-Shot Mode
terminal(command="hermes chat -q 'Research GRPO papers and write summary to ~/research/grpo.md'", timeout=300)
Background for long tasks:
terminal(command="hermes chat -q 'Set up CI/CD for ~/myapp'", background=true)
Interactive PTY Mode (via tmux)
Hermes uses prompt_toolkit, which requires a real terminal. Use tmux for interactive spawning:
Start
terminal(command="tmux new-session -d -s agent1 -x 120 -y 40 'hermes'", timeout=10)
Wait for startup, then send a message
terminal(command="sleep 8 && tmux send-keys -t agent1 'Build a FastAPI auth service' Enter", timeout=15)
Read output
terminal(command="sleep 20 && tmux capture-pane -t agent1 -p", timeout=5)
Send follow-up
terminal(command="tmux send-keys -t agent1 'Add rate limiting middleware' Enter", timeout=5)
Exit
terminal(command="tmux send-keys -t agent1 '/exit' Enter && sleep 2 && tmux kill-session -t agent1", timeout=10)
Multi-Agent Coordination
Agent A: backend
terminal(command="tmux new-session -d -s backend -x 120 -y 40 'hermes -w'", timeout=10)
terminal(command="sleep 8 && tmux send-keys -t backend 'Build REST API for user management' Enter", timeout=15)
Agent B: frontend
terminal(command="tmux new-session -d -s frontend -x 120 -y 40 'hermes -w'", timeout=10)
terminal(command="sleep 8 && tmux send-keys -t frontend 'Build React dashboard for user management' Enter", timeout=15)
Check progress, relay context between them
terminal(command="tmux capture-pane -t backend -p | tail -30", timeout=5)
terminal(command="tmux send-keys -t frontend 'Here is the API schema from the backend agent: ...' Enter", timeout=5)
Session Resume
Resume most recent session
terminal(command="tmux new-session -d -s resumed 'hermes --continue'", timeout=10)
Resume specific session
terminal(command="tmux new-session -d -s resumed 'hermes --resume 20260225_143052_a1b2c3'", timeout=10)
Tips
- Prefer
delegate_task for quick subtasks โ less overhead than spawning a full process
- Use
-w (worktree mode) when spawning agents that edit code โ prevents git conflicts
- Set timeouts for one-shot mode โ complex tasks can take 5-10 minutes
- Use
hermes chat -q for fire-and-forget โ no PTY needed
- Use tmux for interactive sessions โ raw PTY mode has
\r vs \n issues with prompt_toolkit
- For scheduled tasks, use the
cronjob tool instead of spawning โ handles delivery and retry
---
Durable & Background Systems
Four systems run alongside the main conversation loop. Quick reference
here; full developer notes live in AGENTS.md, user-facing docs under
website/docs/user-guide/features/.
Delegation (delegate_task)
Synchronous subagent spawn โ the parent waits for the child's summary
before continuing its own loop. Isolated context + terminal session.
- Single:
delegate_task(goal, context, toolsets).
- Batch:
delegate_task(tasks=[{goal, ...}, ...]) runs children in
parallel, capped by delegation.max_concurrent_children (default 3).
- Roles:
leaf (default; cannot re-delegate) vs orchestrator
(can spawn its own workers, bounded by delegation.max_spawn_depth).
- Not durable. If the parent is interrupted, the child is
cancelled. For work that must outlive the turn, use cronjob or
terminal(background=True, notify_on_complete=True).
Config: delegation.* in config.yaml.
Tuning max_concurrent_children
Default is 3. Rule of thumb for raising it:
- Light tasks (web search, file grep): up to
6-8
- Medium tasks (code execution, browser):
4-5
- Heavy tasks (builds, large data):
2-3
- Actual bottleneck is usually the API rate limit, not local CPU/RAM. On a 10-core M4 with 16GB RAM, CPU is rarely the constraint.
- Formula: start at
5, raise only if profiling shows idle time between API responses.
Cron (scheduled jobs)
Durable scheduler โ cron/jobs.py + cron/scheduler.py. Drive it via
the cronjob tool, the hermes cron CLI (list, add, edit,
pause, resume, run, remove), or the /cron slash command.
- Schedules: duration (
"30m", "2h"), "every" phrase
( "every monday 9am"), 5-field cron ( "0 9 *"), or ISO timestamp.
- Per-job knobs:
skills, model/provider override, script
(pre-run data collection; no_agent=True makes the script the whole
job), context_from (chain job A's output into job B), workdir
(run in a specific dir with its AGENTS.md / CLAUDE.md loaded),
multi-platform delivery.
- Invariants: 3-minute hard interrupt per run,
.tick.lock file
prevents duplicate ticks across processes, cron sessions pass
skip_memory=True by default, and cron deliveries are framed with a
header/footer instead of being mirrored into the target gateway
session (keeps role alternation intact).
User docs: https://hermes-agent.nousresearch.com/docs/user-guide/features/cron
Curator (skill lifecycle)
Background maintenance for agent-created skills. Tracks usage, marks
idle skills stale, archives stale ones, keeps a pre-run tar.gz backup
so nothing is lost.
- CLI:
hermes curator <verb> โ status, run, pause, resume,
pin, unpin, archive, restore, prune, backup, rollback.
- Slash:
/curator <subcommand> mirrors the CLI.
- Scope: only touches skills with
created_by: "agent" provenance.
Bundled + hub-installed skills are off-limits. Never deletes โ
max destructive action is archive. Pinned skills are exempt from
every auto-transition and every LLM review pass.
- Telemetry: sidecar at
~/.hermes/skills/.usage.json holds
per-skill use_count, view_count, patch_count,
last_activity_at, state, pinned.
Config: curator.* (enabled, interval_hours, min_idle_hours,
stale_after_days, archive_after_days, backup.*).
User docs: https://hermes-agent.nousresearch.com/docs/user-guide/features/curator
Dreaming (periodic memory/skill consolidation)
For Anthropic-style "dreaming" workflows, combine cron + session_search + memory + skills + curator into a scheduled review loop. Start with a weekly, proposal-only report that audits recent sessions, repeated user corrections, memory conflicts, skill patch candidates, and cron/automation improvements. Do not automatically delete/replace memory or patch/archive skills unless the user explicitly approves the proposed changes. See references/weekly-dreaming-routine.md for the recommended prompt, report format, safety policy, and cron creation pattern.
Kanban (multi-agent work queue)
Durable SQLite board for multi-profile / multi-worker collaboration.
Users drive it via hermes kanban <verb>; dispatcher-spawned workers
see a focused kanban_* toolset gated by HERMES_KANBAN_TASK so the
schema footprint is zero outside worker processes.
- CLI verbs (common):
init, create, list (alias ls),
show, assign, link, unlink, comment, complete, block,
unblock, archive, tail. Less common: watch, stats, runs,
log, dispatch, daemon, gc.
- Worker toolset:
kanban_show, kanban_complete, kanban_block,
kanban_heartbeat, kanban_comment, kanban_create, kanban_link.
- Dispatcher runs inside the gateway by default
( kanban.dispatch_in_gateway: true) โ reclaims stale claims,
promotes ready tasks, atomically claims, spawns assigned profiles.
Auto-blocks a task after ~5 consecutive spawn failures.
- Isolation: board is the hard boundary (workers get
HERMES_KANBAN_BOARD pinned in env); tenant is a soft namespace
within a board for workspace-path + memory-key isolation.
User docs: https://hermes-agent.nousresearch.com/docs/user-guide/features/kanban
Log Relay (Hermes โ Discord)
A background Python script that tails ~/.hermes/logs/*.log and batches lines to a Discord channel. Includes session-ID extraction, rate-limit handling, and auto-restart via launchd/systemd. Useful for remote monitoring and audit trails.
- Reference:
references/discord-log-relay.md โ full setup, tuning, macOS/Linux service install, pitfalls.
- Template:
templates/discord-log-relay.py โ copy, set CHANNEL_ID, and deploy.
- Discord operations:
references/discord-operating-planes.md โ channel-purpose routing, periodic-summary vs Dreaming report formats, and safety/cost notes for Discord-first Hermes deployments.
Key pitfall: ask the user about batch frequency upfront rather than defaulting to real-time streaming. Most users prefer 10-minute or hourly batches. High-volume raw logs should be batched, summarized, or stored out-of-band; avoid Discord message storms during error loops.
Weekly Dreaming / Memory Curation
For long-running Hermes deployments, users may want an Anthropic-style "Dreaming" loop: a scheduled review that consolidates experience, proposes memory/skill/cron changes, and identifies what to keep, weaken, archive, or delete. Hermes has the building blocks (sessions, session_search, memory, skills, curator, cron), but the safe default is proposal mode:
1. Inspect recent usage and sessions.
2. Extract repeated success patterns, failure patterns, and user corrections.
3. Propose memory updates/removals without applying them silently.
4. Propose skill patches/archive candidates and cron/reporting improvements.
5. End with explicit approval checkboxes.
Do not silently rewrite or delete memory/skills from a Dreaming report unless the user explicitly authorized automatic application. See references/discord-operating-planes.md for a report template and routing heuristics.
---
Windows-Specific Quirks
Hermes runs natively on Windows (PowerShell, cmd, Windows Terminal, git-bash
mintty, VS Code integrated terminal). Most of it just works, but a handful
of differences between Win32 and POSIX have bitten us โ document new ones
here as you hit them so the next person (or the next session) doesn't
rediscover them from scratch.
Input / Keybindings
Alt+Enter doesn't insert a newline. Windows Terminal intercepts Alt+Enter
at the terminal layer to toggle fullscreen โ the keystroke never reaches
prompt_toolkit. Use Ctrl+Enter instead. Windows Terminal delivers
Ctrl+Enter as LF ( c-j), distinct from plain Enter ( c-m / CR), and the
CLI binds c-j to newline insertion on win32 only (see
_bind_prompt_submit_keys + the Windows-only c-j binding in cli.py).
Side effect: the raw Ctrl+J keystroke also inserts a newline on Windows โ
unavoidable, because Windows Terminal collapses Ctrl+Enter and Ctrl+J to
the same keycode at the Win32 console API layer. No conflicting binding
existed for Ctrl+J on Windows, so this is a harmless side effect.
mintty / git-bash behaves the same (fullscreen on Alt+Enter) unless you
disable Alt+Fn shortcuts in Options โ Keys. Easier to just use Ctrl+Enter.
Diagnosing keybindings. Run python scripts/keystroke_diagnostic.py
(repo root) to see exactly how prompt_toolkit identifies each keystroke
in the current terminal. Answers questions like "does Shift+Enter come
through as a distinct key?" (almost never โ most terminals collapse it
to plain Enter) or "what byte sequence is my terminal sending for
Ctrl+Enter?" This is how the Ctrl+Enter = c-j fact was established.
Config / Files
HTTP 400 "No models provided" on first run. config.yaml was saved
with a UTF-8 BOM (common when Windows apps write it). Re-save as UTF-8
without BOM. hermes config edit writes without BOM; manual edits in
Notepad are the usual culprit.
execute_code / Sandbox
WinError 10106 ("The requested service provider could not be loaded
or initialized") from the sandbox child process โ it can't create an
AF_INET socket, so the loopback-TCP RPC fallback fails before
connect(). Root cause is usually not a broken Winsock LSP; it's
Hermes's own env scrubber dropping SYSTEMROOT / WINDIR / COMSPEC
from the child env. Python's socket module needs SYSTEMROOT to locate
mswsock.dll. Fixed via the _WINDOWS_ESSENTIAL_ENV_VARS allowlist in
tools/code_execution_tool.py. If you still hit it, echo os.environ
inside an execute_code block to confirm SYSTEMROOT is set. Full
diagnostic recipe in references/execute-code-sandbox-env-windows.md.
Testing / Contributing
scripts/run_tests.sh doesn't work as-is on Windows โ it looks for
POSIX venv layouts ( .venv/bin/activate). The Hermes-installed venv at
venv/Scripts/ has no pip or pytest either (stripped for install size).
Workaround: install pytest + pytest-xdist + pyyaml into a system Python
3.11 user site, then invoke pytest directly with PYTHONPATH set:
"/c/Program Files/Python311/python" -m pip install --user pytest pytest-xdist pyyaml
export PYTHONPATH="$(pwd)"
"/c/Program Files/Python311/python" -m pytest tests/foo/test_bar.py -v --tb=short -n 0
Use -n 0, not -n 4 โ pyproject.toml's default addopts already
includes -n, and the wrapper's CI-parity guarantees don't apply off POSIX.
POSIX-only tests need skip guards. Common markers already in the codebase:
- Symlinks โ elevated privileges on Windows
0o600 file modes โ POSIX mode bits not enforced on NTFS by default
signal.SIGALRM โ Unix-only (see tests/conftest.py::_enforce_test_timeout)
- Winsock / Windows-specific regressions โ
@pytest.mark.skipif(sys.platform != "win32", ...)
Use the existing skip-pattern style (sys.platform == "win32" or
sys.platform.startswith("win")) to stay consistent with the rest of the
suite.
Path / Filesystem
Line endings. Git may warn LF will be replaced by CRLF the next time
Git touches it. Cosmetic โ the repo's .gitattributes normalizes. Don't
let editors auto-convert committed POSIX-newline files to CRLF.
Forward slashes work almost everywhere. C:/Users/... is accepted by
every Hermes tool and most Windows APIs. Prefer forward slashes in code
and logs โ avoids shell-escaping backslashes in bash.
---
Troubleshooting
Voice not working
1. Check stt.enabled: true in config.yaml
2. Verify provider: pip install faster-whisper or set API key
3. In gateway: /restart. In CLI: exit and relaunch.
Tool not available
1. hermes tools โ check if toolset is enabled for your platform
2. Some tools need env vars (check .env)
3. /reset after enabling tools
Model/provider issues
1. hermes doctor โ check config and dependencies
2. hermes auth add <provider> โ re-authenticate OAuth providers (use --type oauth)
3. Check .env has the right API key
4. Copilot 403: gh auth login tokens do NOT work for Copilot API. You must use the Copilot-specific OAuth device code flow via hermes model โ GitHub Copilot.
Changes not taking effect
- Tools/skills:
/reset starts a new session with updated toolset
- Config changes: In gateway:
/restart. In CLI: exit and relaunch.
- Code changes: Restart the CLI or gateway process
Deployed web dashboard shows stale CSS or theme changes
- Browser cache: Add
?v=N cache-busting query strings to CSS/JS/theme links in HTML.
- Service Worker cache: Bump
CACHE_NAME in sw.js to invalidate old shell caches.
- Data freshness: Use
fetch(url, {cache:'no-store'}) for live JSON feeds.
- Auto-detection: Embed
data-build in <html> and compare server build vs loaded build on page load to show a "new version available" banner. See references/static-site-cache-invalidation.md for the full diagnostic recipe and auto-detection pattern.
Dashboard inspector feels too technical
- The default inspector view should contain only plain-language sentences: headline, "what they're doing now", "why it matters", and a silent visual progress bar (no text label).
- Move all technical fields (source IDs, confidence scores, progress labels, status slugs, badges) behind a "Show technical details" toggle.
- If users say "details are hard to understand," the fix is to remove more fields from the default view, not to add explanations. Explanations of technical fields are still technical.
- See
references/progressive-disclosure-human-first.md for the aggressive simplification pattern.
Skills not showing
1. hermes skills list โ verify installed
2. hermes skills config โ check platform enablement
3. Load explicitly: /skill name or hermes -s name
Gateway issues
Check logs first:
grep -i "failed to send\|error" ~/.hermes/logs/gateway.log | tail -20
Common gateway problems:
- Gateway dies on SSH logout: Enable linger:
sudo loginctl enable-linger $USER
- Gateway dies on WSL2 close: WSL2 requires
systemd=true in /etc/wsl.conf for systemd services to work. Without it, gateway falls back to nohup (dies when session closes).
- Gateway crash loop: Reset the failed state:
systemctl --user reset-failed hermes-gateway
- macOS: bot shows offline after idle time: The gateway runs as a user agent (
LimitLoadToSessionType=Aqua), so macOS suspends it when the system sleeps. The platform websocket drops and the bot appears offline until the network returns. Fix: keep the Mac awake (System Settings -> Energy -> Prevent automatic sleeping, or caffeinate -d -i -s -u &). Low Power Mode makes this worse, not better. See references/macos-gateway-sleep-disconnect.md for the full diagnostic recipe.
Platform-specific issues
- Discord bot silent: Must enable Message Content Intent in Bot โ Privileged Gateway Intents. See full Discord setup reference:
references/discord-gateway-setup.md.
- Slack bot only works in DMs: Must subscribe to
message.channels event. Without it, the bot ignores public channels.
- Windows-specific issues (
Alt+Enter newline, WinError 10106, UTF-8 BOM config, test suite, line endings): see the dedicated Windows-Specific Quirks section above.
Auxiliary models not working
If auxiliary tasks (vision, compression, session_search) fail silently, the auto provider can't find a backend. Either set OPENROUTER_API_KEY or GOOGLE_API_KEY, or explicitly configure each auxiliary task's provider:
hermes config set auxiliary.vision.provider <your_provider>
hermes config set auxiliary.vision.model <model_name>
Full system auth provisioning
For a one-shot workflow to maximize available credentials โ installing gh, generating SSH keys, configuring git, enabling all Hermes toolsets, and auditing current auth state โ see references/system-auth-setup.md.
Editing large files with patch
When a file is read with read_file(offset=...) (pagination), the tool warns that the view is partial. If you attempt patch without re-reading the full file first, you will likely hit non-unique match errors or corrupt the file. Fix: always call read_file without offset to load the whole file before patching. The tool explicitly warns: "โฆwas last read with offset/limit pagination (partial view). Re-read the whole file before overwriting it." โ heed this warning. For append-only updates (e.g., adding a cycle log entry to state.md), do not use terminal(command="cat >> file << 'EOF'...EOF") โ the terminal tool on macOS/Linux misinterprets heredoc << as backgrounding and fails. Instead, write a short Python script via write_file and execute it with terminal(command="python3 /tmp/script.py"). See references/terminal-heredoc-workaround.md for the full pattern.
Sibling subagent file overwrites
When multiple subagents are running in parallel (e.g. via delegate_task batch mode or kanban worker lanes), a file may be modified by one subagent while another is about to write to it. If you use write_file or patch on a file that was last read before a sibling subagent modified it, your write may silently truncate or revert the sibling's changes. The tool may show a warning like "this file was modified by sibling subagent X but this agent never read it."
Fix:
1. Heed the warning. If the tool reports a sibling modification, re-read the file with read_file before writing.
2. Prefer patch over write_file for partial updates โ patch only changes the matched region and is less likely to wipe unrelated content.
3. If the file is already published/deployed, and the local working copy gets corrupted, recover from the published copy:
cp ~/hermes-web/agent-pets/css/dashboard.css ~/.hermes/autonomous-agent-lab/pixel-pet-ops/web/css/dashboard.css
4. For append-only updates, write a small Python script and execute it rather than using write_file on the whole file.
Prevention: In kanban/multi-agent workflows, assign file-level ownership so only one worker touches each file. If parallel workers must edit the same file, have them write to separate temp files and let the orchestrator merge.
---
Windows-Specific Quirks
| Looking for... | Location |
|----------------|----------|
| Config options | hermes config edit or [Configuration docs](https://hermes-agent.nousresearch.com/docs/user-guide/configuration) |
| Available tools | hermes tools list or [Tools reference](https://hermes-agent.nousresearch.com/docs/reference/tools-reference) |
| Slash commands | /help in session or [Slash commands reference](https://hermes-agent.nousresearch.com/docs/reference/slash-commands) |
| Skills catalog | hermes skills browse or [Skills catalog](https://hermes-agent.nousresearch.com/docs/reference/skills-catalog) |
| Provider setup | hermes model or [Providers guide](https://hermes-agent.nousresearch.com/docs/integrations/providers) |
| Platform setup | hermes gateway setup or [Messaging docs](https://hermes-agent.nousresearch.com/docs/user-guide/messaging/) |
| MCP servers | hermes mcp list or [MCP guide](https://hermes-agent.nousresearch.com/docs/user-guide/features/mcp) |
| Profiles | hermes profile list or [Profiles docs](https://hermes-agent.nousresearch.com/docs/user-guide/profiles) |
| Cron jobs | hermes cron list or [Cron docs](https://hermes-agent.nousresearch.com/docs/user-guide/features/cron) |
| Memory | hermes memory status or [Memory docs](https://hermes-agent.nousresearch.com/docs/user-guide/features/memory) |
| Env variables | hermes config env-path or [Env vars reference](https://hermes-agent.nousresearch.com/docs/reference/environment-variables) |
| CLI commands | hermes --help or [CLI reference](https://hermes-agent.nousresearch.com/docs/reference/cli-commands) |
| Gateway logs | ~/.hermes/logs/gateway.log |
| Session files | ~/.hermes/sessions/ or hermes sessions browse |
| Source code | ~/.hermes/hermes-agent/ |
---
Contributor Quick Reference
For occasional contributors and PR authors. Full developer docs: https://hermes-agent.nousresearch.com/docs/developer-guide/
Project Layout
hermes-agent/
โโโ run_agent.py # AIAgent โ core conversation loop
โโโ model_tools.py # Tool discovery and dispatch
โโโ toolsets.py # Toolset definitions
โโโ cli.py # Interactive CLI (HermesCLI)
โโโ hermes_state.py # SQLite session store
โโโ agent/ # Prompt builder, context compression, memory, model routing, credential pooling, skill dispatch
โโโ hermes_cli/ # CLI subcommands, config, setup, commands
โ โโโ commands.py # Slash command registry (CommandDef)
โ โโโ config.py # DEFAULT_CONFIG, env var definitions
โ โโโ main.py # CLI entry point and argparse
โโโ tools/ # One file per tool
โ โโโ registry.py # Central tool registry
โโโ gateway/ # Messaging gateway
โ โโโ platforms/ # Platform adapters (telegram, discord, etc.)
โโโ cron/ # Job scheduler
โโโ tests/ # ~3000 pytest tests
โโโ website/ # Docusaurus docs site
Config: ~/.hermes/config.yaml (settings), ~/.hermes/.env (API keys).
Adding a Tool (3 files)
1. Create tools/your_tool.py:
import json, os
from tools.registry import registry
def check_requirements() -> bool:
return bool(os.getenv("EXAMPLE_API_KEY"))
def example_tool(param: str, task_id: str = None) -> str:
return json.dumps({"success": True, "data": "..."})
registry.register(
name="example_tool",
toolset="example",
schema={"name": "example_tool", "description": "...", "parameters": {...}},
handler=lambda args, **kw: example_tool(
param=args.get("param", ""), task_id=kw.get("task_id")),
check_fn=check_requirements,
requires_env=["EXAMPLE_API_KEY"],
)
2. Add to toolsets.py โ _HERMES_CORE_TOOLS list.
Auto-discovery: any tools/*.py file with a top-level registry.register() call is imported automatically โ no manual list needed.
All handlers must return JSON strings. Use get_hermes_home() for paths, never hardcode ~/.hermes.
Adding a Slash Command
1. Add CommandDef to COMMAND_REGISTRY in hermes_cli/commands.py
2. Add handler in cli.py โ process_command()
3. (Optional) Add gateway handler in gateway/run.py
All consumers (help text, autocomplete, Telegram menu, Slack mapping) derive from the central registry automatically.
Agent Loop (High Level)
run_conversation():
1. Build system prompt
2. Loop while iterations < max:
a. Call LLM (OpenAI-format messages + tool schemas)
b. If tool_calls โ dispatch each via handle_function_call() โ append results โ continue
c. If text response โ return
3. Context compression triggers automatically near token limit
Testing
python -m pytest tests/ -o 'addopts=' -q # Full suite
python -m pytest tests/tools/ -q # Specific area
- Tests auto-redirect
HERMES_HOME to temp dirs โ never touch real ~/.hermes/
- Run full suite before pushing any change
- Use
-o 'addopts=' to clear any baked-in pytest flags
Windows contributors: scripts/run_tests.sh currently looks for POSIX venvs ( .venv/bin/activate / venv/bin/activate) and will error out on Windows where the layout is venv/Scripts/activate + python.exe. The Hermes-installed venv at venv/Scripts/ also has no pip or pytest โ it's stripped for end-user install size. Workaround: install pytest + pytest-xdist + pyyaml into a system Python 3.11 user site ( /c/Program Files/Python311/python -m pip install --user pytest pytest-xdist pyyaml), then run tests directly:
export PYTHONPATH="$(pwd)"
"/c/Program Files/Python311/python" -m pytest tests/tools/test_foo.py -v --tb=short -n 0
Use -n 0 (not -n 4) because pyproject.toml's default addopts already includes -n, and the wrapper's CI-parity story doesn't apply off-POSIX.
Cross-platform test guards: tests that use POSIX-only syscalls need a skip marker. Common ones already in the codebase:
- Symlink creation โ
@pytest.mark.skipif(sys.platform == "win32", reason="Symlinks require elevated privileges on Windows") (see tests/cron/test_cron_script.py)
- POSIX file modes (0o600, etc.) โ
@pytest.mark.skipif(sys.platform.startswith("win"), reason="POSIX mode bits not enforced on Windows") (see tests/hermes_cli/test_auth_toctou_file_modes.py)
signal.SIGALRM โ Unix-only (see tests/conftest.py::_enforce_test_timeout)
- Live Winsock / Windows-specific regression tests โ
@pytest.mark.skipif(sys.platform != "win32", reason="Windows-specific regression")
Monkeypatching sys.platform is not enough when the code under test also calls platform.system() / platform.release() / platform.mac_ver(). Those functions re-read the real OS independently, so a test that sets sys.platform = "linux" on a Windows runner will still see platform.system() == "Windows" and route through the Windows branch. Patch all three together:
monkeypatch.setattr(sys, "platform", "linux")
monkeypatch.setattr(platform, "system", lambda: "Linux")
monkeypatch.setattr(platform, "release", lambda: "6.8.0-generic")
See tests/agent/test_prompt_builder.py::TestEnvironmentHints for a worked example.
Extending the system prompt's execution-environment block
Factual guidance about the host OS, user home, cwd, terminal backend, and shell (bash vs. PowerShell on Windows) is emitted from agent/prompt_builder.py::build_environment_hints(). This is also where the WSL hint and per-backend probe logic live. The convention:
- Local terminal backend โ emit host info (OS,
$HOME, cwd) + Windows-specific notes (hostname โ username, terminal uses bash not PowerShell).
- Remote terminal backend (anything in
_REMOTE_TERMINAL_BACKENDS: docker, singularity, modal, daytona, ssh, vercel_sandbox, managed_modal) โ suppress host info entirely and describe only the backend. A live uname/whoami/pwd probe runs inside the backend via tools.environments.get_environment(...).execute(...), cached per process in _BACKEND_PROBE_CACHE, with a static fallback if the probe times out.
- Key fact for prompt authoring: when
TERMINAL_ENV != "local", every file tool (read_file, write_file, patch, search_files) runs inside the backend container, not on the host. The system prompt must never describe the host in that case โ the agent can't touch it.
Full design notes, the exact emitted strings, and testing pitfalls:
references/prompt-builder-environment-hints.md.
Refactor-safety pattern (POSIX-equivalence guard): when you extract inline logic into a helper that adds Windows/platform-specific behavior, keep a _legacy_<name> oracle function in the test file that's a verbatim copy of the old code, then parametrize-diff against it. Example: tests/tools/test_code_execution_windows_env.py::TestPosixEquivalence. This locks in the invariant that POSIX behavior is bit-for-bit identical and makes any future drift fail loudly with a clear diff.
Commit Conventions
type: concise subject line
Optional body.
Types: fix:, feat:, refactor:, docs:, chore:
Key Rules
- Never break prompt caching โ don't change context, tools, or system prompt mid-conversation
- Message role alternation โ never two assistant or two user messages in a row
- Use
get_hermes_home() from hermes_constants for all paths (profile-safe)
- Config values go in
config.yaml, secrets go in .env
- New tools need a
check_fn so they only appear when requirements are met
[IMPORTANT: The user has invoked the "kanban-orchestrator" skill, indicating they want you to follow its instructions. The full skill content is loaded below.]
---
name: kanban-orchestrator
description: Decomposition playbook + anti-temptation rules for an orchestrator profile routing work through Kanban. The "don't do the work yourself" rule and the basic lifecycle are auto-injected into every kanban worker's system prompt; this skill is the deeper playbook when you're specifically playing the orchestrator role.
version: 3.0.0
platforms: [linux, macos, windows]
metadata:
hermes:
tags: [kanban, multi-agent, orchestration, routing]
related_skills: [kanban-worker]
---
Kanban Orchestrator โ Decomposition Playbook
> The core worker lifecycle (including the kanban_create fan-out pattern and the "decompose, don't execute" rule) is auto-injected into every kanban process via the KANBAN_GUIDANCE system-prompt block. This skill is the deeper playbook when you're an orchestrator profile whose whole job is routing.
Profiles are user-configured โ not a fixed roster
Hermes setups vary widely. Some users run a single profile that does everything; some run a small fleet (docker-worker, cron-worker); some run a curated specialist team they've named themselves. There is no default specialist roster โ the orchestrator skill does not know what profiles exist on this machine.
Before fanning out, you must ground the decomposition in the profiles that actually exist. The dispatcher silently fails to spawn unknown assignee names โ it doesn't autocorrect, doesn't suggest, doesn't fall back. So a card assigned to researcher on a setup that only has docker-worker just sits in ready forever.
Step 0: discover available profiles before planning.
Use one of these:
hermes profile list โ prints the table of profiles configured on this machine. Run it through your terminal tool if you have one; otherwise ask the user.
kanban_list(assignee="<some-name>") โ sanity-check a single name. Returns an empty list (rather than an error) for an unknown assignee, so this only confirms a name you're already considering.
- Just ask the user. "What profiles do you have set up?" is a fine first turn when the goal needs more than one specialist.
Cache the result in your working memory for the rest of the conversation. Re-asking every turn wastes a tool call.
When to use the board (vs. just doing the work)
Create Kanban tasks when any of these are true:
1. Multiple specialists are needed. Research + analysis + writing is three profiles.
2. The work should survive a crash or restart. Long-running, recurring, or important.
3. The user might want to interject. Human-in-the-loop at any step.
4. Multiple subtasks can run in parallel. Fan-out for speed.
5. Review / iteration is expected. A reviewer profile loops on drafter output.
6. The audit trail matters. Board rows persist in SQLite forever.
If none of those apply โ it's a small one-shot reasoning task โ use delegate_task instead or answer the user directly.
The anti-temptation rules
Your job description says "route, don't execute." The rules that enforce that:
- Do not execute the work yourself. Your restricted toolset usually doesn't even include terminal/file/code/web for implementation. If you find yourself "just fixing this quickly" โ stop and create a task for the right specialist.
- For any concrete task, create a Kanban task and assign it. Every single time.
- Split multi-lane requests before creating cards. A user prompt can contain several independent workstreams. Extract those lanes first, then create one card per lane instead of bundling unrelated work into a single implementer card.
- Run independent lanes in parallel. If two cards do not need each other's output, leave them unlinked so the dispatcher can fan them out. Link only true data dependencies.
- If no specialist fits the available profiles, ask the user which profile to create or which existing profile to use. Do not invent profile names; the dispatcher will silently drop unknown assignees.
- Decompose, route, and summarize โ that's the whole job.
Exception: micro-UI polish cycles
There is one narrow exception where the orchestrator may execute directly instead of creating Kanban cards: tiny UI-only polish cycles (e.g., adding a CSS class, a theme preview dot, a hover state, a cross-link, or a HUD button) that are purely presentational, require no cross-file logic changes, and fit comfortably inside a single bounded cycle with no need for review or parallel work. If the change is limited to HTML/CSS/JS cosmetics, no other profile has a stake in it, and the user did not ask for a design review, the orchestrator should just edit and publish rather than paying the kanban-overhead tax. This exception does NOT apply to architecture changes, adapter logic, plugin interfaces, or anything that touches the data layer.
Decomposition playbook
Step 1 โ Understand the goal
Ask clarifying questions if the goal is ambiguous. Cheap to ask; expensive to spawn the wrong fleet.
Step 2 โ Sketch the task graph
Before creating anything, draft the graph out loud (in your response to the user). Treat every concrete workstream as a candidate card:
1. Extract the lanes from the request.
2. Map each lane to one of the profiles you discovered in Step 0. If a lane doesn't fit any existing profile, ask the user which to use or create.
3. Decide whether each lane is independent or gated by another lane.
4. Create independent lanes as parallel cards with no parent links.
5. Create synthesis/review/integration cards with parent links to the lanes they depend on.
Examples of prompts that should fan out (using placeholder profile names โ substitute whatever exists on the user's setup):
- "Build an app" โ one card to a design-oriented profile for product/UI direction, one or two cards to engineering profiles for implementation, plus a later integration/review card if the user has a reviewer profile.
- "Fix blockers and check model variants" โ one implementation card for the blocker fixes plus one discovery/research card for config/source verification. A final reviewer card can depend on both.
- "Research docs and implement" โ a docs-research card can run in parallel with a codebase-discovery card; implementation waits only if it truly needs those findings.
- "Analyze this screenshot and find the related code" โ one card to a vision-capable profile for the visual analysis while another searches the codebase.
Words like "also," "finally," or "and" do not automatically imply a dependency. They often mean "make sure this is covered before reporting back." Only link tasks when one card cannot start until another card's output exists.
Show the graph to the user before creating cards. Let them correct it โ including which actual profile name should own each lane.
Step 3 โ Create tasks and link
Use the profile names from Step 0. The example below uses placeholders <profile-A>, <profile-B>, <profile-C> โ replace them with what the user actually has.
t1 = kanban_create(
title="research: Postgres cost vs current",
assignee="<profile-A>", # whichever profile handles research on this setup
body="Compare estimated infrastructure costs, migration costs, and ongoing ops costs over a 3-year window. Sources: AWS/GCP pricing, team time estimates, current Postgres bills from peers.",
tenant=os.environ.get("HERMES_TENANT"),
)["task_id"]
t2 = kanban_create(
title="research: Postgres performance vs current",
assignee="<profile-A>", # same profile, run in parallel
body="Compare query latency, throughput, and scaling characteristics at our expected data volume (~500GB, 10k QPS peak). Sources: benchmark papers, public case studies, pgbench results if easy.",
)["task_id"]
t3 = kanban_create(
title="synthesize migration recommendation",
assignee="<profile-B>", # whichever profile does synthesis/analysis
body="Read the findings from T1 (cost) and T2 (performance). Produce a 1-page recommendation with explicit trade-offs and a go/no-go call.",
parents=[t1, t2],
)["task_id"]
t4 = kanban_create(
title="draft decision memo",
assignee="<profile-C>", # whichever profile drafts user-facing prose
body="Turn the analyst's recommendation into a 2-page memo for the CTO. Match the tone of previous decision memos in the team's knowledge base.",
parents=[t3],
)["task_id"]
parents=[...] gates promotion โ children stay in todo until every parent reaches done, then auto-promote to ready. No manual coordination needed; the dispatcher and dependency engine handle it.
Step 4 โ Complete your own task
If you were spawned as a task yourself (e.g. a planner profile was assigned T0: "investigate Postgres migration"), mark it done with a summary of what you created:
kanban_complete(
summary="decomposed into T1-T4: 2 research lanes in parallel, 1 synthesis on their outputs, 1 prose draft on the recommendation",
metadata={
"task_graph": {
"T1": {"assignee": "<profile-A>", "parents": []},
"T2": {"assignee": "<profile-A>", "parents": []},
"T3": {"assignee": "<profile-B>", "parents": ["T1", "T2"]},
"T4": {"assignee": "<profile-C>", "parents": ["T3"]},
},
},
)
Step 5 โ Report back to the user
Tell them what you created in plain prose, naming the actual profiles you used:
> I've queued 4 tasks:
> - T1 (<profile-A>): cost comparison
> - T2 (<profile-A>): performance comparison, in parallel with T1
> - T3 (<profile-B>): synthesizes T1 + T2 into a recommendation
> - T4 (<profile-C>): turns T3 into a CTO memo
>
> The dispatcher will pick up T1 and T2 now. T3 starts when both finish. You'll get a gateway ping when T4 completes. Use the dashboard or hermes kanban tail <id> to follow along.
Common patterns
Fan-out + fan-in (research โ synthesize): N research-style cards with no parents, one synthesis card with all of them as parents.
Parallel implementation + validation: one implementer card makes the change while one explorer/researcher card verifies config, docs, or source mapping. A reviewer card can depend on both. Do not make the implementer own unrelated verification just because the user mentioned both in one sentence.
Pipeline with gates: planner โ implementer โ reviewer. Each stage's parents=[previous_task]. Reviewer blocks or completes; if reviewer blocks, the operator unblocks with feedback and respawns.
Same-profile queue: N tasks, all assigned to the same profile, no dependencies between them. Dispatcher serializes โ that profile processes them in priority order, accumulating experience in its own memory.
Parallel UI/frontend lanes: When the goal touches multiple independent HTML/CSS/JS files (e.g., a dashboard page and a 2D gather view), fan out to separate subagents per file. Each lane edits its own file, then the orchestrator integrates, fixes cross-file references (theme paths, shared JSON endpoints), and publishes. This avoids merge conflicts in single-file HTML dashboards and keeps each subagent's context focused. See references/parallel-ui-lanes-and-publishing.md for the post-subagent integration checklist and rsync safety notes.
Human-in-the-loop: Any task can kanban_block() to wait for input. Dispatcher respawns after /unblock. The comment thread carries the full context.
Pitfalls
Inventing profile names that don't exist. The dispatcher silently fails to spawn unknown assignees โ the card just sits in ready forever. Always assign to a profile from your Step 0 discovery; ask the user if you're unsure.
Bundling independent lanes into one card. If the user asks for two independent outcomes, create two cards. Example: "fix blockers and check model variants" is not one fixer task; create a fixer/engineer card for the fixes and an explorer/researcher card for the variant check, then optionally gate review on both.
Over-linking because of wording. "Finally check X" may still be parallel with implementation if X is static config, docs, or source discovery. Link it after implementation only when the check depends on the implementation result.
Forgetting dependency links. If the task graph says research -> implement -> review, do not create all tasks as independent ready cards. Use parent links so implement/review cannot run before their inputs exist.
Reassignment vs. new task. If a reviewer blocks with "needs changes," create a NEW task linked from the reviewer's task โ don't re-run the same task with a stern look. The new task is assigned to the original implementer profile.
Argument order for links. kanban_link(parent_id=..., child_id=...) โ parent first. Mixing them up demotes the wrong task to todo.
Ignoring explicit user feedback to keep building infrastructure. When the user says a specific UX issue (legibility, theme switching, movement density) is "immediate priority," treat it as P0 and route it before deeper packaging/architecture work. Infrastructure polish feels productive, but shipping user-visible fixes is what matters. Create cards for the UX feedback first, then resume infrastructure lanes.
Treating status: complete as immutable when user feedback says otherwise. A state.md that says status: complete does not override a user's report that a completion criterion is actually broken. If the user says "theme switching is not working" and the Final Completion Condition requires "working UI theme switcher," the mission is not complete. Reactivate immediately: set status: active, append a reactivation cycle log, and fix the issue. Do not burn cycles on post-complete verification while the user is reporting active defects.
Don't pre-create the whole graph if the shape depends on intermediate findings. If T3's structure depends on what T1 and T2 find, let T3 exist as a "synthesize findings" task whose own first step is to read parent handoffs and plan the rest. Orchestrators can spawn orchestrators.
Tenant inheritance. If HERMES_TENANT is set in your env, pass tenant=os.environ.get("HERMES_TENANT") on every kanban_create call so child tasks stay in the same namespace.
Verifying cross-file references after directory reorganization. When subagents edit HTML/CSS/JS files and the directory structure shifts (e.g., moving files from root into web/dashboard/ and web/gather/), relative asset paths ( themes/default/theme.css, ./ops-data.json) often break. After subagents finish, the orchestrator must grep for href= and src= in moved files and fix relative paths before publishing. Subagents don't know the final publish layout โ the orchestrator does.
Destructive sync wipes needed files. Commands like rsync -av --delete will delete destination files that aren't in the source list. If you publish a directory tree piecemeal (e.g., copy web/dashboard/ first, then web/gather/ separately), --delete on the first rsync will erase the gather files before the second rsync runs. Either list all source paths in a single rsync invocation, or omit --delete and use cp -r / rsync -av without deletion when doing staged copies.
Recovering stuck workers
When a worker profile keeps crashing, hallucinating, or getting blocked by its own mistakes (usually: wrong model, missing skill, broken credential), the kanban dashboard flags the task with a โ badge and opens a Recovery section in the drawer. Three primary actions:
1. Reclaim (or hermes kanban reclaim <task_id>) โ abort the running worker immediately and reset the task to ready. The existing claim TTL is ~15 min; this is the fast path out.
2. Reassign (or hermes kanban reassign <task_id> <new-profile> --reclaim) โ switch the task to a different profile (one that exists on this setup) and let the dispatcher pick it up with a fresh worker.
3. Change profile model โ the dashboard prints a copy-paste hint for hermes -p <profile> model since profile config lives on disk; edit it in a terminal, then Reclaim to retry with the new model.
Hallucination warnings appear on tasks where a worker's kanban_complete(created_cards=[...]) claim included card ids that don't exist or weren't created by the worker's profile (the gate blocks the completion), or where the free-form summary references t_<hex> ids that don't resolve (advisory prose scan, non-blocking). Both produce audit events that persist even after recovery actions โ the trail stays for debugging.
The user has provided the following instruction alongside the skill invocation: [IMPORTANT: You are running as a scheduled cron job. DELIVERY: Your final response will be automatically delivered to the user โ do NOT use send_message or try to deliver the output yourself. Just produce your report/output as your final response and the system handles the rest. SILENT: If there is genuinely nothing new to report, respond with exactly "[SILENT]" (nothing else) to suppress delivery. Never combine [SILENT] with content โ either report your findings normally, or say [SILENT] and nothing more.]
You are the 15-minute Orchestrator for Son's Autonomous Agent Lab v1, reporting to Discord channel ID 1505805763824586952.
Durable state path: /Users/jooho-hermes/.hermes/autonomous-agent-lab/state.md
Working directory for experiment artifacts: /Users/jooho-hermes/.hermes/autonomous-agent-lab/
Preferred published web root: /Users/jooho-hermes/hermes-web/agent-pets/
Top-level directive from Son:
- The project has evolved from a personal dashboard into an INSTALLABLE PRODUCT that external Hermes users can deploy.
- The final target is a self-contained, configurable, publishable solution: "Hermes Pixel Pet Ops Office".
- Do NOT shrink the mission into a small static MVP and autonomously stop.
- The Gather.town-style 2D spatial office is a first-class feature, not a side page.
Latest UX feedback from Son (treat as immediate priority before deeper packaging work):
- Details are hard for a human to understand. Add human-first summaries, plain-language labels, and progressive disclosure: summary first, technical details second.
- Gather Town version has too many agents roaming around. Reduce default movement, add density/speed controls, cluster agents by room/task, and add focus/calm mode.
- Theme switching is not visibly working. Implement real UI theme switcher with persistence and clear visual theme changes.
Key product requirements (installable solution level):
1. Config-driven architecture: all paths, URLs, colors, names, room layouts via config.yaml. No hardcoded references to jooho-hermes.
2. Self-contained package: clear directory structure (src/, web/, config/, docs/, scripts/), install script, requirements.txt.
3. Pluggable data adapter: support multiple backends via plugin architecture.
4. Themeable frontend: CSS variables driven from config, swappable themes, plus a working UI theme switcher.
5. Multi-tenant ready: works for any Hermes instance.
6. Build/Deploy ready: Dockerfile or docker-compose, or clear static-server setup.
7. Documentation: README, architecture docs, configuration reference, contributor guide.
8. Human-comprehensible UX: plain-language summaries and progressive disclosure for technical detail.
9. Gather.town calm mode: adjustable movement density/speed and less chaotic defaults.
10. Versioned releases: CHANGELOG.md, semantic versioning, release packaging.
Mission model:
- Read state.md first before doing anything else.
- If state.md says
status: inactive or has no Current Mission, do not invent work. Return exactly: ๐ก Autonomous Agent Lab ๋๊ธฐ์ค โ Son์ด ํธ๋ฆฌ๊ฑฐ/๋ฏธ์
์ ์ฃผ๋ฉด 15๋ถ ์ฌ์ดํด์ ์์ํฉ๋๋ค.
- If state.md says
status: active, run one bounded 15-minute cycle toward the full installable solution.
- If state.md says
status: complete, verify that the Final Completion Condition in state.md is truly met. If it is not fully met, reactivate or report that state needs correction.
Cycle procedure when active:
1. Read state.md first. Extract current mission, constraints, previous cycle log, and Final Completion Condition.
2. Decide the next smallest useful step toward installable solution quality. Focus on: architecture, configurability, documentation, and clean separation of concerns.
3. Use delegate_task for independent subagent lanes when helpful.
4. Prefer concrete progress: refactor to config-driven, add install scripts, create docs, add Docker support, theme system, plugin architecture.
5. Update state.md with a new cycle log entry before final reporting.
6. Completion rule: only set status: complete when every item under state.md Final Completion Condition is satisfied. A non-installable MVP is not complete.
7. Stop/block only if Son explicitly stops/redirects, a safety boundary is reached, or a hard blocker needs Son's decision.
Link requirement (never forget):
- Every cycle report MUST include at least one direct viewable link to the published dashboard/artifact.
- The canonical URL:
http://hermes-mac-mini.tail46b3c6.ts.net:8099/agent-pets/
- Include gather town URL too:
http://hermes-mac-mini.tail46b3c6.ts.net:8099/agent-pets/gather/
Final Discord message format:
[Autonomous Agent Lab v1 / Cycle N]
๋ชฉํ:
์ํ:
๊ฒฐ๊ณผ:
๊ฒ์ฆ:
๋ค์:
์ํ:
Safety/quality rules:
- Do not handle secrets, passwords, API keys, payment, permission dialogs, or destructive commands.
- Do not claim completion without updating state.md.
- Do not rely on Discord history as durable state.
- Do not spam raw logs; summarize lane outputs and verification.
- Keep working in /Users/jooho-hermes/.hermes/autonomous-agent-lab/ and publish only to /Users/jooho-hermes/hermes-web/agent-pets/ unless the state file says otherwise.
Design/UX priorities:
- Mobile responsiveness is first-class.
- Character animation/movement is desired.
- Every cycle report must include published links.
- This is now a product engineering mission. Architecture, configurability, and documentation matter as much as visuals.
Response
[Autonomous Agent Lab v1 / Cycle 67]
๋ชฉํ:
Dashboard์ Gather Town์ ๋ฒ์ /๋ฑ์ง ๋ถ์ผ์น๋ฅผ ์์ ํ๊ณ , ๋ชจ๋ ๊ฒ์ ํ์ผ์ด v1.4.4 ยท b67๋ก ์ผ๊ด๋๊ฒ ํ์๋๋๋ก ์ ๋ฆฌ.
์ํ:
1. Dashboard ๋ฑ์ง ์์ : v1.4.4 ยท b65 โ v1.4.4 ยท b67 (data-build="67" ๋ฐ ?v=67์ ์ผ์น)
2. Gather Town ๋ฑ์ง ์์ : v1.4.5 ยท b67 โ v1.4.4 ยท b67 (config.yaml ๋ฒ์ 1.4.4์ ์ผ์น)
3. ์บ์ ๋ฒ์คํ
์ผ๊ด์ฑ ํ์ธ: dashboard/gather ๋ชจ๋ ์์ฐ ๋งํฌ ?v=67, sw.js CACHE_NAME = 'pixel-pet-ops-v21'
4. scripts/publish.sh๋ก ๋ชจ๋ ์์
์ฌ๊ฒ์
5. state.md์ Cycle 67 ๊ธฐ๋ก ์ถ๊ฐ, cycle_count: 67๋ก ๊ฐฑ์
๊ฒฐ๊ณผ:
- ๊ฒ์๋ ๋์๋ณด๋ ๋ฑ์ง:
v1.4.4 ยท b67 โ
- ๊ฒ์๋ Gather Town ๋ฑ์ง:
v1.4.4 ยท b67 โ
data-build="67" ๋์๋ณด๋ + Gather Town ๋ชจ๋ ์ผ์น
- ์์ค์ ๊ฒ์ ํ์ผ ๊ฐ diff 100% ์ผ์น
๊ฒ์ฆ:
- ํตํฉ ํ
์คํธ: 128/128 passed, 0 failed
- ์ค์น ๊ฒ์ฆ: 21/21 passed, 0 warned, 0 critical
- ์ด๋ํฐ: 32 agents, 15 cron jobs, 20 sessions, 16 events, schema 1.4
ops-data.json / health.json mtime fresh (< 60s)
refresh.err.log empty, LaunchAgent healthy
- ์์ค ๋ด ํ๋์ฝ๋ฉ๋
jooho-hermes ์ฐธ์กฐ 0๊ฑด
๋ค์:
- Son์ด ๋์๋ณด๋ ๋ฐฉ๋ฌธ ์ ๋ฑ์ง๊ฐ
v1.4.4 ยท b67๋ก ๋ณด์ด๋์ง ํ์ธ
- ํ
๋ง ์ ํ(hero panel), Gather calm mode(5 agents), ์ธ์คํํฐ human-first view ํ
์คํธ
- ์ธ ๊ฐ์ง ๋ชจ๋ ๋ง์กฑ ์
status: complete๋ก ๋ง๋ฌด๋ฆฌ
์ํ:
active โ ๋ฒ์ ํ๊ธฐ ์ผ๊ด์ฑ ๋ฌธ์ ํด๊ฒฐ, ๋ชจ๋ Final Completion Condition ์ถฉ์กฑ ์ ์ง. Son์ ๋ธ๋ผ์ฐ์ ์ธก ํ์ธ ๋๊ธฐ ์ค.
๋งํฌ:
- ๋์๋ณด๋: http://hermes-mac-mini.tail46b3c6.ts.net:8099/agent-pets/
- Gather Town: http://hermes-mac-mini.tail46b3c6.ts.net:8099/agent-pets/gather/
|
| 2026-05-19 19-22-14 |
82,450 chars |
2026-05-19_19-22-14.md |
Cron Job: autonomous-agent-lab-v1-orchestrator
Job ID: 35127ff89556
Run Time: 2026-05-19 19:22:14
Schedule: every 15m
Prompt
[IMPORTANT: The user has invoked the "hermes-agent" skill, indicating they want you to follow its instructions. The full skill content is loaded below.]
---
name: hermes-agent
description: "Configure, extend, or contribute to Hermes Agent."
version: 2.1.0
author: Hermes Agent + Teknium
license: MIT
platforms: [linux, macos, windows]
metadata:
hermes:
tags: [hermes, setup, configuration, multi-agent, spawning, cli, gateway, development]
homepage: https://github.com/NousResearch/hermes-agent
related_skills: [claude-code, codex, opencode]
---
Hermes Agent
Hermes Agent is an open-source AI agent framework by Nous Research that runs in your terminal, messaging platforms, and IDEs. It belongs to the same category as Claude Code (Anthropic), Codex (OpenAI), and OpenClaw โ autonomous coding and task-execution agents that use tool calling to interact with your system. Hermes works with any LLM provider (OpenRouter, Anthropic, OpenAI, DeepSeek, local models, and 15+ others) and runs on Linux, macOS, and WSL.
What makes Hermes different:
- Self-improving through skills โ Hermes learns from experience by saving reusable procedures as skills. When it solves a complex problem, discovers a workflow, or gets corrected, it can persist that knowledge as a skill document that loads into future sessions. Skills accumulate over time, making the agent better at your specific tasks and environment.
- Persistent memory across sessions โ remembers who you are, your preferences, environment details, and lessons learned. Pluggable memory backends (built-in, Honcho, Mem0, and more) let you choose how memory works.
- Multi-platform gateway โ the same agent runs on Telegram, Discord, Slack, WhatsApp, Signal, Matrix, Email, and 10+ other platforms with full tool access, not just chat.
- Provider-agnostic โ swap models and providers mid-workflow without changing anything else. Credential pools rotate across multiple API keys automatically.
- Profiles โ run multiple independent Hermes instances with isolated configs, sessions, skills, and memory.
- Extensible โ plugins, MCP servers, custom tools, webhook triggers, cron scheduling, and the full Python ecosystem.
People use Hermes for software development, research, system administration, data analysis, content creation, home automation, and anything else that benefits from an AI agent with persistent context and full system access.
This skill helps you work with Hermes Agent effectively โ setting it up, configuring features, spawning additional agent instances, troubleshooting issues, finding the right commands and settings, and understanding how the system works when you need to extend or contribute to it.
Docs: https://hermes-agent.nousresearch.com/docs/
Quick Start
Install
curl -fsSL https://raw.githubusercontent.com/NousResearch/hermes-agent/main/scripts/install.sh | bash
Interactive chat (default)
hermes
Single query
hermes chat -q "What is the capital of France?"
Setup wizard
hermes setup
Change model/provider
hermes model
Check health
hermes doctor
---
CLI Reference
Global Flags
hermes [flags] [command]
--version, -V Show version
--resume, -r SESSION Resume session by ID or title
--continue, -c [NAME] Resume by name, or most recent session
--worktree, -w Isolated git worktree mode (parallel agents)
--skills, -s SKILL Preload skills (comma-separate or repeat)
--profile, -p NAME Use a named profile
--yolo Skip dangerous command approval
--pass-session-id Include session ID in system prompt
No subcommand defaults to chat.
Chat
hermes chat [flags]
-q, --query TEXT Single query, non-interactive
-m, --model MODEL Model (e.g. anthropic/claude-sonnet-4)
-t, --toolsets LIST Comma-separated toolsets
--provider PROVIDER Force provider (openrouter, anthropic, nous, etc.)
-v, --verbose Verbose output
-Q, --quiet Suppress banner, spinner, tool previews
--checkpoints Enable filesystem checkpoints (/rollback)
--source TAG Session source tag (default: cli)
Configuration
hermes setup [section] Interactive wizard (model|terminal|gateway|tools|agent)
hermes model Interactive model/provider picker
hermes config View current config
hermes config edit Open config.yaml in $EDITOR
hermes config set KEY VAL Set a config value
hermes config path Print config.yaml path
hermes config env-path Print .env path
hermes config check Check for missing/outdated config
hermes config migrate Update config with new options
hermes doctor [--fix] Check dependencies and config
Credential Pools
hermes auth add Interactive credential wizard (oauth, api-key)
hermes auth list [PROVIDER] List pooled credentials
hermes auth remove P INDEX Remove by provider + index
hermes auth reset PROVIDER Clear exhaustion status
hermes logout Clear stored auth
Tools & Skills
hermes tools Interactive tool enable/disable (curses UI)
hermes tools list Show all tools and status
hermes tools enable NAME Enable a toolset
hermes tools disable NAME Disable a toolset
hermes skills list List installed skills
hermes skills search QUERY Search the skills hub
hermes skills install ID Install a skill (ID can be a hub identifier OR a direct https://โฆ/SKILL.md URL; pass --name to override when frontmatter has no name)
hermes skills inspect ID Preview without installing
hermes skills config Enable/disable skills per platform
hermes skills check Check for updates
hermes skills update Update outdated skills
hermes skills uninstall N Remove a hub skill
hermes skills publish PATH Publish to registry
hermes skills browse Browse all available skills
hermes skills tap add REPO Add a GitHub repo as skill source
MCP Servers
hermes mcp serve Run Hermes as an MCP server
hermes mcp add NAME Add an MCP server (--url or --command)
hermes mcp remove NAME Remove an MCP server
hermes mcp list List configured servers
hermes mcp test NAME Test connection
hermes mcp configure NAME Toggle tool selection
Gateway (Messaging Platforms)
hermes gateway run Start gateway foreground
hermes gateway install Install as background service
hermes gateway start/stop Control the service
hermes gateway restart Restart the service
hermes gateway status Check status
hermes gateway setup Configure platforms
Supported platforms: Telegram, Discord, Slack, WhatsApp, Signal, Email, SMS, Matrix, Mattermost, Home Assistant, DingTalk, Feishu, WeCom, BlueBubbles (iMessage), Weixin (WeChat), API Server, Webhooks. Open WebUI connects via the API Server adapter.
Platform docs: https://hermes-agent.nousresearch.com/docs/user-guide/messaging/
Discord-specific walkthrough (token, intents, service install, access control): see references/discord-gateway-setup.md in this skill.
- Per-channel personas and skill bindings: see
references/gateway-channel-personas.md (works on Discord, Slack, Telegram, Mattermost, Matrix).
- For long-running Discord-first operations, purpose-specific channel routing, periodic summaries, weekly Dreaming/audit reports, and log-safety patterns: see
references/discord-operating-planes.md.
- For broad Hermes/LifeOS/SQAF ecosystem audits (cron inventory, live services, dashboards, provider/model warnings, and control-plane gaps), see
references/ecosystem-audit.md.
Sessions
hermes sessions list List recent sessions
hermes sessions browse Interactive picker
hermes sessions export OUT Export to JSONL
hermes sessions rename ID T Rename a session
hermes sessions delete ID Delete a session
hermes sessions prune Clean up old sessions (--older-than N days)
hermes sessions stats Session store statistics
For browser-based viewing of existing Hermes CLI/Discord/cron session transcripts, prefer a lightweight static export from ~/.hermes/state.db into a private web root instead of assuming Open WebUI can browse Hermes' native session store. See references/hermes-session-static-web-viewer.md for the SQLite schema, static HTML export workflow, redaction/truncation cautions, and the user's Mac mini deployment (/hermes-sessions/ under the Tailscale-only ~/hermes-web site).
For cron job execution history, the same static-export pattern applies to ~/.hermes/cron/jobs.json and ~/.hermes/cron/output/{job_id}/*.md. See references/cron-history-web-viewer.md for the cron data model, schedule-dict pitfall, and the user's deployed /cron-history/ dashboard.
Cron Jobs
hermes cron list List jobs (--all for disabled)
hermes cron create SCHED Create: '30m', 'every 2h', '0 9 *'
hermes cron edit ID Edit schedule, prompt, delivery
hermes cron pause/resume ID Control job state
hermes cron run ID Trigger on next tick
hermes cron remove ID Delete a job
hermes cron status Scheduler status
For bounded autonomous lab/orchestrator cron jobs that use file-based state, subagent lanes, artifact publishing, and status transitions (active โ complete/blocked/inactive), see references/autonomous-agent-lab-cron-cycle.md. A reusable verification script template lives at scripts/verify-completion-template.py.
For a worked example of evolving an autonomous lab into a config-driven, themeable, Docker-ready installable product, see references/autonomous-lab-product-architecture.md. For CI, integration testing, pluggable adapter architecture, bounded cycle orchestration, and post-productization patterns, see references/product-maturity-patterns.md.
For the final completion verification checklist โ the explicit audit pattern to run before marking status: complete on an installable-solution mission, see references/autonomous-lab-completion-verification.md.
For the reactivation protocol when a completed lab receives new P0 feedback or the user contradicts a completion claim, see references/autonomous-lab-reactivation-protocol.md.
For the config/CHANGELOG version drift pitfall that occurs when autonomous labs evolve over many cycles, and for the related source vs. published file drift problem where the live web root diverges from the project source, see references/autonomous-lab-version-drift.md.
For adding historical trend tracking (SQLite-backed agent status transitions + vanilla JS SVG sparklines) to an autonomous lab dashboard, see references/history-tracking-sparkline-pattern.md.
For reusable dashboard UX patterns (onboarding tours, data freshness badges, keyboard shortcuts, progressive disclosure inspectors, cross-linking between views), see references/dashboard-ux-patterns.md.
For the aggressive human-first inspector refinement โ when users report that details are hard to understand and the fix is to strip technical labels from the default view โ see references/progressive-disclosure-human-first.md.
For programmatic verification of CSS custom-property theme systems โ catching scoping bugs, confirming theme distinctness, and validating JS switching logic โ see references/theme-system-verification.md.
For Son's Discord-first autonomous experiments where a channel hosts a repeated multi-agent loop, use the Autonomous Discord Agent Lab pattern: create file-based durable state, a paused cron orchestrator delivered to discord:<channel_id>, then activate it from a user mission trigger. See references/autonomous-discord-agent-lab.md.
Webhooks
hermes webhook subscribe N Create route at /webhooks/<name>
hermes webhook list List subscriptions
hermes webhook remove NAME Remove a subscription
hermes webhook test NAME Send a test POST
Profiles
hermes profile list List all profiles
hermes profile create NAME Create (--clone, --clone-all, --clone-from)
hermes profile use NAME Set sticky default
hermes profile delete NAME Delete a profile
hermes profile show NAME Show details
hermes profile alias NAME Manage wrapper scripts
hermes profile rename A B Rename a profile
hermes profile export NAME Export to tar.gz
hermes profile import FILE Import from archive
Credential Pools
hermes auth add Interactive credential wizard
hermes auth list [PROVIDER] List pooled credentials
hermes auth remove P INDEX Remove by provider + index
hermes auth reset PROVIDER Clear exhaustion status
Other
hermes insights [--days N] Usage analytics
hermes update Update to latest version
hermes pairing list/approve/revoke DM authorization
hermes plugins list/install/remove Plugin management
hermes honcho setup/status Honcho memory integration (requires honcho plugin)
hermes memory setup/status/off Memory provider config
hermes completion bash|zsh Shell completions
hermes acp ACP server (IDE integration)
hermes claw migrate Migrate from OpenClaw
hermes uninstall Uninstall Hermes
---
Slash Commands (In-Session)
Type these during an interactive chat session. New commands land fairly
often; if something below looks stale, run /help in-session for the
authoritative list or see the [live slash commands reference](https://hermes-agent.nousresearch.com/docs/reference/slash-commands).
The registry of record is hermes_cli/commands.py โ every consumer
(autocomplete, Telegram menu, Slack mapping, /help) derives from it.
Session Control
/new (/reset) Fresh session
/clear Clear screen + new session (CLI)
/retry Resend last message
/undo Remove last exchange
/title [name] Name the session
/compress Manually compress context
/stop Kill background processes
/rollback [N] Restore filesystem checkpoint
/snapshot [sub] Create or restore state snapshots of Hermes config/state (CLI)
/background <prompt> Run prompt in background
/queue <prompt> Queue for next turn
/steer <prompt> Inject a message after the next tool call without interrupting
/agents (/tasks) Show active agents and running tasks
/resume [name] Resume a named session
/goal [text|sub] Set a standing goal Hermes works on across turns until achieved
(subcommands: status, pause, resume, clear)
/redraw Force a full UI repaint (CLI)
Configuration
/config Show config (CLI)
/model [name] Show or change model
/personality [name] Set personality
/reasoning [level] Set reasoning (none|minimal|low|medium|high|xhigh|show|hide)
/verbose Cycle: off โ new โ all โ verbose
/voice [on|off|tts] Voice mode
/yolo Toggle approval bypass
/busy [sub] Control what Enter does while Hermes is working (CLI)
(subcommands: queue, steer, interrupt, status)
/indicator [style] Pick the TUI busy-indicator style (CLI)
(styles: kaomoji, emoji, unicode, ascii)
/footer [on|off] Toggle gateway runtime-metadata footer on final replies
/skin [name] Change theme (CLI)
/statusbar Toggle status bar (CLI)
Tools & Skills
/tools Manage tools (CLI)
/toolsets List toolsets (CLI)
/skills Search/install skills (CLI)
/skill <name> Load a skill into session
/reload-skills Re-scan ~/.hermes/skills/ for added/removed skills
/reload Reload .env variables into the running session (CLI)
/reload-mcp Reload MCP servers
/cron Manage cron jobs (CLI)
/curator [sub] Background skill maintenance (status, run, pin, archive, โฆ)
/kanban [sub] Multi-profile collaboration board (tasks, links, comments)
/plugins List plugins (CLI)
Gateway
/approve Approve a pending command (gateway)
/deny Deny a pending command (gateway)
/restart Restart gateway (gateway)
/sethome Set current chat as home channel (gateway)
/update Update Hermes to latest (gateway)
/topic [sub] Enable or inspect Telegram DM topic sessions (gateway)
/platforms (/gateway) Show platform connection status (gateway)
Utility
/branch (/fork) Branch the current session
/fast Toggle priority/fast processing
/browser Open CDP browser connection
/history Show conversation history (CLI)
/save Save conversation to file (CLI)
/copy [N] Copy the last assistant response to clipboard (CLI)
/paste Attach clipboard image (CLI)
/image Attach local image file (CLI)
Info
/help Show commands
/commands [page] Browse all commands (gateway)
/usage Token usage
/insights [days] Usage analytics
/gquota Show Google Gemini Code Assist quota usage (CLI)
/status Session info (gateway)
/profile Active profile info
/debug Upload debug report (system info + logs) and get shareable links
Exit
/quit (/exit, /q) Exit CLI
---
Key Paths & Config
~/.hermes/config.yaml Main configuration
~/.hermes/.env API keys and secrets
$HERMES_HOME/skills/ Installed skills
~/.hermes/sessions/ Session transcripts
~/.hermes/logs/ Gateway and error logs
~/.hermes/auth.json OAuth tokens and credential pools
~/.hermes/hermes-agent/ Source code (if git-installed)
Profiles use ~/.hermes/profiles/<name>/ with the same layout.
Config Sections
Edit with hermes config edit or hermes config set section.key value.
| Section | Key options |
|---------|-------------|
| model | default, provider, base_url, api_key, context_length |
| agent | max_turns (90), tool_use_enforcement |
| terminal | backend (local/docker/ssh/modal), cwd, timeout (180) |
| compression | enabled, threshold (0.50), target_ratio (0.20) |
| display | skin, tool_progress, show_reasoning, show_cost |
| stt | enabled, provider (local/groq/openai/mistral) |
| tts | provider (edge/elevenlabs/openai/minimax/mistral/neutts) |
| memory | memory_enabled, user_profile_enabled, provider |
| security | tirith_enabled, website_blocklist |
| delegation | model, provider, base_url, api_key, max_iterations (50), reasoning_effort |
| checkpoints | enabled, max_snapshots (50) |
| fallback_model | provider, model, base_url, key_env |
Fallback Providers
Hermes can automatically fail over to a backup provider:model when the primary is unavailable. This is turn-scoped โ each new user message starts with the primary restored; fallback only activates mid-turn when the primary fails.
Configuration ( ~/.hermes/config.yaml):
fallback_model:
provider: opencode-go
model: kimi-k2.6
Or use the interactive manager:
hermes fallback add # interactive picker
hermes fallback list # show fallback chain
hermes fallback remove # remove by index
Legacy note: fallback_model (singular) is the legacy single-fallback key. fallback_providers (list) supports multiple ordered fallbacks. When both exist, fallback_providers takes priority.
Trigger conditions (after exhausting retries where applicable):
- Rate limits (HTTP 429)
- Server errors (HTTP 500, 502, 503)
- Auth failures (HTTP 401, 403) โ immediately
- Not found (HTTP 404) โ immediately
- Invalid / empty responses repeatedly
Supported providers include all standard providers (OpenRouter, Anthropic, OpenCode Go/ Zen, Kimi, etc.) plus custom endpoints with base_url + key_env. Full provider docs: https://hermes-agent.nousresearch.com/docs/integrations/providers
Limitations:
- Subagent delegation does not inherit fallback config
- Cron jobs do not use fallback (use per-job provider/model overrides)
- Auxiliary tasks (vision, compression, etc.) use their own
auxiliary.* provider chain
For a deep-dive with worked examples and model lists, see references/fallback-providers.md.
Full config reference: https://hermes-agent.nousresearch.com/docs/user-guide/configuration
Providers
20+ providers supported. Set via hermes model or hermes setup.
| Provider | Auth | Key env var |
|----------|------|-------------|
| OpenRouter | API key | OPENROUTER_API_KEY |
| Anthropic | API key | ANTHROPIC_API_KEY |
| Nous Portal | OAuth | hermes auth |
| OpenAI Codex | OAuth | hermes auth |
| GitHub Copilot | Token | COPILOT_GITHUB_TOKEN |
| Google Gemini | API key | GOOGLE_API_KEY or GEMINI_API_KEY |
| DeepSeek | API key | DEEPSEEK_API_KEY |
| xAI / Grok | API key | XAI_API_KEY |
| Hugging Face | Token | HF_TOKEN |
| Z.AI / GLM | API key | GLM_API_KEY |
| MiniMax | API key | MINIMAX_API_KEY |
| MiniMax CN | API key | MINIMAX_CN_API_KEY |
| Kimi / Moonshot | API key | KIMI_API_KEY |
| Alibaba / DashScope | API key | DASHSCOPE_API_KEY |
| Xiaomi MiMo | API key | XIAOMI_API_KEY |
| Kilo Code | API key | KILOCODE_API_KEY |
| AI Gateway (Vercel) | API key | AI_GATEWAY_API_KEY |
| OpenCode Zen | API key | OPENCODE_ZEN_API_KEY |
| OpenCode Go | API key | OPENCODE_GO_API_KEY |
| Qwen OAuth | OAuth | hermes auth add qwen-oauth |
| Custom endpoint | Config | model.base_url + model.api_key in config.yaml |
| GitHub Copilot ACP | External | COPILOT_CLI_PATH or Copilot CLI |
Full provider docs: https://hermes-agent.nousresearch.com/docs/integrations/providers
Toolsets
Enable/disable via hermes tools (interactive) or hermes tools enable/disable NAME.
| Toolset | What it provides |
|---------|-----------------|
| web | Web search and content extraction |
| search | Web search only (subset of web) |
| browser | Browser automation (Browserbase, Camofox, or local Chromium) |
| terminal | Shell commands and process management |
| file | File read/write/search/patch |
| code_execution | Sandboxed Python execution |
| vision | Image analysis |
| image_gen | AI image generation |
| video | Video analysis and generation |
| tts | Text-to-speech |
| skills | Skill browsing and management |
| memory | Persistent cross-session memory |
| session_search | Search past conversations |
| delegation | Subagent task delegation |
| cronjob | Scheduled task management |
| clarify | Ask user clarifying questions |
| messaging | Cross-platform message sending |
| todo | In-session task planning and tracking |
| kanban | Multi-agent work-queue tools (gated to workers) |
| debugging | Extra introspection/debug tools (off by default) |
| safe | Minimal, low-risk toolset for locked-down sessions |
| spotify | Spotify playback and playlist control |
| homeassistant | Smart home control (off by default) |
| discord | Discord integration tools |
| discord_admin | Discord admin/moderation tools |
| feishu_doc | Feishu (Lark) document tools |
| feishu_drive | Feishu (Lark) drive tools |
| yuanbao | Yuanbao integration tools |
| rl | Reinforcement learning tools (off by default) |
| moa | Mixture of Agents (off by default) |
Full enumeration lives in toolsets.py as the TOOLSETS dict; _HERMES_CORE_TOOLS is the default bundle most platforms inherit from.
Tool changes take effect on /reset (new session). They do NOT apply mid-conversation to preserve prompt caching.
---
Security & Privacy Toggles
Common "why is Hermes doing X to my output / tool calls / commands?" toggles โ and the exact commands to change them. Most of these need a fresh session (/reset in chat, or start a new hermes invocation) because they're read once at startup.
Secret redaction in tool output
Secret redaction is off by default โ tool output (terminal stdout, read_file, web content, subagent summaries, etc.) passes through unmodified. If the user wants Hermes to auto-mask strings that look like API keys, tokens, and secrets before they enter the conversation context and logs:
hermes config set security.redact_secrets true # enable globally
Restart required. security.redact_secrets is snapshotted at import time โ toggling it mid-session (e.g. via export HERMES_REDACT_SECRETS=true from a tool call) will NOT take effect for the running process. Tell the user to run hermes config set security.redact_secrets true in a terminal, then start a new session. This is deliberate โ it prevents an LLM from flipping the toggle on itself mid-task.
Disable again with:
hermes config set security.redact_secrets false
PII redaction in gateway messages
Separate from secret redaction. When enabled, the gateway hashes user IDs and strips phone numbers from the session context before it reaches the model:
hermes config set privacy.redact_pii true # enable
hermes config set privacy.redact_pii false # disable (default)
Command approval prompts
By default (approvals.mode: manual), Hermes prompts the user before running shell commands flagged as destructive (rm -rf, git reset --hard, etc.). The modes are:
manual โ always prompt (default)
smart โ use an auxiliary LLM to auto-approve low-risk commands, prompt on high-risk
off โ skip all approval prompts (equivalent to --yolo)
hermes config set approvals.mode smart # recommended middle ground
hermes config set approvals.mode off # bypass everything (not recommended)
Per-invocation bypass without changing config:
hermes --yolo โฆ
export HERMES_YOLO_MODE=1
Note: YOLO / approvals.mode: off does NOT turn off secret redaction. They are independent.
Shell hooks allowlist
Some shell-hook integrations require explicit allowlisting before they fire. Managed via ~/.hermes/shell-hooks-allowlist.json โ prompted interactively the first time a hook wants to run.
Disabling the web/browser/image-gen tools
To keep the model away from network or media tools entirely, open hermes tools and toggle per-platform. Takes effect on next session (/reset). See the Tools & Skills section above.
---
Voice & Transcription
STT (Voice โ Text)
Voice messages from messaging platforms are auto-transcribed.
Provider priority (auto-detected):
1. Local faster-whisper โ free, no API key: pip install faster-whisper
2. Groq Whisper โ free tier: set GROQ_API_KEY
3. OpenAI Whisper โ paid: set VOICE_TOOLS_OPENAI_KEY
4. Mistral Voxtral โ set MISTRAL_API_KEY
Config:
stt:
enabled: true
provider: local # local, groq, openai, mistral
local:
model: base # tiny, base, small, medium, large-v3
TTS (Text โ Voice)
| Provider | Env var | Free? |
|----------|---------|-------|
| Edge TTS | None | Yes (default) |
| ElevenLabs | ELEVENLABS_API_KEY | Free tier |
| OpenAI | VOICE_TOOLS_OPENAI_KEY | Paid |
| MiniMax | MINIMAX_API_KEY | Paid |
| Mistral (Voxtral) | MISTRAL_API_KEY | Paid |
| NeuTTS (local) | None (pip install neutts[all] + espeak-ng) | Free |
Voice commands: /voice on (voice-to-voice), /voice tts (always voice), /voice off.
---
Spawning Additional Hermes Instances
Run additional Hermes processes as fully independent subprocesses โ separate sessions, tools, and environments.
When to Use This vs delegate_task
| | delegate_task | Spawning hermes process |
|-|-----------------|--------------------------|
| Isolation | Separate conversation, shared process | Fully independent process |
| Duration | Minutes (bounded by parent loop) | Hours/days |
| Tool access | Subset of parent's tools | Full tool access |
| Interactive | No | Yes (PTY mode) |
| Use case | Quick parallel subtasks | Long autonomous missions |
One-Shot Mode
terminal(command="hermes chat -q 'Research GRPO papers and write summary to ~/research/grpo.md'", timeout=300)
Background for long tasks:
terminal(command="hermes chat -q 'Set up CI/CD for ~/myapp'", background=true)
Interactive PTY Mode (via tmux)
Hermes uses prompt_toolkit, which requires a real terminal. Use tmux for interactive spawning:
Start
terminal(command="tmux new-session -d -s agent1 -x 120 -y 40 'hermes'", timeout=10)
Wait for startup, then send a message
terminal(command="sleep 8 && tmux send-keys -t agent1 'Build a FastAPI auth service' Enter", timeout=15)
Read output
terminal(command="sleep 20 && tmux capture-pane -t agent1 -p", timeout=5)
Send follow-up
terminal(command="tmux send-keys -t agent1 'Add rate limiting middleware' Enter", timeout=5)
Exit
terminal(command="tmux send-keys -t agent1 '/exit' Enter && sleep 2 && tmux kill-session -t agent1", timeout=10)
Multi-Agent Coordination
Agent A: backend
terminal(command="tmux new-session -d -s backend -x 120 -y 40 'hermes -w'", timeout=10)
terminal(command="sleep 8 && tmux send-keys -t backend 'Build REST API for user management' Enter", timeout=15)
Agent B: frontend
terminal(command="tmux new-session -d -s frontend -x 120 -y 40 'hermes -w'", timeout=10)
terminal(command="sleep 8 && tmux send-keys -t frontend 'Build React dashboard for user management' Enter", timeout=15)
Check progress, relay context between them
terminal(command="tmux capture-pane -t backend -p | tail -30", timeout=5)
terminal(command="tmux send-keys -t frontend 'Here is the API schema from the backend agent: ...' Enter", timeout=5)
Session Resume
Resume most recent session
terminal(command="tmux new-session -d -s resumed 'hermes --continue'", timeout=10)
Resume specific session
terminal(command="tmux new-session -d -s resumed 'hermes --resume 20260225_143052_a1b2c3'", timeout=10)
Tips
- Prefer
delegate_task for quick subtasks โ less overhead than spawning a full process
- Use
-w (worktree mode) when spawning agents that edit code โ prevents git conflicts
- Set timeouts for one-shot mode โ complex tasks can take 5-10 minutes
- Use
hermes chat -q for fire-and-forget โ no PTY needed
- Use tmux for interactive sessions โ raw PTY mode has
\r vs \n issues with prompt_toolkit
- For scheduled tasks, use the
cronjob tool instead of spawning โ handles delivery and retry
---
Durable & Background Systems
Four systems run alongside the main conversation loop. Quick reference
here; full developer notes live in AGENTS.md, user-facing docs under
website/docs/user-guide/features/.
Delegation (delegate_task)
Synchronous subagent spawn โ the parent waits for the child's summary
before continuing its own loop. Isolated context + terminal session.
- Single:
delegate_task(goal, context, toolsets).
- Batch:
delegate_task(tasks=[{goal, ...}, ...]) runs children in
parallel, capped by delegation.max_concurrent_children (default 3).
- Roles:
leaf (default; cannot re-delegate) vs orchestrator
(can spawn its own workers, bounded by delegation.max_spawn_depth).
- Not durable. If the parent is interrupted, the child is
cancelled. For work that must outlive the turn, use cronjob or
terminal(background=True, notify_on_complete=True).
Config: delegation.* in config.yaml.
Tuning max_concurrent_children
Default is 3. Rule of thumb for raising it:
- Light tasks (web search, file grep): up to
6-8
- Medium tasks (code execution, browser):
4-5
- Heavy tasks (builds, large data):
2-3
- Actual bottleneck is usually the API rate limit, not local CPU/RAM. On a 10-core M4 with 16GB RAM, CPU is rarely the constraint.
- Formula: start at
5, raise only if profiling shows idle time between API responses.
Cron (scheduled jobs)
Durable scheduler โ cron/jobs.py + cron/scheduler.py. Drive it via
the cronjob tool, the hermes cron CLI (list, add, edit,
pause, resume, run, remove), or the /cron slash command.
- Schedules: duration (
"30m", "2h"), "every" phrase
( "every monday 9am"), 5-field cron ( "0 9 *"), or ISO timestamp.
- Per-job knobs:
skills, model/provider override, script
(pre-run data collection; no_agent=True makes the script the whole
job), context_from (chain job A's output into job B), workdir
(run in a specific dir with its AGENTS.md / CLAUDE.md loaded),
multi-platform delivery.
- Invariants: 3-minute hard interrupt per run,
.tick.lock file
prevents duplicate ticks across processes, cron sessions pass
skip_memory=True by default, and cron deliveries are framed with a
header/footer instead of being mirrored into the target gateway
session (keeps role alternation intact).
User docs: https://hermes-agent.nousresearch.com/docs/user-guide/features/cron
Curator (skill lifecycle)
Background maintenance for agent-created skills. Tracks usage, marks
idle skills stale, archives stale ones, keeps a pre-run tar.gz backup
so nothing is lost.
- CLI:
hermes curator <verb> โ status, run, pause, resume,
pin, unpin, archive, restore, prune, backup, rollback.
- Slash:
/curator <subcommand> mirrors the CLI.
- Scope: only touches skills with
created_by: "agent" provenance.
Bundled + hub-installed skills are off-limits. Never deletes โ
max destructive action is archive. Pinned skills are exempt from
every auto-transition and every LLM review pass.
- Telemetry: sidecar at
~/.hermes/skills/.usage.json holds
per-skill use_count, view_count, patch_count,
last_activity_at, state, pinned.
Config: curator.* (enabled, interval_hours, min_idle_hours,
stale_after_days, archive_after_days, backup.*).
User docs: https://hermes-agent.nousresearch.com/docs/user-guide/features/curator
Dreaming (periodic memory/skill consolidation)
For Anthropic-style "dreaming" workflows, combine cron + session_search + memory + skills + curator into a scheduled review loop. Start with a weekly, proposal-only report that audits recent sessions, repeated user corrections, memory conflicts, skill patch candidates, and cron/automation improvements. Do not automatically delete/replace memory or patch/archive skills unless the user explicitly approves the proposed changes. See references/weekly-dreaming-routine.md for the recommended prompt, report format, safety policy, and cron creation pattern.
Kanban (multi-agent work queue)
Durable SQLite board for multi-profile / multi-worker collaboration.
Users drive it via hermes kanban <verb>; dispatcher-spawned workers
see a focused kanban_* toolset gated by HERMES_KANBAN_TASK so the
schema footprint is zero outside worker processes.
- CLI verbs (common):
init, create, list (alias ls),
show, assign, link, unlink, comment, complete, block,
unblock, archive, tail. Less common: watch, stats, runs,
log, dispatch, daemon, gc.
- Worker toolset:
kanban_show, kanban_complete, kanban_block,
kanban_heartbeat, kanban_comment, kanban_create, kanban_link.
- Dispatcher runs inside the gateway by default
( kanban.dispatch_in_gateway: true) โ reclaims stale claims,
promotes ready tasks, atomically claims, spawns assigned profiles.
Auto-blocks a task after ~5 consecutive spawn failures.
- Isolation: board is the hard boundary (workers get
HERMES_KANBAN_BOARD pinned in env); tenant is a soft namespace
within a board for workspace-path + memory-key isolation.
User docs: https://hermes-agent.nousresearch.com/docs/user-guide/features/kanban
Log Relay (Hermes โ Discord)
A background Python script that tails ~/.hermes/logs/*.log and batches lines to a Discord channel. Includes session-ID extraction, rate-limit handling, and auto-restart via launchd/systemd. Useful for remote monitoring and audit trails.
- Reference:
references/discord-log-relay.md โ full setup, tuning, macOS/Linux service install, pitfalls.
- Template:
templates/discord-log-relay.py โ copy, set CHANNEL_ID, and deploy.
- Discord operations:
references/discord-operating-planes.md โ channel-purpose routing, periodic-summary vs Dreaming report formats, and safety/cost notes for Discord-first Hermes deployments.
Key pitfall: ask the user about batch frequency upfront rather than defaulting to real-time streaming. Most users prefer 10-minute or hourly batches. High-volume raw logs should be batched, summarized, or stored out-of-band; avoid Discord message storms during error loops.
Weekly Dreaming / Memory Curation
For long-running Hermes deployments, users may want an Anthropic-style "Dreaming" loop: a scheduled review that consolidates experience, proposes memory/skill/cron changes, and identifies what to keep, weaken, archive, or delete. Hermes has the building blocks (sessions, session_search, memory, skills, curator, cron), but the safe default is proposal mode:
1. Inspect recent usage and sessions.
2. Extract repeated success patterns, failure patterns, and user corrections.
3. Propose memory updates/removals without applying them silently.
4. Propose skill patches/archive candidates and cron/reporting improvements.
5. End with explicit approval checkboxes.
Do not silently rewrite or delete memory/skills from a Dreaming report unless the user explicitly authorized automatic application. See references/discord-operating-planes.md for a report template and routing heuristics.
---
Windows-Specific Quirks
Hermes runs natively on Windows (PowerShell, cmd, Windows Terminal, git-bash
mintty, VS Code integrated terminal). Most of it just works, but a handful
of differences between Win32 and POSIX have bitten us โ document new ones
here as you hit them so the next person (or the next session) doesn't
rediscover them from scratch.
Input / Keybindings
Alt+Enter doesn't insert a newline. Windows Terminal intercepts Alt+Enter
at the terminal layer to toggle fullscreen โ the keystroke never reaches
prompt_toolkit. Use Ctrl+Enter instead. Windows Terminal delivers
Ctrl+Enter as LF ( c-j), distinct from plain Enter ( c-m / CR), and the
CLI binds c-j to newline insertion on win32 only (see
_bind_prompt_submit_keys + the Windows-only c-j binding in cli.py).
Side effect: the raw Ctrl+J keystroke also inserts a newline on Windows โ
unavoidable, because Windows Terminal collapses Ctrl+Enter and Ctrl+J to
the same keycode at the Win32 console API layer. No conflicting binding
existed for Ctrl+J on Windows, so this is a harmless side effect.
mintty / git-bash behaves the same (fullscreen on Alt+Enter) unless you
disable Alt+Fn shortcuts in Options โ Keys. Easier to just use Ctrl+Enter.
Diagnosing keybindings. Run python scripts/keystroke_diagnostic.py
(repo root) to see exactly how prompt_toolkit identifies each keystroke
in the current terminal. Answers questions like "does Shift+Enter come
through as a distinct key?" (almost never โ most terminals collapse it
to plain Enter) or "what byte sequence is my terminal sending for
Ctrl+Enter?" This is how the Ctrl+Enter = c-j fact was established.
Config / Files
HTTP 400 "No models provided" on first run. config.yaml was saved
with a UTF-8 BOM (common when Windows apps write it). Re-save as UTF-8
without BOM. hermes config edit writes without BOM; manual edits in
Notepad are the usual culprit.
execute_code / Sandbox
WinError 10106 ("The requested service provider could not be loaded
or initialized") from the sandbox child process โ it can't create an
AF_INET socket, so the loopback-TCP RPC fallback fails before
connect(). Root cause is usually not a broken Winsock LSP; it's
Hermes's own env scrubber dropping SYSTEMROOT / WINDIR / COMSPEC
from the child env. Python's socket module needs SYSTEMROOT to locate
mswsock.dll. Fixed via the _WINDOWS_ESSENTIAL_ENV_VARS allowlist in
tools/code_execution_tool.py. If you still hit it, echo os.environ
inside an execute_code block to confirm SYSTEMROOT is set. Full
diagnostic recipe in references/execute-code-sandbox-env-windows.md.
Testing / Contributing
scripts/run_tests.sh doesn't work as-is on Windows โ it looks for
POSIX venv layouts ( .venv/bin/activate). The Hermes-installed venv at
venv/Scripts/ has no pip or pytest either (stripped for install size).
Workaround: install pytest + pytest-xdist + pyyaml into a system Python
3.11 user site, then invoke pytest directly with PYTHONPATH set:
"/c/Program Files/Python311/python" -m pip install --user pytest pytest-xdist pyyaml
export PYTHONPATH="$(pwd)"
"/c/Program Files/Python311/python" -m pytest tests/foo/test_bar.py -v --tb=short -n 0
Use -n 0, not -n 4 โ pyproject.toml's default addopts already
includes -n, and the wrapper's CI-parity guarantees don't apply off POSIX.
POSIX-only tests need skip guards. Common markers already in the codebase:
- Symlinks โ elevated privileges on Windows
0o600 file modes โ POSIX mode bits not enforced on NTFS by default
signal.SIGALRM โ Unix-only (see tests/conftest.py::_enforce_test_timeout)
- Winsock / Windows-specific regressions โ
@pytest.mark.skipif(sys.platform != "win32", ...)
Use the existing skip-pattern style (sys.platform == "win32" or
sys.platform.startswith("win")) to stay consistent with the rest of the
suite.
Path / Filesystem
Line endings. Git may warn LF will be replaced by CRLF the next time
Git touches it. Cosmetic โ the repo's .gitattributes normalizes. Don't
let editors auto-convert committed POSIX-newline files to CRLF.
Forward slashes work almost everywhere. C:/Users/... is accepted by
every Hermes tool and most Windows APIs. Prefer forward slashes in code
and logs โ avoids shell-escaping backslashes in bash.
---
Troubleshooting
Voice not working
1. Check stt.enabled: true in config.yaml
2. Verify provider: pip install faster-whisper or set API key
3. In gateway: /restart. In CLI: exit and relaunch.
Tool not available
1. hermes tools โ check if toolset is enabled for your platform
2. Some tools need env vars (check .env)
3. /reset after enabling tools
Model/provider issues
1. hermes doctor โ check config and dependencies
2. hermes auth add <provider> โ re-authenticate OAuth providers (use --type oauth)
3. Check .env has the right API key
4. Copilot 403: gh auth login tokens do NOT work for Copilot API. You must use the Copilot-specific OAuth device code flow via hermes model โ GitHub Copilot.
Changes not taking effect
- Tools/skills:
/reset starts a new session with updated toolset
- Config changes: In gateway:
/restart. In CLI: exit and relaunch.
- Code changes: Restart the CLI or gateway process
Deployed web dashboard shows stale CSS or theme changes
- Browser cache: Add
?v=N cache-busting query strings to CSS/JS/theme links in HTML.
- Service Worker cache: Bump
CACHE_NAME in sw.js to invalidate old shell caches.
- Data freshness: Use
fetch(url, {cache:'no-store'}) for live JSON feeds.
- Auto-detection: Embed
data-build in <html> and compare server build vs loaded build on page load to show a "new version available" banner. See references/static-site-cache-invalidation.md for the full diagnostic recipe and auto-detection pattern.
Dashboard inspector feels too technical
- The default inspector view should contain only plain-language sentences: headline, "what they're doing now", "why it matters", and a silent visual progress bar (no text label).
- Move all technical fields (source IDs, confidence scores, progress labels, status slugs, badges) behind a "Show technical details" toggle.
- If users say "details are hard to understand," the fix is to remove more fields from the default view, not to add explanations. Explanations of technical fields are still technical.
- See
references/progressive-disclosure-human-first.md for the aggressive simplification pattern.
Skills not showing
1. hermes skills list โ verify installed
2. hermes skills config โ check platform enablement
3. Load explicitly: /skill name or hermes -s name
Gateway issues
Check logs first:
grep -i "failed to send\|error" ~/.hermes/logs/gateway.log | tail -20
Common gateway problems:
- Gateway dies on SSH logout: Enable linger:
sudo loginctl enable-linger $USER
- Gateway dies on WSL2 close: WSL2 requires
systemd=true in /etc/wsl.conf for systemd services to work. Without it, gateway falls back to nohup (dies when session closes).
- Gateway crash loop: Reset the failed state:
systemctl --user reset-failed hermes-gateway
- macOS: bot shows offline after idle time: The gateway runs as a user agent (
LimitLoadToSessionType=Aqua), so macOS suspends it when the system sleeps. The platform websocket drops and the bot appears offline until the network returns. Fix: keep the Mac awake (System Settings -> Energy -> Prevent automatic sleeping, or caffeinate -d -i -s -u &). Low Power Mode makes this worse, not better. See references/macos-gateway-sleep-disconnect.md for the full diagnostic recipe.
Platform-specific issues
- Discord bot silent: Must enable Message Content Intent in Bot โ Privileged Gateway Intents. See full Discord setup reference:
references/discord-gateway-setup.md.
- Slack bot only works in DMs: Must subscribe to
message.channels event. Without it, the bot ignores public channels.
- Windows-specific issues (
Alt+Enter newline, WinError 10106, UTF-8 BOM config, test suite, line endings): see the dedicated Windows-Specific Quirks section above.
Auxiliary models not working
If auxiliary tasks (vision, compression, session_search) fail silently, the auto provider can't find a backend. Either set OPENROUTER_API_KEY or GOOGLE_API_KEY, or explicitly configure each auxiliary task's provider:
hermes config set auxiliary.vision.provider <your_provider>
hermes config set auxiliary.vision.model <model_name>
Full system auth provisioning
For a one-shot workflow to maximize available credentials โ installing gh, generating SSH keys, configuring git, enabling all Hermes toolsets, and auditing current auth state โ see references/system-auth-setup.md.
Editing large files with patch
When a file is read with read_file(offset=...) (pagination), the tool warns that the view is partial. If you attempt patch without re-reading the full file first, you will likely hit non-unique match errors or corrupt the file. Fix: always call read_file without offset to load the whole file before patching. For append-only updates (e.g., adding a cycle log entry to state.md), do not use terminal(command="cat >> file << 'EOF'...EOF") โ the terminal tool on macOS/Linux misinterprets heredoc << as backgrounding and fails. Instead, write a short Python script via write_file and execute it with terminal(command="python3 /tmp/script.py"). See references/terminal-heredoc-workaround.md for the full pattern.
Sibling subagent file overwrites
When multiple subagents are running in parallel (e.g. via delegate_task batch mode or kanban worker lanes), a file may be modified by one subagent while another is about to write to it. If you use write_file or patch on a file that was last read before a sibling subagent modified it, your write may silently truncate or revert the sibling's changes. The tool may show a warning like "this file was modified by sibling subagent X but this agent never read it."
Fix:
1. Heed the warning. If the tool reports a sibling modification, re-read the file with read_file before writing.
2. Prefer patch over write_file for partial updates โ patch only changes the matched region and is less likely to wipe unrelated content.
3. If the file is already published/deployed, and the local working copy gets corrupted, recover from the published copy:
cp ~/hermes-web/agent-pets/css/dashboard.css ~/.hermes/autonomous-agent-lab/pixel-pet-ops/web/css/dashboard.css
4. For append-only updates, write a small Python script and execute it rather than using write_file on the whole file.
Prevention: In kanban/multi-agent workflows, assign file-level ownership so only one worker touches each file. If parallel workers must edit the same file, have them write to separate temp files and let the orchestrator merge.
---
Windows-Specific Quirks
| Looking for... | Location |
|----------------|----------|
| Config options | hermes config edit or [Configuration docs](https://hermes-agent.nousresearch.com/docs/user-guide/configuration) |
| Available tools | hermes tools list or [Tools reference](https://hermes-agent.nousresearch.com/docs/reference/tools-reference) |
| Slash commands | /help in session or [Slash commands reference](https://hermes-agent.nousresearch.com/docs/reference/slash-commands) |
| Skills catalog | hermes skills browse or [Skills catalog](https://hermes-agent.nousresearch.com/docs/reference/skills-catalog) |
| Provider setup | hermes model or [Providers guide](https://hermes-agent.nousresearch.com/docs/integrations/providers) |
| Platform setup | hermes gateway setup or [Messaging docs](https://hermes-agent.nousresearch.com/docs/user-guide/messaging/) |
| MCP servers | hermes mcp list or [MCP guide](https://hermes-agent.nousresearch.com/docs/user-guide/features/mcp) |
| Profiles | hermes profile list or [Profiles docs](https://hermes-agent.nousresearch.com/docs/user-guide/profiles) |
| Cron jobs | hermes cron list or [Cron docs](https://hermes-agent.nousresearch.com/docs/user-guide/features/cron) |
| Memory | hermes memory status or [Memory docs](https://hermes-agent.nousresearch.com/docs/user-guide/features/memory) |
| Env variables | hermes config env-path or [Env vars reference](https://hermes-agent.nousresearch.com/docs/reference/environment-variables) |
| CLI commands | hermes --help or [CLI reference](https://hermes-agent.nousresearch.com/docs/reference/cli-commands) |
| Gateway logs | ~/.hermes/logs/gateway.log |
| Session files | ~/.hermes/sessions/ or hermes sessions browse |
| Source code | ~/.hermes/hermes-agent/ |
---
Contributor Quick Reference
For occasional contributors and PR authors. Full developer docs: https://hermes-agent.nousresearch.com/docs/developer-guide/
Project Layout
hermes-agent/
โโโ run_agent.py # AIAgent โ core conversation loop
โโโ model_tools.py # Tool discovery and dispatch
โโโ toolsets.py # Toolset definitions
โโโ cli.py # Interactive CLI (HermesCLI)
โโโ hermes_state.py # SQLite session store
โโโ agent/ # Prompt builder, context compression, memory, model routing, credential pooling, skill dispatch
โโโ hermes_cli/ # CLI subcommands, config, setup, commands
โ โโโ commands.py # Slash command registry (CommandDef)
โ โโโ config.py # DEFAULT_CONFIG, env var definitions
โ โโโ main.py # CLI entry point and argparse
โโโ tools/ # One file per tool
โ โโโ registry.py # Central tool registry
โโโ gateway/ # Messaging gateway
โ โโโ platforms/ # Platform adapters (telegram, discord, etc.)
โโโ cron/ # Job scheduler
โโโ tests/ # ~3000 pytest tests
โโโ website/ # Docusaurus docs site
Config: ~/.hermes/config.yaml (settings), ~/.hermes/.env (API keys).
Adding a Tool (3 files)
1. Create tools/your_tool.py:
import json, os
from tools.registry import registry
def check_requirements() -> bool:
return bool(os.getenv("EXAMPLE_API_KEY"))
def example_tool(param: str, task_id: str = None) -> str:
return json.dumps({"success": True, "data": "..."})
registry.register(
name="example_tool",
toolset="example",
schema={"name": "example_tool", "description": "...", "parameters": {...}},
handler=lambda args, **kw: example_tool(
param=args.get("param", ""), task_id=kw.get("task_id")),
check_fn=check_requirements,
requires_env=["EXAMPLE_API_KEY"],
)
2. Add to toolsets.py โ _HERMES_CORE_TOOLS list.
Auto-discovery: any tools/*.py file with a top-level registry.register() call is imported automatically โ no manual list needed.
All handlers must return JSON strings. Use get_hermes_home() for paths, never hardcode ~/.hermes.
Adding a Slash Command
1. Add CommandDef to COMMAND_REGISTRY in hermes_cli/commands.py
2. Add handler in cli.py โ process_command()
3. (Optional) Add gateway handler in gateway/run.py
All consumers (help text, autocomplete, Telegram menu, Slack mapping) derive from the central registry automatically.
Agent Loop (High Level)
run_conversation():
1. Build system prompt
2. Loop while iterations < max:
a. Call LLM (OpenAI-format messages + tool schemas)
b. If tool_calls โ dispatch each via handle_function_call() โ append results โ continue
c. If text response โ return
3. Context compression triggers automatically near token limit
Testing
python -m pytest tests/ -o 'addopts=' -q # Full suite
python -m pytest tests/tools/ -q # Specific area
- Tests auto-redirect
HERMES_HOME to temp dirs โ never touch real ~/.hermes/
- Run full suite before pushing any change
- Use
-o 'addopts=' to clear any baked-in pytest flags
Windows contributors: scripts/run_tests.sh currently looks for POSIX venvs ( .venv/bin/activate / venv/bin/activate) and will error out on Windows where the layout is venv/Scripts/activate + python.exe. The Hermes-installed venv at venv/Scripts/ also has no pip or pytest โ it's stripped for end-user install size. Workaround: install pytest + pytest-xdist + pyyaml into a system Python 3.11 user site ( /c/Program Files/Python311/python -m pip install --user pytest pytest-xdist pyyaml), then run tests directly:
export PYTHONPATH="$(pwd)"
"/c/Program Files/Python311/python" -m pytest tests/tools/test_foo.py -v --tb=short -n 0
Use -n 0 (not -n 4) because pyproject.toml's default addopts already includes -n, and the wrapper's CI-parity story doesn't apply off-POSIX.
Cross-platform test guards: tests that use POSIX-only syscalls need a skip marker. Common ones already in the codebase:
- Symlink creation โ
@pytest.mark.skipif(sys.platform == "win32", reason="Symlinks require elevated privileges on Windows") (see tests/cron/test_cron_script.py)
- POSIX file modes (0o600, etc.) โ
@pytest.mark.skipif(sys.platform.startswith("win"), reason="POSIX mode bits not enforced on Windows") (see tests/hermes_cli/test_auth_toctou_file_modes.py)
signal.SIGALRM โ Unix-only (see tests/conftest.py::_enforce_test_timeout)
- Live Winsock / Windows-specific regression tests โ
@pytest.mark.skipif(sys.platform != "win32", reason="Windows-specific regression")
Monkeypatching sys.platform is not enough when the code under test also calls platform.system() / platform.release() / platform.mac_ver(). Those functions re-read the real OS independently, so a test that sets sys.platform = "linux" on a Windows runner will still see platform.system() == "Windows" and route through the Windows branch. Patch all three together:
monkeypatch.setattr(sys, "platform", "linux")
monkeypatch.setattr(platform, "system", lambda: "Linux")
monkeypatch.setattr(platform, "release", lambda: "6.8.0-generic")
See tests/agent/test_prompt_builder.py::TestEnvironmentHints for a worked example.
Extending the system prompt's execution-environment block
Factual guidance about the host OS, user home, cwd, terminal backend, and shell (bash vs. PowerShell on Windows) is emitted from agent/prompt_builder.py::build_environment_hints(). This is also where the WSL hint and per-backend probe logic live. The convention:
- Local terminal backend โ emit host info (OS,
$HOME, cwd) + Windows-specific notes (hostname โ username, terminal uses bash not PowerShell).
- Remote terminal backend (anything in
_REMOTE_TERMINAL_BACKENDS: docker, singularity, modal, daytona, ssh, vercel_sandbox, managed_modal) โ suppress host info entirely and describe only the backend. A live uname/whoami/pwd probe runs inside the backend via tools.environments.get_environment(...).execute(...), cached per process in _BACKEND_PROBE_CACHE, with a static fallback if the probe times out.
- Key fact for prompt authoring: when
TERMINAL_ENV != "local", every file tool (read_file, write_file, patch, search_files) runs inside the backend container, not on the host. The system prompt must never describe the host in that case โ the agent can't touch it.
Full design notes, the exact emitted strings, and testing pitfalls:
references/prompt-builder-environment-hints.md.
Refactor-safety pattern (POSIX-equivalence guard): when you extract inline logic into a helper that adds Windows/platform-specific behavior, keep a _legacy_<name> oracle function in the test file that's a verbatim copy of the old code, then parametrize-diff against it. Example: tests/tools/test_code_execution_windows_env.py::TestPosixEquivalence. This locks in the invariant that POSIX behavior is bit-for-bit identical and makes any future drift fail loudly with a clear diff.
Commit Conventions
type: concise subject line
Optional body.
Types: fix:, feat:, refactor:, docs:, chore:
Key Rules
- Never break prompt caching โ don't change context, tools, or system prompt mid-conversation
- Message role alternation โ never two assistant or two user messages in a row
- Use
get_hermes_home() from hermes_constants for all paths (profile-safe)
- Config values go in
config.yaml, secrets go in .env
- New tools need a
check_fn so they only appear when requirements are met
[IMPORTANT: The user has invoked the "kanban-orchestrator" skill, indicating they want you to follow its instructions. The full skill content is loaded below.]
---
name: kanban-orchestrator
description: Decomposition playbook + anti-temptation rules for an orchestrator profile routing work through Kanban. The "don't do the work yourself" rule and the basic lifecycle are auto-injected into every kanban worker's system prompt; this skill is the deeper playbook when you're specifically playing the orchestrator role.
version: 3.0.0
platforms: [linux, macos, windows]
metadata:
hermes:
tags: [kanban, multi-agent, orchestration, routing]
related_skills: [kanban-worker]
---
Kanban Orchestrator โ Decomposition Playbook
> The core worker lifecycle (including the kanban_create fan-out pattern and the "decompose, don't execute" rule) is auto-injected into every kanban process via the KANBAN_GUIDANCE system-prompt block. This skill is the deeper playbook when you're an orchestrator profile whose whole job is routing.
Profiles are user-configured โ not a fixed roster
Hermes setups vary widely. Some users run a single profile that does everything; some run a small fleet (docker-worker, cron-worker); some run a curated specialist team they've named themselves. There is no default specialist roster โ the orchestrator skill does not know what profiles exist on this machine.
Before fanning out, you must ground the decomposition in the profiles that actually exist. The dispatcher silently fails to spawn unknown assignee names โ it doesn't autocorrect, doesn't suggest, doesn't fall back. So a card assigned to researcher on a setup that only has docker-worker just sits in ready forever.
Step 0: discover available profiles before planning.
Use one of these:
hermes profile list โ prints the table of profiles configured on this machine. Run it through your terminal tool if you have one; otherwise ask the user.
kanban_list(assignee="<some-name>") โ sanity-check a single name. Returns an empty list (rather than an error) for an unknown assignee, so this only confirms a name you're already considering.
- Just ask the user. "What profiles do you have set up?" is a fine first turn when the goal needs more than one specialist.
Cache the result in your working memory for the rest of the conversation. Re-asking every turn wastes a tool call.
When to use the board (vs. just doing the work)
Create Kanban tasks when any of these are true:
1. Multiple specialists are needed. Research + analysis + writing is three profiles.
2. The work should survive a crash or restart. Long-running, recurring, or important.
3. The user might want to interject. Human-in-the-loop at any step.
4. Multiple subtasks can run in parallel. Fan-out for speed.
5. Review / iteration is expected. A reviewer profile loops on drafter output.
6. The audit trail matters. Board rows persist in SQLite forever.
If none of those apply โ it's a small one-shot reasoning task โ use delegate_task instead or answer the user directly.
The anti-temptation rules
Your job description says "route, don't execute." The rules that enforce that:
- Do not execute the work yourself. Your restricted toolset usually doesn't even include terminal/file/code/web for implementation. If you find yourself "just fixing this quickly" โ stop and create a task for the right specialist.
- For any concrete task, create a Kanban task and assign it. Every single time.
- Split multi-lane requests before creating cards. A user prompt can contain several independent workstreams. Extract those lanes first, then create one card per lane instead of bundling unrelated work into a single implementer card.
- Run independent lanes in parallel. If two cards do not need each other's output, leave them unlinked so the dispatcher can fan them out. Link only true data dependencies.
- If no specialist fits the available profiles, ask the user which profile to create or which existing profile to use. Do not invent profile names; the dispatcher will silently drop unknown assignees.
- Decompose, route, and summarize โ that's the whole job.
Exception: micro-UI polish cycles
There is one narrow exception where the orchestrator may execute directly instead of creating Kanban cards: tiny UI-only polish cycles (e.g., adding a CSS class, a theme preview dot, a hover state, a cross-link, or a HUD button) that are purely presentational, require no cross-file logic changes, and fit comfortably inside a single bounded cycle with no need for review or parallel work. If the change is limited to HTML/CSS/JS cosmetics, no other profile has a stake in it, and the user did not ask for a design review, the orchestrator should just edit and publish rather than paying the kanban-overhead tax. This exception does NOT apply to architecture changes, adapter logic, plugin interfaces, or anything that touches the data layer.
Decomposition playbook
Step 1 โ Understand the goal
Ask clarifying questions if the goal is ambiguous. Cheap to ask; expensive to spawn the wrong fleet.
Step 2 โ Sketch the task graph
Before creating anything, draft the graph out loud (in your response to the user). Treat every concrete workstream as a candidate card:
1. Extract the lanes from the request.
2. Map each lane to one of the profiles you discovered in Step 0. If a lane doesn't fit any existing profile, ask the user which to use or create.
3. Decide whether each lane is independent or gated by another lane.
4. Create independent lanes as parallel cards with no parent links.
5. Create synthesis/review/integration cards with parent links to the lanes they depend on.
Examples of prompts that should fan out (using placeholder profile names โ substitute whatever exists on the user's setup):
- "Build an app" โ one card to a design-oriented profile for product/UI direction, one or two cards to engineering profiles for implementation, plus a later integration/review card if the user has a reviewer profile.
- "Fix blockers and check model variants" โ one implementation card for the blocker fixes plus one discovery/research card for config/source verification. A final reviewer card can depend on both.
- "Research docs and implement" โ a docs-research card can run in parallel with a codebase-discovery card; implementation waits only if it truly needs those findings.
- "Analyze this screenshot and find the related code" โ one card to a vision-capable profile for the visual analysis while another searches the codebase.
Words like "also," "finally," or "and" do not automatically imply a dependency. They often mean "make sure this is covered before reporting back." Only link tasks when one card cannot start until another card's output exists.
Show the graph to the user before creating cards. Let them correct it โ including which actual profile name should own each lane.
Step 3 โ Create tasks and link
Use the profile names from Step 0. The example below uses placeholders <profile-A>, <profile-B>, <profile-C> โ replace them with what the user actually has.
t1 = kanban_create(
title="research: Postgres cost vs current",
assignee="<profile-A>", # whichever profile handles research on this setup
body="Compare estimated infrastructure costs, migration costs, and ongoing ops costs over a 3-year window. Sources: AWS/GCP pricing, team time estimates, current Postgres bills from peers.",
tenant=os.environ.get("HERMES_TENANT"),
)["task_id"]
t2 = kanban_create(
title="research: Postgres performance vs current",
assignee="<profile-A>", # same profile, run in parallel
body="Compare query latency, throughput, and scaling characteristics at our expected data volume (~500GB, 10k QPS peak). Sources: benchmark papers, public case studies, pgbench results if easy.",
)["task_id"]
t3 = kanban_create(
title="synthesize migration recommendation",
assignee="<profile-B>", # whichever profile does synthesis/analysis
body="Read the findings from T1 (cost) and T2 (performance). Produce a 1-page recommendation with explicit trade-offs and a go/no-go call.",
parents=[t1, t2],
)["task_id"]
t4 = kanban_create(
title="draft decision memo",
assignee="<profile-C>", # whichever profile drafts user-facing prose
body="Turn the analyst's recommendation into a 2-page memo for the CTO. Match the tone of previous decision memos in the team's knowledge base.",
parents=[t3],
)["task_id"]
parents=[...] gates promotion โ children stay in todo until every parent reaches done, then auto-promote to ready. No manual coordination needed; the dispatcher and dependency engine handle it.
Step 4 โ Complete your own task
If you were spawned as a task yourself (e.g. a planner profile was assigned T0: "investigate Postgres migration"), mark it done with a summary of what you created:
kanban_complete(
summary="decomposed into T1-T4: 2 research lanes in parallel, 1 synthesis on their outputs, 1 prose draft on the recommendation",
metadata={
"task_graph": {
"T1": {"assignee": "<profile-A>", "parents": []},
"T2": {"assignee": "<profile-A>", "parents": []},
"T3": {"assignee": "<profile-B>", "parents": ["T1", "T2"]},
"T4": {"assignee": "<profile-C>", "parents": ["T3"]},
},
},
)
Step 5 โ Report back to the user
Tell them what you created in plain prose, naming the actual profiles you used:
> I've queued 4 tasks:
> - T1 (<profile-A>): cost comparison
> - T2 (<profile-A>): performance comparison, in parallel with T1
> - T3 (<profile-B>): synthesizes T1 + T2 into a recommendation
> - T4 (<profile-C>): turns T3 into a CTO memo
>
> The dispatcher will pick up T1 and T2 now. T3 starts when both finish. You'll get a gateway ping when T4 completes. Use the dashboard or hermes kanban tail <id> to follow along.
Common patterns
Fan-out + fan-in (research โ synthesize): N research-style cards with no parents, one synthesis card with all of them as parents.
Parallel implementation + validation: one implementer card makes the change while one explorer/researcher card verifies config, docs, or source mapping. A reviewer card can depend on both. Do not make the implementer own unrelated verification just because the user mentioned both in one sentence.
Pipeline with gates: planner โ implementer โ reviewer. Each stage's parents=[previous_task]. Reviewer blocks or completes; if reviewer blocks, the operator unblocks with feedback and respawns.
Same-profile queue: N tasks, all assigned to the same profile, no dependencies between them. Dispatcher serializes โ that profile processes them in priority order, accumulating experience in its own memory.
Parallel UI/frontend lanes: When the goal touches multiple independent HTML/CSS/JS files (e.g., a dashboard page and a 2D gather view), fan out to separate subagents per file. Each lane edits its own file, then the orchestrator integrates, fixes cross-file references (theme paths, shared JSON endpoints), and publishes. This avoids merge conflicts in single-file HTML dashboards and keeps each subagent's context focused. See references/parallel-ui-lanes-and-publishing.md for the post-subagent integration checklist and rsync safety notes.
Human-in-the-loop: Any task can kanban_block() to wait for input. Dispatcher respawns after /unblock. The comment thread carries the full context.
Pitfalls
Inventing profile names that don't exist. The dispatcher silently fails to spawn unknown assignees โ the card just sits in ready forever. Always assign to a profile from your Step 0 discovery; ask the user if you're unsure.
Bundling independent lanes into one card. If the user asks for two independent outcomes, create two cards. Example: "fix blockers and check model variants" is not one fixer task; create a fixer/engineer card for the fixes and an explorer/researcher card for the variant check, then optionally gate review on both.
Over-linking because of wording. "Finally check X" may still be parallel with implementation if X is static config, docs, or source discovery. Link it after implementation only when the check depends on the implementation result.
Forgetting dependency links. If the task graph says research -> implement -> review, do not create all tasks as independent ready cards. Use parent links so implement/review cannot run before their inputs exist.
Reassignment vs. new task. If a reviewer blocks with "needs changes," create a NEW task linked from the reviewer's task โ don't re-run the same task with a stern look. The new task is assigned to the original implementer profile.
Argument order for links. kanban_link(parent_id=..., child_id=...) โ parent first. Mixing them up demotes the wrong task to todo.
Ignoring explicit user feedback to keep building infrastructure. When the user says a specific UX issue (legibility, theme switching, movement density) is "immediate priority," treat it as P0 and route it before deeper packaging/architecture work. Infrastructure polish feels productive, but shipping user-visible fixes is what matters. Create cards for the UX feedback first, then resume infrastructure lanes.
Treating status: complete as immutable when user feedback says otherwise. A state.md that says status: complete does not override a user's report that a completion criterion is actually broken. If the user says "theme switching is not working" and the Final Completion Condition requires "working UI theme switcher," the mission is not complete. Reactivate immediately: set status: active, append a reactivation cycle log, and fix the issue. Do not burn cycles on post-complete verification while the user is reporting active defects.
Don't pre-create the whole graph if the shape depends on intermediate findings. If T3's structure depends on what T1 and T2 find, let T3 exist as a "synthesize findings" task whose own first step is to read parent handoffs and plan the rest. Orchestrators can spawn orchestrators.
Tenant inheritance. If HERMES_TENANT is set in your env, pass tenant=os.environ.get("HERMES_TENANT") on every kanban_create call so child tasks stay in the same namespace.
Verifying cross-file references after directory reorganization. When subagents edit HTML/CSS/JS files and the directory structure shifts (e.g., moving files from root into web/dashboard/ and web/gather/), relative asset paths ( themes/default/theme.css, ./ops-data.json) often break. After subagents finish, the orchestrator must grep for href= and src= in moved files and fix relative paths before publishing. Subagents don't know the final publish layout โ the orchestrator does.
Destructive sync wipes needed files. Commands like rsync -av --delete will delete destination files that aren't in the source list. If you publish a directory tree piecemeal (e.g., copy web/dashboard/ first, then web/gather/ separately), --delete on the first rsync will erase the gather files before the second rsync runs. Either list all source paths in a single rsync invocation, or omit --delete and use cp -r / rsync -av without deletion when doing staged copies.
Recovering stuck workers
When a worker profile keeps crashing, hallucinating, or getting blocked by its own mistakes (usually: wrong model, missing skill, broken credential), the kanban dashboard flags the task with a โ badge and opens a Recovery section in the drawer. Three primary actions:
1. Reclaim (or hermes kanban reclaim <task_id>) โ abort the running worker immediately and reset the task to ready. The existing claim TTL is ~15 min; this is the fast path out.
2. Reassign (or hermes kanban reassign <task_id> <new-profile> --reclaim) โ switch the task to a different profile (one that exists on this setup) and let the dispatcher pick it up with a fresh worker.
3. Change profile model โ the dashboard prints a copy-paste hint for hermes -p <profile> model since profile config lives on disk; edit it in a terminal, then Reclaim to retry with the new model.
Hallucination warnings appear on tasks where a worker's kanban_complete(created_cards=[...]) claim included card ids that don't exist or weren't created by the worker's profile (the gate blocks the completion), or where the free-form summary references t_<hex> ids that don't resolve (advisory prose scan, non-blocking). Both produce audit events that persist even after recovery actions โ the trail stays for debugging.
The user has provided the following instruction alongside the skill invocation: [IMPORTANT: You are running as a scheduled cron job. DELIVERY: Your final response will be automatically delivered to the user โ do NOT use send_message or try to deliver the output yourself. Just produce your report/output as your final response and the system handles the rest. SILENT: If there is genuinely nothing new to report, respond with exactly "[SILENT]" (nothing else) to suppress delivery. Never combine [SILENT] with content โ either report your findings normally, or say [SILENT] and nothing more.]
You are the 15-minute Orchestrator for Son's Autonomous Agent Lab v1, reporting to Discord channel ID 1505805763824586952.
Durable state path: /Users/jooho-hermes/.hermes/autonomous-agent-lab/state.md
Working directory for experiment artifacts: /Users/jooho-hermes/.hermes/autonomous-agent-lab/
Preferred published web root: /Users/jooho-hermes/hermes-web/agent-pets/
Top-level directive from Son:
- The project has evolved from a personal dashboard into an INSTALLABLE PRODUCT that external Hermes users can deploy.
- The final target is a self-contained, configurable, publishable solution: "Hermes Pixel Pet Ops Office".
- Do NOT shrink the mission into a small static MVP and autonomously stop.
- The Gather.town-style 2D spatial office is a first-class feature, not a side page.
Latest UX feedback from Son (treat as immediate priority before deeper packaging work):
- Details are hard for a human to understand. Add human-first summaries, plain-language labels, and progressive disclosure: summary first, technical details second.
- Gather Town version has too many agents roaming around. Reduce default movement, add density/speed controls, cluster agents by room/task, and add focus/calm mode.
- Theme switching is not visibly working. Implement real UI theme switcher with persistence and clear visual theme changes.
Key product requirements (installable solution level):
1. Config-driven architecture: all paths, URLs, colors, names, room layouts via config.yaml. No hardcoded references to jooho-hermes.
2. Self-contained package: clear directory structure (src/, web/, config/, docs/, scripts/), install script, requirements.txt.
3. Pluggable data adapter: support multiple backends via plugin architecture.
4. Themeable frontend: CSS variables driven from config, swappable themes, plus a working UI theme switcher.
5. Multi-tenant ready: works for any Hermes instance.
6. Build/Deploy ready: Dockerfile or docker-compose, or clear static-server setup.
7. Documentation: README, architecture docs, configuration reference, contributor guide.
8. Human-comprehensible UX: plain-language summaries and progressive disclosure for technical detail.
9. Gather.town calm mode: adjustable movement density/speed and less chaotic defaults.
10. Versioned releases: CHANGELOG.md, semantic versioning, release packaging.
Mission model:
- Read state.md first before doing anything else.
- If state.md says
status: inactive or has no Current Mission, do not invent work. Return exactly: ๐ก Autonomous Agent Lab ๋๊ธฐ์ค โ Son์ด ํธ๋ฆฌ๊ฑฐ/๋ฏธ์
์ ์ฃผ๋ฉด 15๋ถ ์ฌ์ดํด์ ์์ํฉ๋๋ค.
- If state.md says
status: active, run one bounded 15-minute cycle toward the full installable solution.
- If state.md says
status: complete, verify that the Final Completion Condition in state.md is truly met. If it is not fully met, reactivate or report that state needs correction.
Cycle procedure when active:
1. Read state.md first. Extract current mission, constraints, previous cycle log, and Final Completion Condition.
2. Decide the next smallest useful step toward installable solution quality. Focus on: architecture, configurability, documentation, and clean separation of concerns.
3. Use delegate_task for independent subagent lanes when helpful.
4. Prefer concrete progress: refactor to config-driven, add install scripts, create docs, add Docker support, theme system, plugin architecture.
5. Update state.md with a new cycle log entry before final reporting.
6. Completion rule: only set status: complete when every item under state.md Final Completion Condition is satisfied. A non-installable MVP is not complete.
7. Stop/block only if Son explicitly stops/redirects, a safety boundary is reached, or a hard blocker needs Son's decision.
Link requirement (never forget):
- Every cycle report MUST include at least one direct viewable link to the published dashboard/artifact.
- The canonical URL:
http://hermes-mac-mini.tail46b3c6.ts.net:8099/agent-pets/
- Include gather town URL too:
http://hermes-mac-mini.tail46b3c6.ts.net:8099/agent-pets/gather/
Final Discord message format:
[Autonomous Agent Lab v1 / Cycle N]
๋ชฉํ:
์ํ:
๊ฒฐ๊ณผ:
๊ฒ์ฆ:
๋ค์:
์ํ:
Safety/quality rules:
- Do not handle secrets, passwords, API keys, payment, permission dialogs, or destructive commands.
- Do not claim completion without updating state.md.
- Do not rely on Discord history as durable state.
- Do not spam raw logs; summarize lane outputs and verification.
- Keep working in /Users/jooho-hermes/.hermes/autonomous-agent-lab/ and publish only to /Users/jooho-hermes/hermes-web/agent-pets/ unless the state file says otherwise.
Design/UX priorities:
- Mobile responsiveness is first-class.
- Character animation/movement is desired.
- Every cycle report must include published links.
- This is now a product engineering mission. Architecture, configurability, and documentation matter as much as visuals.
Response
[Autonomous Agent Lab v1 / Cycle 66]
๋ชฉํ: ๋ฆด๋ฆฌ์ค ํจํค์ง๋ฅผ ์ต์ b65 ์์ค์ ๋๊ธฐํํ๊ณ , ์ 3์ ์ค์น ์๋ฎฌ๋ ์ด์
์ ์ํํ๋ฉฐ, ์ ์ฒด ์๋ํ ํ
์คํธยท๊ฒ์ฆ์ ์คํํด ์ค์นํ ์ ํ์ ๊ฑด์ ์ฑ์ ํ์ธํ๋ค.
์ํ:
1. scripts/package-release.sh ์คํ โ releases/hermes-pixel-pet-ops-v1.4.4.tar.gz / .zip ์ฌ์์ฑ
2. ๋ฆด๋ฆฌ์ค ํจํค์ง ๋ด๋ถ ๋น๋ ๋ฐฐ์ง๊ฐ v1.4.4 ยท b65์ด๊ณ data-build="65"์ธ์ง ํ์ธ
3. ๋ฆด๋ฆฌ์ค ํจํค์ง์ ํ๋์ฝ๋ฉ๋ jooho-hermes ์ฐธ์กฐ๊ฐ 0๊ฐ์ธ์ง ๊ฒ์ฆ
4. ์์ ๋๋ ํ ๋ฆฌ์ ๋ฆด๋ฆฌ์ค ํจํค์ง๋ฅผ ์ถ์ถํ ๋ค scripts/install.sh ์คํ โ ์ค์น ์ฑ๊ณต
5. ์์ ๋๋ ํ ๋ฆฌ์์ ์ด๋ํฐ ์คํ โ 32 agents, 15 cron jobs, 20 sessions, 16 events ์ ์ ์ถ๋ ฅ
6. ํตํฉ ํ
์คํธ 126๊ฐ ์ ๋ถ ํต๊ณผ, ์ค์ ๊ฒ์ฆ 21๊ฐ ์ ๋ถ ํต๊ณผ
7. scripts/publish.sh ์คํ โ ์ ์ ์์ฐ ์ฌ๋ฐฐํฌ ์๋ฃ
8. ops-data.json, health.json mtime 60์ด ์ด๋ด ์ ์ ํจ ํ์ธ
๊ฒฐ๊ณผ:
- ๋ฆด๋ฆฌ์ค ํจํค์ง๊ฐ ์ต์ b65 ์์ค์ ์์ ํ ๋๊ธฐํ๋จ
- ์ 3์๊ฐ
tar -xzf โ bash scripts/install.sh โ python3 -m src.adapter.generate_ops_data ์์๋ก ์ค์นยท์คํ ๊ฐ๋ฅํจ์ ์
์ฆ
- ๋ชจ๋ ์๋ํ ํ
์คํธ ๋ฐ ๊ฒ์ฆ ํต๊ณผ
- ๋ฐฐํฌ ํ์ดํ๋ผ์ธ(60์ด LaunchAgent) ์ ์ ๊ฐ๋ ์ค
๊ฒ์ฆ:
- ํตํฉ ํ
์คํธ: 126/126 passed, 0 failed
- ์ค์ ๊ฒ์ฆ: 21/21 passed, 0 warned, 0 critical
- ํ๋์ฝ๋ฉ ์ฐธ์กฐ: 0๊ฐ (์์ค ๋ฐ ๋ฆด๋ฆฌ์ค ํจํค์ง)
- ์ด๋ํฐ ์ถ๋ ฅ: schema 1.4, 32 agents, 15 cron jobs, 20 sessions, 16 events
- published
ops-data.json / health.json mtime: < 60s
refresh.err.log: ๋น์ด ์์
- source โ published diff: 100% ์ผ์น
๋ค์:
- Son์ด ๋์๋ณด๋๋ฅผ ๋ฐฉ๋ฌธํ์ฌ ์๋จ ์
๋ฐ์ดํธ ๋ฐฐ๋๊ฐ ๋จ๋ฉด "ํ์ธ ํ ์๋ก๊ณ ์นจ" ํด๋ฆญ
- ๋ฐฐ์ง๊ฐ
v1.4.4 ยท b65๋ก ํ์๋๋์ง ํ์ธ
- ํ
๋ง ์ ํ(ํ์ด๋ก ํจ๋), Gather calm mode(5 agents, ๊ธฐ๋ณธ ํ์ฑ), inspector human-first view ์ง์ ํ
์คํธ
- ์ธ ๊ฐ์ง ๋ชจ๋ ๋ง์กฑํ๋ฉด
status: complete๋ก ๋ณ๊ฒฝ ๊ฐ๋ฅ
์ํ: active โ Son์ ๋ธ๋ผ์ฐ์ ์ฌ์ด๋ UX ํ์ธ ๋๊ธฐ ์ค
๐ ๋์๋ณด๋: http://hermes-mac-mini.tail46b3c6.ts.net:8099/agent-pets/
๐ Gather Town: http://hermes-mac-mini.tail46b3c6.ts.net:8099/agent-pets/gather/
|
| 2026-05-19 18-58-50 |
82,408 chars |
2026-05-19_18-58-50.md |
Cron Job: autonomous-agent-lab-v1-orchestrator
Job ID: 35127ff89556
Run Time: 2026-05-19 18:58:50
Schedule: every 15m
Prompt
[IMPORTANT: The user has invoked the "hermes-agent" skill, indicating they want you to follow its instructions. The full skill content is loaded below.]
---
name: hermes-agent
description: "Configure, extend, or contribute to Hermes Agent."
version: 2.1.0
author: Hermes Agent + Teknium
license: MIT
platforms: [linux, macos, windows]
metadata:
hermes:
tags: [hermes, setup, configuration, multi-agent, spawning, cli, gateway, development]
homepage: https://github.com/NousResearch/hermes-agent
related_skills: [claude-code, codex, opencode]
---
Hermes Agent
Hermes Agent is an open-source AI agent framework by Nous Research that runs in your terminal, messaging platforms, and IDEs. It belongs to the same category as Claude Code (Anthropic), Codex (OpenAI), and OpenClaw โ autonomous coding and task-execution agents that use tool calling to interact with your system. Hermes works with any LLM provider (OpenRouter, Anthropic, OpenAI, DeepSeek, local models, and 15+ others) and runs on Linux, macOS, and WSL.
What makes Hermes different:
- Self-improving through skills โ Hermes learns from experience by saving reusable procedures as skills. When it solves a complex problem, discovers a workflow, or gets corrected, it can persist that knowledge as a skill document that loads into future sessions. Skills accumulate over time, making the agent better at your specific tasks and environment.
- Persistent memory across sessions โ remembers who you are, your preferences, environment details, and lessons learned. Pluggable memory backends (built-in, Honcho, Mem0, and more) let you choose how memory works.
- Multi-platform gateway โ the same agent runs on Telegram, Discord, Slack, WhatsApp, Signal, Matrix, Email, and 10+ other platforms with full tool access, not just chat.
- Provider-agnostic โ swap models and providers mid-workflow without changing anything else. Credential pools rotate across multiple API keys automatically.
- Profiles โ run multiple independent Hermes instances with isolated configs, sessions, skills, and memory.
- Extensible โ plugins, MCP servers, custom tools, webhook triggers, cron scheduling, and the full Python ecosystem.
People use Hermes for software development, research, system administration, data analysis, content creation, home automation, and anything else that benefits from an AI agent with persistent context and full system access.
This skill helps you work with Hermes Agent effectively โ setting it up, configuring features, spawning additional agent instances, troubleshooting issues, finding the right commands and settings, and understanding how the system works when you need to extend or contribute to it.
Docs: https://hermes-agent.nousresearch.com/docs/
Quick Start
Install
curl -fsSL https://raw.githubusercontent.com/NousResearch/hermes-agent/main/scripts/install.sh | bash
Interactive chat (default)
hermes
Single query
hermes chat -q "What is the capital of France?"
Setup wizard
hermes setup
Change model/provider
hermes model
Check health
hermes doctor
---
CLI Reference
Global Flags
hermes [flags] [command]
--version, -V Show version
--resume, -r SESSION Resume session by ID or title
--continue, -c [NAME] Resume by name, or most recent session
--worktree, -w Isolated git worktree mode (parallel agents)
--skills, -s SKILL Preload skills (comma-separate or repeat)
--profile, -p NAME Use a named profile
--yolo Skip dangerous command approval
--pass-session-id Include session ID in system prompt
No subcommand defaults to chat.
Chat
hermes chat [flags]
-q, --query TEXT Single query, non-interactive
-m, --model MODEL Model (e.g. anthropic/claude-sonnet-4)
-t, --toolsets LIST Comma-separated toolsets
--provider PROVIDER Force provider (openrouter, anthropic, nous, etc.)
-v, --verbose Verbose output
-Q, --quiet Suppress banner, spinner, tool previews
--checkpoints Enable filesystem checkpoints (/rollback)
--source TAG Session source tag (default: cli)
Configuration
hermes setup [section] Interactive wizard (model|terminal|gateway|tools|agent)
hermes model Interactive model/provider picker
hermes config View current config
hermes config edit Open config.yaml in $EDITOR
hermes config set KEY VAL Set a config value
hermes config path Print config.yaml path
hermes config env-path Print .env path
hermes config check Check for missing/outdated config
hermes config migrate Update config with new options
hermes doctor [--fix] Check dependencies and config
Credential Pools
hermes auth add Interactive credential wizard (oauth, api-key)
hermes auth list [PROVIDER] List pooled credentials
hermes auth remove P INDEX Remove by provider + index
hermes auth reset PROVIDER Clear exhaustion status
hermes logout Clear stored auth
Tools & Skills
hermes tools Interactive tool enable/disable (curses UI)
hermes tools list Show all tools and status
hermes tools enable NAME Enable a toolset
hermes tools disable NAME Disable a toolset
hermes skills list List installed skills
hermes skills search QUERY Search the skills hub
hermes skills install ID Install a skill (ID can be a hub identifier OR a direct https://โฆ/SKILL.md URL; pass --name to override when frontmatter has no name)
hermes skills inspect ID Preview without installing
hermes skills config Enable/disable skills per platform
hermes skills check Check for updates
hermes skills update Update outdated skills
hermes skills uninstall N Remove a hub skill
hermes skills publish PATH Publish to registry
hermes skills browse Browse all available skills
hermes skills tap add REPO Add a GitHub repo as skill source
MCP Servers
hermes mcp serve Run Hermes as an MCP server
hermes mcp add NAME Add an MCP server (--url or --command)
hermes mcp remove NAME Remove an MCP server
hermes mcp list List configured servers
hermes mcp test NAME Test connection
hermes mcp configure NAME Toggle tool selection
Gateway (Messaging Platforms)
hermes gateway run Start gateway foreground
hermes gateway install Install as background service
hermes gateway start/stop Control the service
hermes gateway restart Restart the service
hermes gateway status Check status
hermes gateway setup Configure platforms
Supported platforms: Telegram, Discord, Slack, WhatsApp, Signal, Email, SMS, Matrix, Mattermost, Home Assistant, DingTalk, Feishu, WeCom, BlueBubbles (iMessage), Weixin (WeChat), API Server, Webhooks. Open WebUI connects via the API Server adapter.
Platform docs: https://hermes-agent.nousresearch.com/docs/user-guide/messaging/
Discord-specific walkthrough (token, intents, service install, access control): see references/discord-gateway-setup.md in this skill.
- Per-channel personas and skill bindings: see
references/gateway-channel-personas.md (works on Discord, Slack, Telegram, Mattermost, Matrix).
- For long-running Discord-first operations, purpose-specific channel routing, periodic summaries, weekly Dreaming/audit reports, and log-safety patterns: see
references/discord-operating-planes.md.
- For broad Hermes/LifeOS/SQAF ecosystem audits (cron inventory, live services, dashboards, provider/model warnings, and control-plane gaps), see
references/ecosystem-audit.md.
Sessions
hermes sessions list List recent sessions
hermes sessions browse Interactive picker
hermes sessions export OUT Export to JSONL
hermes sessions rename ID T Rename a session
hermes sessions delete ID Delete a session
hermes sessions prune Clean up old sessions (--older-than N days)
hermes sessions stats Session store statistics
For browser-based viewing of existing Hermes CLI/Discord/cron session transcripts, prefer a lightweight static export from ~/.hermes/state.db into a private web root instead of assuming Open WebUI can browse Hermes' native session store. See references/hermes-session-static-web-viewer.md for the SQLite schema, static HTML export workflow, redaction/truncation cautions, and the user's Mac mini deployment (/hermes-sessions/ under the Tailscale-only ~/hermes-web site).
For cron job execution history, the same static-export pattern applies to ~/.hermes/cron/jobs.json and ~/.hermes/cron/output/{job_id}/*.md. See references/cron-history-web-viewer.md for the cron data model, schedule-dict pitfall, and the user's deployed /cron-history/ dashboard.
Cron Jobs
hermes cron list List jobs (--all for disabled)
hermes cron create SCHED Create: '30m', 'every 2h', '0 9 *'
hermes cron edit ID Edit schedule, prompt, delivery
hermes cron pause/resume ID Control job state
hermes cron run ID Trigger on next tick
hermes cron remove ID Delete a job
hermes cron status Scheduler status
For bounded autonomous lab/orchestrator cron jobs that use file-based state, subagent lanes, artifact publishing, and status transitions (active โ complete/blocked/inactive), see references/autonomous-agent-lab-cron-cycle.md. A reusable verification script template lives at scripts/verify-completion-template.py.
For a worked example of evolving an autonomous lab into a config-driven, themeable, Docker-ready installable product, see references/autonomous-lab-product-architecture.md. For CI, integration testing, pluggable adapter architecture, bounded cycle orchestration, and post-productization patterns, see references/product-maturity-patterns.md.
For the final completion verification checklist โ the explicit audit pattern to run before marking status: complete on an installable-solution mission, see references/autonomous-lab-completion-verification.md.
For the reactivation protocol when a completed lab receives new P0 feedback or the user contradicts a completion claim, see references/autonomous-lab-reactivation-protocol.md.
For the config/CHANGELOG version drift pitfall that occurs when autonomous labs evolve over many cycles, and for the related source vs. published file drift problem where the live web root diverges from the project source, see references/autonomous-lab-version-drift.md.
For adding historical trend tracking (SQLite-backed agent status transitions + vanilla JS SVG sparklines) to an autonomous lab dashboard, see references/history-tracking-sparkline-pattern.md.
For reusable dashboard UX patterns (onboarding tours, data freshness badges, keyboard shortcuts, progressive disclosure inspectors, cross-linking between views), see references/dashboard-ux-patterns.md.
For the aggressive human-first inspector refinement โ when users report that details are hard to understand and the fix is to strip technical labels from the default view โ see references/progressive-disclosure-human-first.md.
For programmatic verification of CSS custom-property theme systems โ catching scoping bugs, confirming theme distinctness, and validating JS switching logic โ see references/theme-system-verification.md.
For Son's Discord-first autonomous experiments where a channel hosts a repeated multi-agent loop, use the Autonomous Discord Agent Lab pattern: create file-based durable state, a paused cron orchestrator delivered to discord:<channel_id>, then activate it from a user mission trigger. See references/autonomous-discord-agent-lab.md.
Webhooks
hermes webhook subscribe N Create route at /webhooks/<name>
hermes webhook list List subscriptions
hermes webhook remove NAME Remove a subscription
hermes webhook test NAME Send a test POST
Profiles
hermes profile list List all profiles
hermes profile create NAME Create (--clone, --clone-all, --clone-from)
hermes profile use NAME Set sticky default
hermes profile delete NAME Delete a profile
hermes profile show NAME Show details
hermes profile alias NAME Manage wrapper scripts
hermes profile rename A B Rename a profile
hermes profile export NAME Export to tar.gz
hermes profile import FILE Import from archive
Credential Pools
hermes auth add Interactive credential wizard
hermes auth list [PROVIDER] List pooled credentials
hermes auth remove P INDEX Remove by provider + index
hermes auth reset PROVIDER Clear exhaustion status
Other
hermes insights [--days N] Usage analytics
hermes update Update to latest version
hermes pairing list/approve/revoke DM authorization
hermes plugins list/install/remove Plugin management
hermes honcho setup/status Honcho memory integration (requires honcho plugin)
hermes memory setup/status/off Memory provider config
hermes completion bash|zsh Shell completions
hermes acp ACP server (IDE integration)
hermes claw migrate Migrate from OpenClaw
hermes uninstall Uninstall Hermes
---
Slash Commands (In-Session)
Type these during an interactive chat session. New commands land fairly
often; if something below looks stale, run /help in-session for the
authoritative list or see the [live slash commands reference](https://hermes-agent.nousresearch.com/docs/reference/slash-commands).
The registry of record is hermes_cli/commands.py โ every consumer
(autocomplete, Telegram menu, Slack mapping, /help) derives from it.
Session Control
/new (/reset) Fresh session
/clear Clear screen + new session (CLI)
/retry Resend last message
/undo Remove last exchange
/title [name] Name the session
/compress Manually compress context
/stop Kill background processes
/rollback [N] Restore filesystem checkpoint
/snapshot [sub] Create or restore state snapshots of Hermes config/state (CLI)
/background <prompt> Run prompt in background
/queue <prompt> Queue for next turn
/steer <prompt> Inject a message after the next tool call without interrupting
/agents (/tasks) Show active agents and running tasks
/resume [name] Resume a named session
/goal [text|sub] Set a standing goal Hermes works on across turns until achieved
(subcommands: status, pause, resume, clear)
/redraw Force a full UI repaint (CLI)
Configuration
/config Show config (CLI)
/model [name] Show or change model
/personality [name] Set personality
/reasoning [level] Set reasoning (none|minimal|low|medium|high|xhigh|show|hide)
/verbose Cycle: off โ new โ all โ verbose
/voice [on|off|tts] Voice mode
/yolo Toggle approval bypass
/busy [sub] Control what Enter does while Hermes is working (CLI)
(subcommands: queue, steer, interrupt, status)
/indicator [style] Pick the TUI busy-indicator style (CLI)
(styles: kaomoji, emoji, unicode, ascii)
/footer [on|off] Toggle gateway runtime-metadata footer on final replies
/skin [name] Change theme (CLI)
/statusbar Toggle status bar (CLI)
Tools & Skills
/tools Manage tools (CLI)
/toolsets List toolsets (CLI)
/skills Search/install skills (CLI)
/skill <name> Load a skill into session
/reload-skills Re-scan ~/.hermes/skills/ for added/removed skills
/reload Reload .env variables into the running session (CLI)
/reload-mcp Reload MCP servers
/cron Manage cron jobs (CLI)
/curator [sub] Background skill maintenance (status, run, pin, archive, โฆ)
/kanban [sub] Multi-profile collaboration board (tasks, links, comments)
/plugins List plugins (CLI)
Gateway
/approve Approve a pending command (gateway)
/deny Deny a pending command (gateway)
/restart Restart gateway (gateway)
/sethome Set current chat as home channel (gateway)
/update Update Hermes to latest (gateway)
/topic [sub] Enable or inspect Telegram DM topic sessions (gateway)
/platforms (/gateway) Show platform connection status (gateway)
Utility
/branch (/fork) Branch the current session
/fast Toggle priority/fast processing
/browser Open CDP browser connection
/history Show conversation history (CLI)
/save Save conversation to file (CLI)
/copy [N] Copy the last assistant response to clipboard (CLI)
/paste Attach clipboard image (CLI)
/image Attach local image file (CLI)
Info
/help Show commands
/commands [page] Browse all commands (gateway)
/usage Token usage
/insights [days] Usage analytics
/gquota Show Google Gemini Code Assist quota usage (CLI)
/status Session info (gateway)
/profile Active profile info
/debug Upload debug report (system info + logs) and get shareable links
Exit
/quit (/exit, /q) Exit CLI
---
Key Paths & Config
~/.hermes/config.yaml Main configuration
~/.hermes/.env API keys and secrets
$HERMES_HOME/skills/ Installed skills
~/.hermes/sessions/ Session transcripts
~/.hermes/logs/ Gateway and error logs
~/.hermes/auth.json OAuth tokens and credential pools
~/.hermes/hermes-agent/ Source code (if git-installed)
Profiles use ~/.hermes/profiles/<name>/ with the same layout.
Config Sections
Edit with hermes config edit or hermes config set section.key value.
| Section | Key options |
|---------|-------------|
| model | default, provider, base_url, api_key, context_length |
| agent | max_turns (90), tool_use_enforcement |
| terminal | backend (local/docker/ssh/modal), cwd, timeout (180) |
| compression | enabled, threshold (0.50), target_ratio (0.20) |
| display | skin, tool_progress, show_reasoning, show_cost |
| stt | enabled, provider (local/groq/openai/mistral) |
| tts | provider (edge/elevenlabs/openai/minimax/mistral/neutts) |
| memory | memory_enabled, user_profile_enabled, provider |
| security | tirith_enabled, website_blocklist |
| delegation | model, provider, base_url, api_key, max_iterations (50), reasoning_effort |
| checkpoints | enabled, max_snapshots (50) |
| fallback_model | provider, model, base_url, key_env |
Fallback Providers
Hermes can automatically fail over to a backup provider:model when the primary is unavailable. This is turn-scoped โ each new user message starts with the primary restored; fallback only activates mid-turn when the primary fails.
Configuration ( ~/.hermes/config.yaml):
fallback_model:
provider: opencode-go
model: kimi-k2.6
Or use the interactive manager:
hermes fallback add # interactive picker
hermes fallback list # show fallback chain
hermes fallback remove # remove by index
Legacy note: fallback_model (singular) is the legacy single-fallback key. fallback_providers (list) supports multiple ordered fallbacks. When both exist, fallback_providers takes priority.
Trigger conditions (after exhausting retries where applicable):
- Rate limits (HTTP 429)
- Server errors (HTTP 500, 502, 503)
- Auth failures (HTTP 401, 403) โ immediately
- Not found (HTTP 404) โ immediately
- Invalid / empty responses repeatedly
Supported providers include all standard providers (OpenRouter, Anthropic, OpenCode Go/ Zen, Kimi, etc.) plus custom endpoints with base_url + key_env. Full provider docs: https://hermes-agent.nousresearch.com/docs/integrations/providers
Limitations:
- Subagent delegation does not inherit fallback config
- Cron jobs do not use fallback (use per-job provider/model overrides)
- Auxiliary tasks (vision, compression, etc.) use their own
auxiliary.* provider chain
For a deep-dive with worked examples and model lists, see references/fallback-providers.md.
Full config reference: https://hermes-agent.nousresearch.com/docs/user-guide/configuration
Providers
20+ providers supported. Set via hermes model or hermes setup.
| Provider | Auth | Key env var |
|----------|------|-------------|
| OpenRouter | API key | OPENROUTER_API_KEY |
| Anthropic | API key | ANTHROPIC_API_KEY |
| Nous Portal | OAuth | hermes auth |
| OpenAI Codex | OAuth | hermes auth |
| GitHub Copilot | Token | COPILOT_GITHUB_TOKEN |
| Google Gemini | API key | GOOGLE_API_KEY or GEMINI_API_KEY |
| DeepSeek | API key | DEEPSEEK_API_KEY |
| xAI / Grok | API key | XAI_API_KEY |
| Hugging Face | Token | HF_TOKEN |
| Z.AI / GLM | API key | GLM_API_KEY |
| MiniMax | API key | MINIMAX_API_KEY |
| MiniMax CN | API key | MINIMAX_CN_API_KEY |
| Kimi / Moonshot | API key | KIMI_API_KEY |
| Alibaba / DashScope | API key | DASHSCOPE_API_KEY |
| Xiaomi MiMo | API key | XIAOMI_API_KEY |
| Kilo Code | API key | KILOCODE_API_KEY |
| AI Gateway (Vercel) | API key | AI_GATEWAY_API_KEY |
| OpenCode Zen | API key | OPENCODE_ZEN_API_KEY |
| OpenCode Go | API key | OPENCODE_GO_API_KEY |
| Qwen OAuth | OAuth | hermes auth add qwen-oauth |
| Custom endpoint | Config | model.base_url + model.api_key in config.yaml |
| GitHub Copilot ACP | External | COPILOT_CLI_PATH or Copilot CLI |
Full provider docs: https://hermes-agent.nousresearch.com/docs/integrations/providers
Toolsets
Enable/disable via hermes tools (interactive) or hermes tools enable/disable NAME.
| Toolset | What it provides |
|---------|-----------------|
| web | Web search and content extraction |
| search | Web search only (subset of web) |
| browser | Browser automation (Browserbase, Camofox, or local Chromium) |
| terminal | Shell commands and process management |
| file | File read/write/search/patch |
| code_execution | Sandboxed Python execution |
| vision | Image analysis |
| image_gen | AI image generation |
| video | Video analysis and generation |
| tts | Text-to-speech |
| skills | Skill browsing and management |
| memory | Persistent cross-session memory |
| session_search | Search past conversations |
| delegation | Subagent task delegation |
| cronjob | Scheduled task management |
| clarify | Ask user clarifying questions |
| messaging | Cross-platform message sending |
| todo | In-session task planning and tracking |
| kanban | Multi-agent work-queue tools (gated to workers) |
| debugging | Extra introspection/debug tools (off by default) |
| safe | Minimal, low-risk toolset for locked-down sessions |
| spotify | Spotify playback and playlist control |
| homeassistant | Smart home control (off by default) |
| discord | Discord integration tools |
| discord_admin | Discord admin/moderation tools |
| feishu_doc | Feishu (Lark) document tools |
| feishu_drive | Feishu (Lark) drive tools |
| yuanbao | Yuanbao integration tools |
| rl | Reinforcement learning tools (off by default) |
| moa | Mixture of Agents (off by default) |
Full enumeration lives in toolsets.py as the TOOLSETS dict; _HERMES_CORE_TOOLS is the default bundle most platforms inherit from.
Tool changes take effect on /reset (new session). They do NOT apply mid-conversation to preserve prompt caching.
---
Security & Privacy Toggles
Common "why is Hermes doing X to my output / tool calls / commands?" toggles โ and the exact commands to change them. Most of these need a fresh session (/reset in chat, or start a new hermes invocation) because they're read once at startup.
Secret redaction in tool output
Secret redaction is off by default โ tool output (terminal stdout, read_file, web content, subagent summaries, etc.) passes through unmodified. If the user wants Hermes to auto-mask strings that look like API keys, tokens, and secrets before they enter the conversation context and logs:
hermes config set security.redact_secrets true # enable globally
Restart required. security.redact_secrets is snapshotted at import time โ toggling it mid-session (e.g. via export HERMES_REDACT_SECRETS=true from a tool call) will NOT take effect for the running process. Tell the user to run hermes config set security.redact_secrets true in a terminal, then start a new session. This is deliberate โ it prevents an LLM from flipping the toggle on itself mid-task.
Disable again with:
hermes config set security.redact_secrets false
PII redaction in gateway messages
Separate from secret redaction. When enabled, the gateway hashes user IDs and strips phone numbers from the session context before it reaches the model:
hermes config set privacy.redact_pii true # enable
hermes config set privacy.redact_pii false # disable (default)
Command approval prompts
By default (approvals.mode: manual), Hermes prompts the user before running shell commands flagged as destructive (rm -rf, git reset --hard, etc.). The modes are:
manual โ always prompt (default)
smart โ use an auxiliary LLM to auto-approve low-risk commands, prompt on high-risk
off โ skip all approval prompts (equivalent to --yolo)
hermes config set approvals.mode smart # recommended middle ground
hermes config set approvals.mode off # bypass everything (not recommended)
Per-invocation bypass without changing config:
hermes --yolo โฆ
export HERMES_YOLO_MODE=1
Note: YOLO / approvals.mode: off does NOT turn off secret redaction. They are independent.
Shell hooks allowlist
Some shell-hook integrations require explicit allowlisting before they fire. Managed via ~/.hermes/shell-hooks-allowlist.json โ prompted interactively the first time a hook wants to run.
Disabling the web/browser/image-gen tools
To keep the model away from network or media tools entirely, open hermes tools and toggle per-platform. Takes effect on next session (/reset). See the Tools & Skills section above.
---
Voice & Transcription
STT (Voice โ Text)
Voice messages from messaging platforms are auto-transcribed.
Provider priority (auto-detected):
1. Local faster-whisper โ free, no API key: pip install faster-whisper
2. Groq Whisper โ free tier: set GROQ_API_KEY
3. OpenAI Whisper โ paid: set VOICE_TOOLS_OPENAI_KEY
4. Mistral Voxtral โ set MISTRAL_API_KEY
Config:
stt:
enabled: true
provider: local # local, groq, openai, mistral
local:
model: base # tiny, base, small, medium, large-v3
TTS (Text โ Voice)
| Provider | Env var | Free? |
|----------|---------|-------|
| Edge TTS | None | Yes (default) |
| ElevenLabs | ELEVENLABS_API_KEY | Free tier |
| OpenAI | VOICE_TOOLS_OPENAI_KEY | Paid |
| MiniMax | MINIMAX_API_KEY | Paid |
| Mistral (Voxtral) | MISTRAL_API_KEY | Paid |
| NeuTTS (local) | None (pip install neutts[all] + espeak-ng) | Free |
Voice commands: /voice on (voice-to-voice), /voice tts (always voice), /voice off.
---
Spawning Additional Hermes Instances
Run additional Hermes processes as fully independent subprocesses โ separate sessions, tools, and environments.
When to Use This vs delegate_task
| | delegate_task | Spawning hermes process |
|-|-----------------|--------------------------|
| Isolation | Separate conversation, shared process | Fully independent process |
| Duration | Minutes (bounded by parent loop) | Hours/days |
| Tool access | Subset of parent's tools | Full tool access |
| Interactive | No | Yes (PTY mode) |
| Use case | Quick parallel subtasks | Long autonomous missions |
One-Shot Mode
terminal(command="hermes chat -q 'Research GRPO papers and write summary to ~/research/grpo.md'", timeout=300)
Background for long tasks:
terminal(command="hermes chat -q 'Set up CI/CD for ~/myapp'", background=true)
Interactive PTY Mode (via tmux)
Hermes uses prompt_toolkit, which requires a real terminal. Use tmux for interactive spawning:
Start
terminal(command="tmux new-session -d -s agent1 -x 120 -y 40 'hermes'", timeout=10)
Wait for startup, then send a message
terminal(command="sleep 8 && tmux send-keys -t agent1 'Build a FastAPI auth service' Enter", timeout=15)
Read output
terminal(command="sleep 20 && tmux capture-pane -t agent1 -p", timeout=5)
Send follow-up
terminal(command="tmux send-keys -t agent1 'Add rate limiting middleware' Enter", timeout=5)
Exit
terminal(command="tmux send-keys -t agent1 '/exit' Enter && sleep 2 && tmux kill-session -t agent1", timeout=10)
Multi-Agent Coordination
Agent A: backend
terminal(command="tmux new-session -d -s backend -x 120 -y 40 'hermes -w'", timeout=10)
terminal(command="sleep 8 && tmux send-keys -t backend 'Build REST API for user management' Enter", timeout=15)
Agent B: frontend
terminal(command="tmux new-session -d -s frontend -x 120 -y 40 'hermes -w'", timeout=10)
terminal(command="sleep 8 && tmux send-keys -t frontend 'Build React dashboard for user management' Enter", timeout=15)
Check progress, relay context between them
terminal(command="tmux capture-pane -t backend -p | tail -30", timeout=5)
terminal(command="tmux send-keys -t frontend 'Here is the API schema from the backend agent: ...' Enter", timeout=5)
Session Resume
Resume most recent session
terminal(command="tmux new-session -d -s resumed 'hermes --continue'", timeout=10)
Resume specific session
terminal(command="tmux new-session -d -s resumed 'hermes --resume 20260225_143052_a1b2c3'", timeout=10)
Tips
- Prefer
delegate_task for quick subtasks โ less overhead than spawning a full process
- Use
-w (worktree mode) when spawning agents that edit code โ prevents git conflicts
- Set timeouts for one-shot mode โ complex tasks can take 5-10 minutes
- Use
hermes chat -q for fire-and-forget โ no PTY needed
- Use tmux for interactive sessions โ raw PTY mode has
\r vs \n issues with prompt_toolkit
- For scheduled tasks, use the
cronjob tool instead of spawning โ handles delivery and retry
---
Durable & Background Systems
Four systems run alongside the main conversation loop. Quick reference
here; full developer notes live in AGENTS.md, user-facing docs under
website/docs/user-guide/features/.
Delegation (delegate_task)
Synchronous subagent spawn โ the parent waits for the child's summary
before continuing its own loop. Isolated context + terminal session.
- Single:
delegate_task(goal, context, toolsets).
- Batch:
delegate_task(tasks=[{goal, ...}, ...]) runs children in
parallel, capped by delegation.max_concurrent_children (default 3).
- Roles:
leaf (default; cannot re-delegate) vs orchestrator
(can spawn its own workers, bounded by delegation.max_spawn_depth).
- Not durable. If the parent is interrupted, the child is
cancelled. For work that must outlive the turn, use cronjob or
terminal(background=True, notify_on_complete=True).
Config: delegation.* in config.yaml.
Tuning max_concurrent_children
Default is 3. Rule of thumb for raising it:
- Light tasks (web search, file grep): up to
6-8
- Medium tasks (code execution, browser):
4-5
- Heavy tasks (builds, large data):
2-3
- Actual bottleneck is usually the API rate limit, not local CPU/RAM. On a 10-core M4 with 16GB RAM, CPU is rarely the constraint.
- Formula: start at
5, raise only if profiling shows idle time between API responses.
Cron (scheduled jobs)
Durable scheduler โ cron/jobs.py + cron/scheduler.py. Drive it via
the cronjob tool, the hermes cron CLI (list, add, edit,
pause, resume, run, remove), or the /cron slash command.
- Schedules: duration (
"30m", "2h"), "every" phrase
( "every monday 9am"), 5-field cron ( "0 9 *"), or ISO timestamp.
- Per-job knobs:
skills, model/provider override, script
(pre-run data collection; no_agent=True makes the script the whole
job), context_from (chain job A's output into job B), workdir
(run in a specific dir with its AGENTS.md / CLAUDE.md loaded),
multi-platform delivery.
- Invariants: 3-minute hard interrupt per run,
.tick.lock file
prevents duplicate ticks across processes, cron sessions pass
skip_memory=True by default, and cron deliveries are framed with a
header/footer instead of being mirrored into the target gateway
session (keeps role alternation intact).
User docs: https://hermes-agent.nousresearch.com/docs/user-guide/features/cron
Curator (skill lifecycle)
Background maintenance for agent-created skills. Tracks usage, marks
idle skills stale, archives stale ones, keeps a pre-run tar.gz backup
so nothing is lost.
- CLI:
hermes curator <verb> โ status, run, pause, resume,
pin, unpin, archive, restore, prune, backup, rollback.
- Slash:
/curator <subcommand> mirrors the CLI.
- Scope: only touches skills with
created_by: "agent" provenance.
Bundled + hub-installed skills are off-limits. Never deletes โ
max destructive action is archive. Pinned skills are exempt from
every auto-transition and every LLM review pass.
- Telemetry: sidecar at
~/.hermes/skills/.usage.json holds
per-skill use_count, view_count, patch_count,
last_activity_at, state, pinned.
Config: curator.* (enabled, interval_hours, min_idle_hours,
stale_after_days, archive_after_days, backup.*).
User docs: https://hermes-agent.nousresearch.com/docs/user-guide/features/curator
Dreaming (periodic memory/skill consolidation)
For Anthropic-style "dreaming" workflows, combine cron + session_search + memory + skills + curator into a scheduled review loop. Start with a weekly, proposal-only report that audits recent sessions, repeated user corrections, memory conflicts, skill patch candidates, and cron/automation improvements. Do not automatically delete/replace memory or patch/archive skills unless the user explicitly approves the proposed changes. See references/weekly-dreaming-routine.md for the recommended prompt, report format, safety policy, and cron creation pattern.
Kanban (multi-agent work queue)
Durable SQLite board for multi-profile / multi-worker collaboration.
Users drive it via hermes kanban <verb>; dispatcher-spawned workers
see a focused kanban_* toolset gated by HERMES_KANBAN_TASK so the
schema footprint is zero outside worker processes.
- CLI verbs (common):
init, create, list (alias ls),
show, assign, link, unlink, comment, complete, block,
unblock, archive, tail. Less common: watch, stats, runs,
log, dispatch, daemon, gc.
- Worker toolset:
kanban_show, kanban_complete, kanban_block,
kanban_heartbeat, kanban_comment, kanban_create, kanban_link.
- Dispatcher runs inside the gateway by default
( kanban.dispatch_in_gateway: true) โ reclaims stale claims,
promotes ready tasks, atomically claims, spawns assigned profiles.
Auto-blocks a task after ~5 consecutive spawn failures.
- Isolation: board is the hard boundary (workers get
HERMES_KANBAN_BOARD pinned in env); tenant is a soft namespace
within a board for workspace-path + memory-key isolation.
User docs: https://hermes-agent.nousresearch.com/docs/user-guide/features/kanban
Log Relay (Hermes โ Discord)
A background Python script that tails ~/.hermes/logs/*.log and batches lines to a Discord channel. Includes session-ID extraction, rate-limit handling, and auto-restart via launchd/systemd. Useful for remote monitoring and audit trails.
- Reference:
references/discord-log-relay.md โ full setup, tuning, macOS/Linux service install, pitfalls.
- Template:
templates/discord-log-relay.py โ copy, set CHANNEL_ID, and deploy.
- Discord operations:
references/discord-operating-planes.md โ channel-purpose routing, periodic-summary vs Dreaming report formats, and safety/cost notes for Discord-first Hermes deployments.
Key pitfall: ask the user about batch frequency upfront rather than defaulting to real-time streaming. Most users prefer 10-minute or hourly batches. High-volume raw logs should be batched, summarized, or stored out-of-band; avoid Discord message storms during error loops.
Weekly Dreaming / Memory Curation
For long-running Hermes deployments, users may want an Anthropic-style "Dreaming" loop: a scheduled review that consolidates experience, proposes memory/skill/cron changes, and identifies what to keep, weaken, archive, or delete. Hermes has the building blocks (sessions, session_search, memory, skills, curator, cron), but the safe default is proposal mode:
1. Inspect recent usage and sessions.
2. Extract repeated success patterns, failure patterns, and user corrections.
3. Propose memory updates/removals without applying them silently.
4. Propose skill patches/archive candidates and cron/reporting improvements.
5. End with explicit approval checkboxes.
Do not silently rewrite or delete memory/skills from a Dreaming report unless the user explicitly authorized automatic application. See references/discord-operating-planes.md for a report template and routing heuristics.
---
Windows-Specific Quirks
Hermes runs natively on Windows (PowerShell, cmd, Windows Terminal, git-bash
mintty, VS Code integrated terminal). Most of it just works, but a handful
of differences between Win32 and POSIX have bitten us โ document new ones
here as you hit them so the next person (or the next session) doesn't
rediscover them from scratch.
Input / Keybindings
Alt+Enter doesn't insert a newline. Windows Terminal intercepts Alt+Enter
at the terminal layer to toggle fullscreen โ the keystroke never reaches
prompt_toolkit. Use Ctrl+Enter instead. Windows Terminal delivers
Ctrl+Enter as LF ( c-j), distinct from plain Enter ( c-m / CR), and the
CLI binds c-j to newline insertion on win32 only (see
_bind_prompt_submit_keys + the Windows-only c-j binding in cli.py).
Side effect: the raw Ctrl+J keystroke also inserts a newline on Windows โ
unavoidable, because Windows Terminal collapses Ctrl+Enter and Ctrl+J to
the same keycode at the Win32 console API layer. No conflicting binding
existed for Ctrl+J on Windows, so this is a harmless side effect.
mintty / git-bash behaves the same (fullscreen on Alt+Enter) unless you
disable Alt+Fn shortcuts in Options โ Keys. Easier to just use Ctrl+Enter.
Diagnosing keybindings. Run python scripts/keystroke_diagnostic.py
(repo root) to see exactly how prompt_toolkit identifies each keystroke
in the current terminal. Answers questions like "does Shift+Enter come
through as a distinct key?" (almost never โ most terminals collapse it
to plain Enter) or "what byte sequence is my terminal sending for
Ctrl+Enter?" This is how the Ctrl+Enter = c-j fact was established.
Config / Files
HTTP 400 "No models provided" on first run. config.yaml was saved
with a UTF-8 BOM (common when Windows apps write it). Re-save as UTF-8
without BOM. hermes config edit writes without BOM; manual edits in
Notepad are the usual culprit.
execute_code / Sandbox
WinError 10106 ("The requested service provider could not be loaded
or initialized") from the sandbox child process โ it can't create an
AF_INET socket, so the loopback-TCP RPC fallback fails before
connect(). Root cause is usually not a broken Winsock LSP; it's
Hermes's own env scrubber dropping SYSTEMROOT / WINDIR / COMSPEC
from the child env. Python's socket module needs SYSTEMROOT to locate
mswsock.dll. Fixed via the _WINDOWS_ESSENTIAL_ENV_VARS allowlist in
tools/code_execution_tool.py. If you still hit it, echo os.environ
inside an execute_code block to confirm SYSTEMROOT is set. Full
diagnostic recipe in references/execute-code-sandbox-env-windows.md.
Testing / Contributing
scripts/run_tests.sh doesn't work as-is on Windows โ it looks for
POSIX venv layouts ( .venv/bin/activate). The Hermes-installed venv at
venv/Scripts/ has no pip or pytest either (stripped for install size).
Workaround: install pytest + pytest-xdist + pyyaml into a system Python
3.11 user site, then invoke pytest directly with PYTHONPATH set:
"/c/Program Files/Python311/python" -m pip install --user pytest pytest-xdist pyyaml
export PYTHONPATH="$(pwd)"
"/c/Program Files/Python311/python" -m pytest tests/foo/test_bar.py -v --tb=short -n 0
Use -n 0, not -n 4 โ pyproject.toml's default addopts already
includes -n, and the wrapper's CI-parity guarantees don't apply off POSIX.
POSIX-only tests need skip guards. Common markers already in the codebase:
- Symlinks โ elevated privileges on Windows
0o600 file modes โ POSIX mode bits not enforced on NTFS by default
signal.SIGALRM โ Unix-only (see tests/conftest.py::_enforce_test_timeout)
- Winsock / Windows-specific regressions โ
@pytest.mark.skipif(sys.platform != "win32", ...)
Use the existing skip-pattern style (sys.platform == "win32" or
sys.platform.startswith("win")) to stay consistent with the rest of the
suite.
Path / Filesystem
Line endings. Git may warn LF will be replaced by CRLF the next time
Git touches it. Cosmetic โ the repo's .gitattributes normalizes. Don't
let editors auto-convert committed POSIX-newline files to CRLF.
Forward slashes work almost everywhere. C:/Users/... is accepted by
every Hermes tool and most Windows APIs. Prefer forward slashes in code
and logs โ avoids shell-escaping backslashes in bash.
---
Troubleshooting
Voice not working
1. Check stt.enabled: true in config.yaml
2. Verify provider: pip install faster-whisper or set API key
3. In gateway: /restart. In CLI: exit and relaunch.
Tool not available
1. hermes tools โ check if toolset is enabled for your platform
2. Some tools need env vars (check .env)
3. /reset after enabling tools
Model/provider issues
1. hermes doctor โ check config and dependencies
2. hermes auth add <provider> โ re-authenticate OAuth providers (use --type oauth)
3. Check .env has the right API key
4. Copilot 403: gh auth login tokens do NOT work for Copilot API. You must use the Copilot-specific OAuth device code flow via hermes model โ GitHub Copilot.
Changes not taking effect
- Tools/skills:
/reset starts a new session with updated toolset
- Config changes: In gateway:
/restart. In CLI: exit and relaunch.
- Code changes: Restart the CLI or gateway process
Deployed web dashboard shows stale CSS or theme changes
- Browser cache: Add
?v=N cache-busting query strings to CSS/JS/theme links in HTML.
- Service Worker cache: Bump
CACHE_NAME in sw.js to invalidate old shell caches.
- Data freshness: Use
fetch(url, {cache:'no-store'}) for live JSON feeds.
- See
references/static-site-cache-invalidation.md for the full diagnostic recipe.
Dashboard inspector feels too technical
- The default inspector view should contain only plain-language sentences: headline, "what they're doing now", "why it matters", and a silent visual progress bar (no text label).
- Move all technical fields (source IDs, confidence scores, progress labels, status slugs, badges) behind a "Show technical details" toggle.
- If users say "details are hard to understand," the fix is to remove more fields from the default view, not to add explanations. Explanations of technical fields are still technical.
- See
references/progressive-disclosure-human-first.md for the aggressive simplification pattern.
Skills not showing
1. hermes skills list โ verify installed
2. hermes skills config โ check platform enablement
3. Load explicitly: /skill name or hermes -s name
Gateway issues
Check logs first:
grep -i "failed to send\|error" ~/.hermes/logs/gateway.log | tail -20
Common gateway problems:
- Gateway dies on SSH logout: Enable linger:
sudo loginctl enable-linger $USER
- Gateway dies on WSL2 close: WSL2 requires
systemd=true in /etc/wsl.conf for systemd services to work. Without it, gateway falls back to nohup (dies when session closes).
- Gateway crash loop: Reset the failed state:
systemctl --user reset-failed hermes-gateway
- macOS: bot shows offline after idle time: The gateway runs as a user agent (
LimitLoadToSessionType=Aqua), so macOS suspends it when the system sleeps. The platform websocket drops and the bot appears offline until the network returns. Fix: keep the Mac awake (System Settings -> Energy -> Prevent automatic sleeping, or caffeinate -d -i -s -u &). Low Power Mode makes this worse, not better. See references/macos-gateway-sleep-disconnect.md for the full diagnostic recipe.
Platform-specific issues
- Discord bot silent: Must enable Message Content Intent in Bot โ Privileged Gateway Intents. See full Discord setup reference:
references/discord-gateway-setup.md.
- Slack bot only works in DMs: Must subscribe to
message.channels event. Without it, the bot ignores public channels.
- Windows-specific issues (
Alt+Enter newline, WinError 10106, UTF-8 BOM config, test suite, line endings): see the dedicated Windows-Specific Quirks section above.
Auxiliary models not working
If auxiliary tasks (vision, compression, session_search) fail silently, the auto provider can't find a backend. Either set OPENROUTER_API_KEY or GOOGLE_API_KEY, or explicitly configure each auxiliary task's provider:
hermes config set auxiliary.vision.provider <your_provider>
hermes config set auxiliary.vision.model <model_name>
Full system auth provisioning
For a one-shot workflow to maximize available credentials โ installing gh, generating SSH keys, configuring git, enabling all Hermes toolsets, and auditing current auth state โ see references/system-auth-setup.md.
Editing large files with patch
When a file is read with read_file(offset=...) (pagination), the tool warns that the view is partial. If you attempt patch without re-reading the full file first, you will likely hit non-unique match errors or corrupt the file. Fix: always call read_file without offset to load the whole file before patching. For append-only updates (e.g., adding a cycle log entry to state.md), do not use terminal(command="cat >> file << 'EOF'...EOF") โ the terminal tool on macOS/Linux misinterprets heredoc << as backgrounding and fails. Instead, write a short Python script via write_file and execute it with terminal(command="python3 /tmp/script.py"). See references/terminal-heredoc-workaround.md for the full pattern.
Sibling subagent file overwrites
When multiple subagents are running in parallel (e.g. via delegate_task batch mode or kanban worker lanes), a file may be modified by one subagent while another is about to write to it. If you use write_file or patch on a file that was last read before a sibling subagent modified it, your write may silently truncate or revert the sibling's changes. The tool may show a warning like "this file was modified by sibling subagent X but this agent never read it."
Fix:
1. Heed the warning. If the tool reports a sibling modification, re-read the file with read_file before writing.
2. Prefer patch over write_file for partial updates โ patch only changes the matched region and is less likely to wipe unrelated content.
3. If the file is already published/deployed, and the local working copy gets corrupted, recover from the published copy:
cp ~/hermes-web/agent-pets/css/dashboard.css ~/.hermes/autonomous-agent-lab/pixel-pet-ops/web/css/dashboard.css
4. For append-only updates, write a small Python script and execute it rather than using write_file on the whole file.
Prevention: In kanban/multi-agent workflows, assign file-level ownership so only one worker touches each file. If parallel workers must edit the same file, have them write to separate temp files and let the orchestrator merge.
---
Windows-Specific Quirks
| Looking for... | Location |
|----------------|----------|
| Config options | hermes config edit or [Configuration docs](https://hermes-agent.nousresearch.com/docs/user-guide/configuration) |
| Available tools | hermes tools list or [Tools reference](https://hermes-agent.nousresearch.com/docs/reference/tools-reference) |
| Slash commands | /help in session or [Slash commands reference](https://hermes-agent.nousresearch.com/docs/reference/slash-commands) |
| Skills catalog | hermes skills browse or [Skills catalog](https://hermes-agent.nousresearch.com/docs/reference/skills-catalog) |
| Provider setup | hermes model or [Providers guide](https://hermes-agent.nousresearch.com/docs/integrations/providers) |
| Platform setup | hermes gateway setup or [Messaging docs](https://hermes-agent.nousresearch.com/docs/user-guide/messaging/) |
| MCP servers | hermes mcp list or [MCP guide](https://hermes-agent.nousresearch.com/docs/user-guide/features/mcp) |
| Profiles | hermes profile list or [Profiles docs](https://hermes-agent.nousresearch.com/docs/user-guide/profiles) |
| Cron jobs | hermes cron list or [Cron docs](https://hermes-agent.nousresearch.com/docs/user-guide/features/cron) |
| Memory | hermes memory status or [Memory docs](https://hermes-agent.nousresearch.com/docs/user-guide/features/memory) |
| Env variables | hermes config env-path or [Env vars reference](https://hermes-agent.nousresearch.com/docs/reference/environment-variables) |
| CLI commands | hermes --help or [CLI reference](https://hermes-agent.nousresearch.com/docs/reference/cli-commands) |
| Gateway logs | ~/.hermes/logs/gateway.log |
| Session files | ~/.hermes/sessions/ or hermes sessions browse |
| Source code | ~/.hermes/hermes-agent/ |
---
Contributor Quick Reference
For occasional contributors and PR authors. Full developer docs: https://hermes-agent.nousresearch.com/docs/developer-guide/
Project Layout
hermes-agent/
โโโ run_agent.py # AIAgent โ core conversation loop
โโโ model_tools.py # Tool discovery and dispatch
โโโ toolsets.py # Toolset definitions
โโโ cli.py # Interactive CLI (HermesCLI)
โโโ hermes_state.py # SQLite session store
โโโ agent/ # Prompt builder, context compression, memory, model routing, credential pooling, skill dispatch
โโโ hermes_cli/ # CLI subcommands, config, setup, commands
โ โโโ commands.py # Slash command registry (CommandDef)
โ โโโ config.py # DEFAULT_CONFIG, env var definitions
โ โโโ main.py # CLI entry point and argparse
โโโ tools/ # One file per tool
โ โโโ registry.py # Central tool registry
โโโ gateway/ # Messaging gateway
โ โโโ platforms/ # Platform adapters (telegram, discord, etc.)
โโโ cron/ # Job scheduler
โโโ tests/ # ~3000 pytest tests
โโโ website/ # Docusaurus docs site
Config: ~/.hermes/config.yaml (settings), ~/.hermes/.env (API keys).
Adding a Tool (3 files)
1. Create tools/your_tool.py:
import json, os
from tools.registry import registry
def check_requirements() -> bool:
return bool(os.getenv("EXAMPLE_API_KEY"))
def example_tool(param: str, task_id: str = None) -> str:
return json.dumps({"success": True, "data": "..."})
registry.register(
name="example_tool",
toolset="example",
schema={"name": "example_tool", "description": "...", "parameters": {...}},
handler=lambda args, **kw: example_tool(
param=args.get("param", ""), task_id=kw.get("task_id")),
check_fn=check_requirements,
requires_env=["EXAMPLE_API_KEY"],
)
2. Add to toolsets.py โ _HERMES_CORE_TOOLS list.
Auto-discovery: any tools/*.py file with a top-level registry.register() call is imported automatically โ no manual list needed.
All handlers must return JSON strings. Use get_hermes_home() for paths, never hardcode ~/.hermes.
Adding a Slash Command
1. Add CommandDef to COMMAND_REGISTRY in hermes_cli/commands.py
2. Add handler in cli.py โ process_command()
3. (Optional) Add gateway handler in gateway/run.py
All consumers (help text, autocomplete, Telegram menu, Slack mapping) derive from the central registry automatically.
Agent Loop (High Level)
run_conversation():
1. Build system prompt
2. Loop while iterations < max:
a. Call LLM (OpenAI-format messages + tool schemas)
b. If tool_calls โ dispatch each via handle_function_call() โ append results โ continue
c. If text response โ return
3. Context compression triggers automatically near token limit
Testing
python -m pytest tests/ -o 'addopts=' -q # Full suite
python -m pytest tests/tools/ -q # Specific area
- Tests auto-redirect
HERMES_HOME to temp dirs โ never touch real ~/.hermes/
- Run full suite before pushing any change
- Use
-o 'addopts=' to clear any baked-in pytest flags
Windows contributors: scripts/run_tests.sh currently looks for POSIX venvs ( .venv/bin/activate / venv/bin/activate) and will error out on Windows where the layout is venv/Scripts/activate + python.exe. The Hermes-installed venv at venv/Scripts/ also has no pip or pytest โ it's stripped for end-user install size. Workaround: install pytest + pytest-xdist + pyyaml into a system Python 3.11 user site ( /c/Program Files/Python311/python -m pip install --user pytest pytest-xdist pyyaml), then run tests directly:
export PYTHONPATH="$(pwd)"
"/c/Program Files/Python311/python" -m pytest tests/tools/test_foo.py -v --tb=short -n 0
Use -n 0 (not -n 4) because pyproject.toml's default addopts already includes -n, and the wrapper's CI-parity story doesn't apply off-POSIX.
Cross-platform test guards: tests that use POSIX-only syscalls need a skip marker. Common ones already in the codebase:
- Symlink creation โ
@pytest.mark.skipif(sys.platform == "win32", reason="Symlinks require elevated privileges on Windows") (see tests/cron/test_cron_script.py)
- POSIX file modes (0o600, etc.) โ
@pytest.mark.skipif(sys.platform.startswith("win"), reason="POSIX mode bits not enforced on Windows") (see tests/hermes_cli/test_auth_toctou_file_modes.py)
signal.SIGALRM โ Unix-only (see tests/conftest.py::_enforce_test_timeout)
- Live Winsock / Windows-specific regression tests โ
@pytest.mark.skipif(sys.platform != "win32", reason="Windows-specific regression")
Monkeypatching sys.platform is not enough when the code under test also calls platform.system() / platform.release() / platform.mac_ver(). Those functions re-read the real OS independently, so a test that sets sys.platform = "linux" on a Windows runner will still see platform.system() == "Windows" and route through the Windows branch. Patch all three together:
monkeypatch.setattr(sys, "platform", "linux")
monkeypatch.setattr(platform, "system", lambda: "Linux")
monkeypatch.setattr(platform, "release", lambda: "6.8.0-generic")
See tests/agent/test_prompt_builder.py::TestEnvironmentHints for a worked example.
Extending the system prompt's execution-environment block
Factual guidance about the host OS, user home, cwd, terminal backend, and shell (bash vs. PowerShell on Windows) is emitted from agent/prompt_builder.py::build_environment_hints(). This is also where the WSL hint and per-backend probe logic live. The convention:
- Local terminal backend โ emit host info (OS,
$HOME, cwd) + Windows-specific notes (hostname โ username, terminal uses bash not PowerShell).
- Remote terminal backend (anything in
_REMOTE_TERMINAL_BACKENDS: docker, singularity, modal, daytona, ssh, vercel_sandbox, managed_modal) โ suppress host info entirely and describe only the backend. A live uname/whoami/pwd probe runs inside the backend via tools.environments.get_environment(...).execute(...), cached per process in _BACKEND_PROBE_CACHE, with a static fallback if the probe times out.
- Key fact for prompt authoring: when
TERMINAL_ENV != "local", every file tool (read_file, write_file, patch, search_files) runs inside the backend container, not on the host. The system prompt must never describe the host in that case โ the agent can't touch it.
Full design notes, the exact emitted strings, and testing pitfalls:
references/prompt-builder-environment-hints.md.
Refactor-safety pattern (POSIX-equivalence guard): when you extract inline logic into a helper that adds Windows/platform-specific behavior, keep a _legacy_<name> oracle function in the test file that's a verbatim copy of the old code, then parametrize-diff against it. Example: tests/tools/test_code_execution_windows_env.py::TestPosixEquivalence. This locks in the invariant that POSIX behavior is bit-for-bit identical and makes any future drift fail loudly with a clear diff.
Commit Conventions
type: concise subject line
Optional body.
Types: fix:, feat:, refactor:, docs:, chore:
Key Rules
- Never break prompt caching โ don't change context, tools, or system prompt mid-conversation
- Message role alternation โ never two assistant or two user messages in a row
- Use
get_hermes_home() from hermes_constants for all paths (profile-safe)
- Config values go in
config.yaml, secrets go in .env
- New tools need a
check_fn so they only appear when requirements are met
[IMPORTANT: The user has invoked the "kanban-orchestrator" skill, indicating they want you to follow its instructions. The full skill content is loaded below.]
---
name: kanban-orchestrator
description: Decomposition playbook + anti-temptation rules for an orchestrator profile routing work through Kanban. The "don't do the work yourself" rule and the basic lifecycle are auto-injected into every kanban worker's system prompt; this skill is the deeper playbook when you're specifically playing the orchestrator role.
version: 3.0.0
platforms: [linux, macos, windows]
metadata:
hermes:
tags: [kanban, multi-agent, orchestration, routing]
related_skills: [kanban-worker]
---
Kanban Orchestrator โ Decomposition Playbook
> The core worker lifecycle (including the kanban_create fan-out pattern and the "decompose, don't execute" rule) is auto-injected into every kanban process via the KANBAN_GUIDANCE system-prompt block. This skill is the deeper playbook when you're an orchestrator profile whose whole job is routing.
Profiles are user-configured โ not a fixed roster
Hermes setups vary widely. Some users run a single profile that does everything; some run a small fleet (docker-worker, cron-worker); some run a curated specialist team they've named themselves. There is no default specialist roster โ the orchestrator skill does not know what profiles exist on this machine.
Before fanning out, you must ground the decomposition in the profiles that actually exist. The dispatcher silently fails to spawn unknown assignee names โ it doesn't autocorrect, doesn't suggest, doesn't fall back. So a card assigned to researcher on a setup that only has docker-worker just sits in ready forever.
Step 0: discover available profiles before planning.
Use one of these:
hermes profile list โ prints the table of profiles configured on this machine. Run it through your terminal tool if you have one; otherwise ask the user.
kanban_list(assignee="<some-name>") โ sanity-check a single name. Returns an empty list (rather than an error) for an unknown assignee, so this only confirms a name you're already considering.
- Just ask the user. "What profiles do you have set up?" is a fine first turn when the goal needs more than one specialist.
Cache the result in your working memory for the rest of the conversation. Re-asking every turn wastes a tool call.
When to use the board (vs. just doing the work)
Create Kanban tasks when any of these are true:
1. Multiple specialists are needed. Research + analysis + writing is three profiles.
2. The work should survive a crash or restart. Long-running, recurring, or important.
3. The user might want to interject. Human-in-the-loop at any step.
4. Multiple subtasks can run in parallel. Fan-out for speed.
5. Review / iteration is expected. A reviewer profile loops on drafter output.
6. The audit trail matters. Board rows persist in SQLite forever.
If none of those apply โ it's a small one-shot reasoning task โ use delegate_task instead or answer the user directly.
The anti-temptation rules
Your job description says "route, don't execute." The rules that enforce that:
- Do not execute the work yourself. Your restricted toolset usually doesn't even include terminal/file/code/web for implementation. If you find yourself "just fixing this quickly" โ stop and create a task for the right specialist.
- For any concrete task, create a Kanban task and assign it. Every single time.
- Split multi-lane requests before creating cards. A user prompt can contain several independent workstreams. Extract those lanes first, then create one card per lane instead of bundling unrelated work into a single implementer card.
- Run independent lanes in parallel. If two cards do not need each other's output, leave them unlinked so the dispatcher can fan them out. Link only true data dependencies.
- If no specialist fits the available profiles, ask the user which profile to create or which existing profile to use. Do not invent profile names; the dispatcher will silently drop unknown assignees.
- Decompose, route, and summarize โ that's the whole job.
Exception: micro-UI polish cycles
There is one narrow exception where the orchestrator may execute directly instead of creating Kanban cards: tiny UI-only polish cycles (e.g., adding a CSS class, a theme preview dot, a hover state, a cross-link, or a HUD button) that are purely presentational, require no cross-file logic changes, and fit comfortably inside a single bounded cycle with no need for review or parallel work. If the change is limited to HTML/CSS/JS cosmetics, no other profile has a stake in it, and the user did not ask for a design review, the orchestrator should just edit and publish rather than paying the kanban-overhead tax. This exception does NOT apply to architecture changes, adapter logic, plugin interfaces, or anything that touches the data layer.
Decomposition playbook
Step 1 โ Understand the goal
Ask clarifying questions if the goal is ambiguous. Cheap to ask; expensive to spawn the wrong fleet.
Step 2 โ Sketch the task graph
Before creating anything, draft the graph out loud (in your response to the user). Treat every concrete workstream as a candidate card:
1. Extract the lanes from the request.
2. Map each lane to one of the profiles you discovered in Step 0. If a lane doesn't fit any existing profile, ask the user which to use or create.
3. Decide whether each lane is independent or gated by another lane.
4. Create independent lanes as parallel cards with no parent links.
5. Create synthesis/review/integration cards with parent links to the lanes they depend on.
Examples of prompts that should fan out (using placeholder profile names โ substitute whatever exists on the user's setup):
- "Build an app" โ one card to a design-oriented profile for product/UI direction, one or two cards to engineering profiles for implementation, plus a later integration/review card if the user has a reviewer profile.
- "Fix blockers and check model variants" โ one implementation card for the blocker fixes plus one discovery/research card for config/source verification. A final reviewer card can depend on both.
- "Research docs and implement" โ a docs-research card can run in parallel with a codebase-discovery card; implementation waits only if it truly needs those findings.
- "Analyze this screenshot and find the related code" โ one card to a vision-capable profile for the visual analysis while another searches the codebase.
Words like "also," "finally," or "and" do not automatically imply a dependency. They often mean "make sure this is covered before reporting back." Only link tasks when one card cannot start until another card's output exists.
Show the graph to the user before creating cards. Let them correct it โ including which actual profile name should own each lane.
Step 3 โ Create tasks and link
Use the profile names from Step 0. The example below uses placeholders <profile-A>, <profile-B>, <profile-C> โ replace them with what the user actually has.
t1 = kanban_create(
title="research: Postgres cost vs current",
assignee="<profile-A>", # whichever profile handles research on this setup
body="Compare estimated infrastructure costs, migration costs, and ongoing ops costs over a 3-year window. Sources: AWS/GCP pricing, team time estimates, current Postgres bills from peers.",
tenant=os.environ.get("HERMES_TENANT"),
)["task_id"]
t2 = kanban_create(
title="research: Postgres performance vs current",
assignee="<profile-A>", # same profile, run in parallel
body="Compare query latency, throughput, and scaling characteristics at our expected data volume (~500GB, 10k QPS peak). Sources: benchmark papers, public case studies, pgbench results if easy.",
)["task_id"]
t3 = kanban_create(
title="synthesize migration recommendation",
assignee="<profile-B>", # whichever profile does synthesis/analysis
body="Read the findings from T1 (cost) and T2 (performance). Produce a 1-page recommendation with explicit trade-offs and a go/no-go call.",
parents=[t1, t2],
)["task_id"]
t4 = kanban_create(
title="draft decision memo",
assignee="<profile-C>", # whichever profile drafts user-facing prose
body="Turn the analyst's recommendation into a 2-page memo for the CTO. Match the tone of previous decision memos in the team's knowledge base.",
parents=[t3],
)["task_id"]
parents=[...] gates promotion โ children stay in todo until every parent reaches done, then auto-promote to ready. No manual coordination needed; the dispatcher and dependency engine handle it.
Step 4 โ Complete your own task
If you were spawned as a task yourself (e.g. a planner profile was assigned T0: "investigate Postgres migration"), mark it done with a summary of what you created:
kanban_complete(
summary="decomposed into T1-T4: 2 research lanes in parallel, 1 synthesis on their outputs, 1 prose draft on the recommendation",
metadata={
"task_graph": {
"T1": {"assignee": "<profile-A>", "parents": []},
"T2": {"assignee": "<profile-A>", "parents": []},
"T3": {"assignee": "<profile-B>", "parents": ["T1", "T2"]},
"T4": {"assignee": "<profile-C>", "parents": ["T3"]},
},
},
)
Step 5 โ Report back to the user
Tell them what you created in plain prose, naming the actual profiles you used:
> I've queued 4 tasks:
> - T1 (<profile-A>): cost comparison
> - T2 (<profile-A>): performance comparison, in parallel with T1
> - T3 (<profile-B>): synthesizes T1 + T2 into a recommendation
> - T4 (<profile-C>): turns T3 into a CTO memo
>
> The dispatcher will pick up T1 and T2 now. T3 starts when both finish. You'll get a gateway ping when T4 completes. Use the dashboard or hermes kanban tail <id> to follow along.
Common patterns
Fan-out + fan-in (research โ synthesize): N research-style cards with no parents, one synthesis card with all of them as parents.
Parallel implementation + validation: one implementer card makes the change while one explorer/researcher card verifies config, docs, or source mapping. A reviewer card can depend on both. Do not make the implementer own unrelated verification just because the user mentioned both in one sentence.
Pipeline with gates: planner โ implementer โ reviewer. Each stage's parents=[previous_task]. Reviewer blocks or completes; if reviewer blocks, the operator unblocks with feedback and respawns.
Same-profile queue: N tasks, all assigned to the same profile, no dependencies between them. Dispatcher serializes โ that profile processes them in priority order, accumulating experience in its own memory.
Parallel UI/frontend lanes: When the goal touches multiple independent HTML/CSS/JS files (e.g., a dashboard page and a 2D gather view), fan out to separate subagents per file. Each lane edits its own file, then the orchestrator integrates, fixes cross-file references (theme paths, shared JSON endpoints), and publishes. This avoids merge conflicts in single-file HTML dashboards and keeps each subagent's context focused. See references/parallel-ui-lanes-and-publishing.md for the post-subagent integration checklist and rsync safety notes.
Human-in-the-loop: Any task can kanban_block() to wait for input. Dispatcher respawns after /unblock. The comment thread carries the full context.
Pitfalls
Inventing profile names that don't exist. The dispatcher silently fails to spawn unknown assignees โ the card just sits in ready forever. Always assign to a profile from your Step 0 discovery; ask the user if you're unsure.
Bundling independent lanes into one card. If the user asks for two independent outcomes, create two cards. Example: "fix blockers and check model variants" is not one fixer task; create a fixer/engineer card for the fixes and an explorer/researcher card for the variant check, then optionally gate review on both.
Over-linking because of wording. "Finally check X" may still be parallel with implementation if X is static config, docs, or source discovery. Link it after implementation only when the check depends on the implementation result.
Forgetting dependency links. If the task graph says research -> implement -> review, do not create all tasks as independent ready cards. Use parent links so implement/review cannot run before their inputs exist.
Reassignment vs. new task. If a reviewer blocks with "needs changes," create a NEW task linked from the reviewer's task โ don't re-run the same task with a stern look. The new task is assigned to the original implementer profile.
Argument order for links. kanban_link(parent_id=..., child_id=...) โ parent first. Mixing them up demotes the wrong task to todo.
Ignoring explicit user feedback to keep building infrastructure. When the user says a specific UX issue (legibility, theme switching, movement density) is "immediate priority," treat it as P0 and route it before deeper packaging/architecture work. Infrastructure polish feels productive, but shipping user-visible fixes is what matters. Create cards for the UX feedback first, then resume infrastructure lanes.
Treating status: complete as immutable when user feedback says otherwise. A state.md that says status: complete does not override a user's report that a completion criterion is actually broken. If the user says "theme switching is not working" and the Final Completion Condition requires "working UI theme switcher," the mission is not complete. Reactivate immediately: set status: active, append a reactivation cycle log, and fix the issue. Do not burn cycles on post-complete verification while the user is reporting active defects.
Don't pre-create the whole graph if the shape depends on intermediate findings. If T3's structure depends on what T1 and T2 find, let T3 exist as a "synthesize findings" task whose own first step is to read parent handoffs and plan the rest. Orchestrators can spawn orchestrators.
Tenant inheritance. If HERMES_TENANT is set in your env, pass tenant=os.environ.get("HERMES_TENANT") on every kanban_create call so child tasks stay in the same namespace.
Verifying cross-file references after directory reorganization. When subagents edit HTML/CSS/JS files and the directory structure shifts (e.g., moving files from root into web/dashboard/ and web/gather/), relative asset paths ( themes/default/theme.css, ./ops-data.json) often break. After subagents finish, the orchestrator must grep for href= and src= in moved files and fix relative paths before publishing. Subagents don't know the final publish layout โ the orchestrator does.
Destructive sync wipes needed files. Commands like rsync -av --delete will delete destination files that aren't in the source list. If you publish a directory tree piecemeal (e.g., copy web/dashboard/ first, then web/gather/ separately), --delete on the first rsync will erase the gather files before the second rsync runs. Either list all source paths in a single rsync invocation, or omit --delete and use cp -r / rsync -av without deletion when doing staged copies.
Recovering stuck workers
When a worker profile keeps crashing, hallucinating, or getting blocked by its own mistakes (usually: wrong model, missing skill, broken credential), the kanban dashboard flags the task with a โ badge and opens a Recovery section in the drawer. Three primary actions:
1. Reclaim (or hermes kanban reclaim <task_id>) โ abort the running worker immediately and reset the task to ready. The existing claim TTL is ~15 min; this is the fast path out.
2. Reassign (or hermes kanban reassign <task_id> <new-profile> --reclaim) โ switch the task to a different profile (one that exists on this setup) and let the dispatcher pick it up with a fresh worker.
3. Change profile model โ the dashboard prints a copy-paste hint for hermes -p <profile> model since profile config lives on disk; edit it in a terminal, then Reclaim to retry with the new model.
Hallucination warnings appear on tasks where a worker's kanban_complete(created_cards=[...]) claim included card ids that don't exist or weren't created by the worker's profile (the gate blocks the completion), or where the free-form summary references t_<hex> ids that don't resolve (advisory prose scan, non-blocking). Both produce audit events that persist even after recovery actions โ the trail stays for debugging.
The user has provided the following instruction alongside the skill invocation: [IMPORTANT: You are running as a scheduled cron job. DELIVERY: Your final response will be automatically delivered to the user โ do NOT use send_message or try to deliver the output yourself. Just produce your report/output as your final response and the system handles the rest. SILENT: If there is genuinely nothing new to report, respond with exactly "[SILENT]" (nothing else) to suppress delivery. Never combine [SILENT] with content โ either report your findings normally, or say [SILENT] and nothing more.]
You are the 15-minute Orchestrator for Son's Autonomous Agent Lab v1, reporting to Discord channel ID 1505805763824586952.
Durable state path: /Users/jooho-hermes/.hermes/autonomous-agent-lab/state.md
Working directory for experiment artifacts: /Users/jooho-hermes/.hermes/autonomous-agent-lab/
Preferred published web root: /Users/jooho-hermes/hermes-web/agent-pets/
Top-level directive from Son:
- The project has evolved from a personal dashboard into an INSTALLABLE PRODUCT that external Hermes users can deploy.
- The final target is a self-contained, configurable, publishable solution: "Hermes Pixel Pet Ops Office".
- Do NOT shrink the mission into a small static MVP and autonomously stop.
- The Gather.town-style 2D spatial office is a first-class feature, not a side page.
Latest UX feedback from Son (treat as immediate priority before deeper packaging work):
- Details are hard for a human to understand. Add human-first summaries, plain-language labels, and progressive disclosure: summary first, technical details second.
- Gather Town version has too many agents roaming around. Reduce default movement, add density/speed controls, cluster agents by room/task, and add focus/calm mode.
- Theme switching is not visibly working. Implement real UI theme switcher with persistence and clear visual theme changes.
Key product requirements (installable solution level):
1. Config-driven architecture: all paths, URLs, colors, names, room layouts via config.yaml. No hardcoded references to jooho-hermes.
2. Self-contained package: clear directory structure (src/, web/, config/, docs/, scripts/), install script, requirements.txt.
3. Pluggable data adapter: support multiple backends via plugin architecture.
4. Themeable frontend: CSS variables driven from config, swappable themes, plus a working UI theme switcher.
5. Multi-tenant ready: works for any Hermes instance.
6. Build/Deploy ready: Dockerfile or docker-compose, or clear static-server setup.
7. Documentation: README, architecture docs, configuration reference, contributor guide.
8. Human-comprehensible UX: plain-language summaries and progressive disclosure for technical detail.
9. Gather.town calm mode: adjustable movement density/speed and less chaotic defaults.
10. Versioned releases: CHANGELOG.md, semantic versioning, release packaging.
Mission model:
- Read state.md first before doing anything else.
- If state.md says
status: inactive or has no Current Mission, do not invent work. Return exactly: ๐ก Autonomous Agent Lab ๋๊ธฐ์ค โ Son์ด ํธ๋ฆฌ๊ฑฐ/๋ฏธ์
์ ์ฃผ๋ฉด 15๋ถ ์ฌ์ดํด์ ์์ํฉ๋๋ค.
- If state.md says
status: active, run one bounded 15-minute cycle toward the full installable solution.
- If state.md says
status: complete, verify that the Final Completion Condition in state.md is truly met. If it is not fully met, reactivate or report that state needs correction.
Cycle procedure when active:
1. Read state.md first. Extract current mission, constraints, previous cycle log, and Final Completion Condition.
2. Decide the next smallest useful step toward installable solution quality. Focus on: architecture, configurability, documentation, and clean separation of concerns.
3. Use delegate_task for independent subagent lanes when helpful.
4. Prefer concrete progress: refactor to config-driven, add install scripts, create docs, add Docker support, theme system, plugin architecture.
5. Update state.md with a new cycle log entry before final reporting.
6. Completion rule: only set status: complete when every item under state.md Final Completion Condition is satisfied. A non-installable MVP is not complete.
7. Stop/block only if Son explicitly stops/redirects, a safety boundary is reached, or a hard blocker needs Son's decision.
Link requirement (never forget):
- Every cycle report MUST include at least one direct viewable link to the published dashboard/artifact.
- The canonical URL:
http://hermes-mac-mini.tail46b3c6.ts.net:8099/agent-pets/
- Include gather town URL too:
http://hermes-mac-mini.tail46b3c6.ts.net:8099/agent-pets/gather/
Final Discord message format:
[Autonomous Agent Lab v1 / Cycle N]
๋ชฉํ:
์ํ:
๊ฒฐ๊ณผ:
๊ฒ์ฆ:
๋ค์:
์ํ:
Safety/quality rules:
- Do not handle secrets, passwords, API keys, payment, permission dialogs, or destructive commands.
- Do not claim completion without updating state.md.
- Do not rely on Discord history as durable state.
- Do not spam raw logs; summarize lane outputs and verification.
- Keep working in /Users/jooho-hermes/.hermes/autonomous-agent-lab/ and publish only to /Users/jooho-hermes/hermes-web/agent-pets/ unless the state file says otherwise.
Design/UX priorities:
- Mobile responsiveness is first-class.
- Character animation/movement is desired.
- Every cycle report must include published links.
- This is now a product engineering mission. Architecture, configurability, and documentation matter as much as visuals.
Response
[Autonomous Agent Lab v1 / Cycle 65]
๋ชฉํ:
Son์ UX ํผ๋๋ฐฑ(ํ
๋ง ์ค์์ฒ, Gather calm mode, human-first details)์ด ์ฝ๋์์ผ๋ก๋ ๋ชจ๋ ์์ ๋์์ผ๋, ๋ธ๋ผ์ฐ์ ์บ์ ๋๋ฌธ์ Son์ด ์ค์ ๋ก ๋ณด์ง ๋ชปํ๋ "์ฝ๋๋ ์๋๋ฐ ์ฌ์ฉ์๊ฐ ๋ชป ๋ด" ๋ฌธ์ ๋ฅผ ํด๊ฒฐํฉ๋๋ค.
์ํ:
1. Dashboard์ ์๋ ์บ์ ๊ฐ์ง ๋ฐฐ๋ ์ถ๊ฐ
- ํ์ด์ง ๋ก๋ ์
cache: 'no-store'๋ก ํ์ฌ HTML์ fetch
data-build ์์ฑ ๋น๊ต ํ ์๋ฒ ๋ฒ์ ์ด ๋ ์๋ก์ฐ๋ฉด ์๋จ ๊ณ ์ ๋ฐฐ๋ ํ์
- "โ
์ ๋ก๋์์ผ ๋ณด์ด๋ ๋ฒ์ ์ด ์์ด์" + "ํ์ธ ํ ์๋ก๊ณ ์นจ" ๋ฒํผ ํ ํด๋ฆญ์ผ๋ก ์บ์ ์ญ์ ๋ฐ ๋ฆฌ๋ก๋
2. Gather Town์๋ ๋์ผํ ์บ์ ๊ฐ์ง ๋ก์ง ์ถ๊ฐ (alert ๋ฐฉ์)
3. ์บ์ ๋ฒ์คํ
์ ๋ฉด ๊ฐฑ์ : ?v=64 โ ?v=65, build badge b64 โ b65, sw.js CACHE_NAME v20 โ v21
4. data-build="65"๋ฅผ <html> ํ๊ทธ์ ์ถ๊ฐํ์ฌ ๋ฒ์ ๋น๊ต ๊ธฐ์ค ๋ง๋ จ
5. ๋ชจ๋ ๋ณ๊ฒฝ์ฌํญ์ /Users/jooho-hermes/hermes-web/agent-pets/์ publish ์๋ฃ
๊ฒฐ๊ณผ:
- Dashboard: https://hermes-mac-mini.tail46b3c6.ts.net:8099/agent-pets/
- Gather Town: https://hermes-mac-mini.tail46b3c6.ts.net:8099/agent-pets/gather/
- Published ํ์ผ ๊ฒ์ฆ ์๋ฃ:
data-build="65" ํ์ธ (dashboard + gather)
- build badge
v1.4.4 ยท b65 ํ์ธ
- sw.js
CACHE_NAME = 'pixel-pet-ops-v21' ํ์ธ
.update-banner CSS rule ํ์ธ
ops-data.json, health.json mtime fresh (< 60s)
๊ฒ์ฆ:
- Publish script exit code 0
- Published ํ์ผ์์
data-build="65", b65, v21, ?v=65 ์ผ์น ํ์ธ
refresh.err.log empty, LaunchAgent healthy
๋ค์:
1. Son์ด ๋์๋ณด๋์ ์ ์ํ๋ฉด, ์บ์๊ฐ staleํ ๊ฒฝ์ฐ ์๋จ ๋
น์ ๋ฐฐ๋๊ฐ ์๋์ผ๋ก ํ์๋ฉ๋๋ค.
2. ๋ฐฐ๋์ "ํ์ธ ํ ์๋ก๊ณ ์นจ" ๋ฒํผ์ ํด๋ฆญํ๋ฉด service worker + cache ์ ๋ถ ์ญ์ ํ ์ต์ ๋ฒ์ ๋ก๋.
3. ๋ฆฌํ๋ ์ ํ badge๊ฐ v1.4.4 ยท b65๋ก ํ์๋๋์ง ํ์ธ.
4. ๊ทธ ํ ํ
๋ง ์ค์์ฒ(hero ํจ๋), Gather calm mode(5๋ง๋ฆฌ, calm ๊ธฐ๋ณธ), inspector human-first view ํ
์คํธ.
5. ์ธ ๊ฐ์ง ๋ชจ๋ ๋ง์กฑ์ค๋ฌ์ฐ๋ฉด status: complete๋ก ๋งํน ๊ฐ๋ฅ.
์ํ:
๐ข active โ Son์ ๋ธ๋ผ์ฐ์ ์บ์ ๋ฌธ์ ๋ฅผ ์๋ ๊ฐ์ง + 1ํด๋ฆญ ํด๊ฒฐํ๋ ๋ฉ์ปค๋์ฆ ์ถ๊ฐ. ์ค์ UX ํผ๋๋ฐฑ 3๊ฐ์ง๋ Cycle 53~64์์ ์ฝ๋๋ก ๋ชจ๋ ์์ ๋์์ผ๋ฉฐ, Cycle 65๋ "์ฌ์ฉ์๊ฐ ์ค์ ๋ก ๋ณผ ์ ์๊ฒ" ํ๋ ๋ธ๋ฆฌ์ง ์ญํ . Son์ ํ์ธ ๋๊ธฐ ์ค.
|
| 2026-05-19 18-29-08 |
82,231 chars |
2026-05-19_18-29-08.md |
Cron Job: autonomous-agent-lab-v1-orchestrator
Job ID: 35127ff89556
Run Time: 2026-05-19 18:29:08
Schedule: every 15m
Prompt
[IMPORTANT: The user has invoked the "hermes-agent" skill, indicating they want you to follow its instructions. The full skill content is loaded below.]
---
name: hermes-agent
description: "Configure, extend, or contribute to Hermes Agent."
version: 2.1.0
author: Hermes Agent + Teknium
license: MIT
platforms: [linux, macos, windows]
metadata:
hermes:
tags: [hermes, setup, configuration, multi-agent, spawning, cli, gateway, development]
homepage: https://github.com/NousResearch/hermes-agent
related_skills: [claude-code, codex, opencode]
---
Hermes Agent
Hermes Agent is an open-source AI agent framework by Nous Research that runs in your terminal, messaging platforms, and IDEs. It belongs to the same category as Claude Code (Anthropic), Codex (OpenAI), and OpenClaw โ autonomous coding and task-execution agents that use tool calling to interact with your system. Hermes works with any LLM provider (OpenRouter, Anthropic, OpenAI, DeepSeek, local models, and 15+ others) and runs on Linux, macOS, and WSL.
What makes Hermes different:
- Self-improving through skills โ Hermes learns from experience by saving reusable procedures as skills. When it solves a complex problem, discovers a workflow, or gets corrected, it can persist that knowledge as a skill document that loads into future sessions. Skills accumulate over time, making the agent better at your specific tasks and environment.
- Persistent memory across sessions โ remembers who you are, your preferences, environment details, and lessons learned. Pluggable memory backends (built-in, Honcho, Mem0, and more) let you choose how memory works.
- Multi-platform gateway โ the same agent runs on Telegram, Discord, Slack, WhatsApp, Signal, Matrix, Email, and 10+ other platforms with full tool access, not just chat.
- Provider-agnostic โ swap models and providers mid-workflow without changing anything else. Credential pools rotate across multiple API keys automatically.
- Profiles โ run multiple independent Hermes instances with isolated configs, sessions, skills, and memory.
- Extensible โ plugins, MCP servers, custom tools, webhook triggers, cron scheduling, and the full Python ecosystem.
People use Hermes for software development, research, system administration, data analysis, content creation, home automation, and anything else that benefits from an AI agent with persistent context and full system access.
This skill helps you work with Hermes Agent effectively โ setting it up, configuring features, spawning additional agent instances, troubleshooting issues, finding the right commands and settings, and understanding how the system works when you need to extend or contribute to it.
Docs: https://hermes-agent.nousresearch.com/docs/
Quick Start
Install
curl -fsSL https://raw.githubusercontent.com/NousResearch/hermes-agent/main/scripts/install.sh | bash
Interactive chat (default)
hermes
Single query
hermes chat -q "What is the capital of France?"
Setup wizard
hermes setup
Change model/provider
hermes model
Check health
hermes doctor
---
CLI Reference
Global Flags
hermes [flags] [command]
--version, -V Show version
--resume, -r SESSION Resume session by ID or title
--continue, -c [NAME] Resume by name, or most recent session
--worktree, -w Isolated git worktree mode (parallel agents)
--skills, -s SKILL Preload skills (comma-separate or repeat)
--profile, -p NAME Use a named profile
--yolo Skip dangerous command approval
--pass-session-id Include session ID in system prompt
No subcommand defaults to chat.
Chat
hermes chat [flags]
-q, --query TEXT Single query, non-interactive
-m, --model MODEL Model (e.g. anthropic/claude-sonnet-4)
-t, --toolsets LIST Comma-separated toolsets
--provider PROVIDER Force provider (openrouter, anthropic, nous, etc.)
-v, --verbose Verbose output
-Q, --quiet Suppress banner, spinner, tool previews
--checkpoints Enable filesystem checkpoints (/rollback)
--source TAG Session source tag (default: cli)
Configuration
hermes setup [section] Interactive wizard (model|terminal|gateway|tools|agent)
hermes model Interactive model/provider picker
hermes config View current config
hermes config edit Open config.yaml in $EDITOR
hermes config set KEY VAL Set a config value
hermes config path Print config.yaml path
hermes config env-path Print .env path
hermes config check Check for missing/outdated config
hermes config migrate Update config with new options
hermes doctor [--fix] Check dependencies and config
Credential Pools
hermes auth add Interactive credential wizard (oauth, api-key)
hermes auth list [PROVIDER] List pooled credentials
hermes auth remove P INDEX Remove by provider + index
hermes auth reset PROVIDER Clear exhaustion status
hermes logout Clear stored auth
Tools & Skills
hermes tools Interactive tool enable/disable (curses UI)
hermes tools list Show all tools and status
hermes tools enable NAME Enable a toolset
hermes tools disable NAME Disable a toolset
hermes skills list List installed skills
hermes skills search QUERY Search the skills hub
hermes skills install ID Install a skill (ID can be a hub identifier OR a direct https://โฆ/SKILL.md URL; pass --name to override when frontmatter has no name)
hermes skills inspect ID Preview without installing
hermes skills config Enable/disable skills per platform
hermes skills check Check for updates
hermes skills update Update outdated skills
hermes skills uninstall N Remove a hub skill
hermes skills publish PATH Publish to registry
hermes skills browse Browse all available skills
hermes skills tap add REPO Add a GitHub repo as skill source
MCP Servers
hermes mcp serve Run Hermes as an MCP server
hermes mcp add NAME Add an MCP server (--url or --command)
hermes mcp remove NAME Remove an MCP server
hermes mcp list List configured servers
hermes mcp test NAME Test connection
hermes mcp configure NAME Toggle tool selection
Gateway (Messaging Platforms)
hermes gateway run Start gateway foreground
hermes gateway install Install as background service
hermes gateway start/stop Control the service
hermes gateway restart Restart the service
hermes gateway status Check status
hermes gateway setup Configure platforms
Supported platforms: Telegram, Discord, Slack, WhatsApp, Signal, Email, SMS, Matrix, Mattermost, Home Assistant, DingTalk, Feishu, WeCom, BlueBubbles (iMessage), Weixin (WeChat), API Server, Webhooks. Open WebUI connects via the API Server adapter.
Platform docs: https://hermes-agent.nousresearch.com/docs/user-guide/messaging/
Discord-specific walkthrough (token, intents, service install, access control): see references/discord-gateway-setup.md in this skill.
- Per-channel personas and skill bindings: see
references/gateway-channel-personas.md (works on Discord, Slack, Telegram, Mattermost, Matrix).
- For long-running Discord-first operations, purpose-specific channel routing, periodic summaries, weekly Dreaming/audit reports, and log-safety patterns: see
references/discord-operating-planes.md.
- For broad Hermes/LifeOS/SQAF ecosystem audits (cron inventory, live services, dashboards, provider/model warnings, and control-plane gaps), see
references/ecosystem-audit.md.
Sessions
hermes sessions list List recent sessions
hermes sessions browse Interactive picker
hermes sessions export OUT Export to JSONL
hermes sessions rename ID T Rename a session
hermes sessions delete ID Delete a session
hermes sessions prune Clean up old sessions (--older-than N days)
hermes sessions stats Session store statistics
For browser-based viewing of existing Hermes CLI/Discord/cron session transcripts, prefer a lightweight static export from ~/.hermes/state.db into a private web root instead of assuming Open WebUI can browse Hermes' native session store. See references/hermes-session-static-web-viewer.md for the SQLite schema, static HTML export workflow, redaction/truncation cautions, and the user's Mac mini deployment (/hermes-sessions/ under the Tailscale-only ~/hermes-web site).
For cron job execution history, the same static-export pattern applies to ~/.hermes/cron/jobs.json and ~/.hermes/cron/output/{job_id}/*.md. See references/cron-history-web-viewer.md for the cron data model, schedule-dict pitfall, and the user's deployed /cron-history/ dashboard.
Cron Jobs
hermes cron list List jobs (--all for disabled)
hermes cron create SCHED Create: '30m', 'every 2h', '0 9 *'
hermes cron edit ID Edit schedule, prompt, delivery
hermes cron pause/resume ID Control job state
hermes cron run ID Trigger on next tick
hermes cron remove ID Delete a job
hermes cron status Scheduler status
For bounded autonomous lab/orchestrator cron jobs that use file-based state, subagent lanes, artifact publishing, and status transitions (active โ complete/blocked/inactive), see references/autonomous-agent-lab-cron-cycle.md. A reusable verification script template lives at scripts/verify-completion-template.py.
For a worked example of evolving an autonomous lab into a config-driven, themeable, Docker-ready installable product, see references/autonomous-lab-product-architecture.md. For CI, integration testing, pluggable adapter architecture, bounded cycle orchestration, and post-productization patterns, see references/product-maturity-patterns.md.
For the final completion verification checklist โ the explicit audit pattern to run before marking status: complete on an installable-solution mission, see references/autonomous-lab-completion-verification.md.
For the reactivation protocol when a completed lab receives new P0 feedback or the user contradicts a completion claim, see references/autonomous-lab-reactivation-protocol.md.
For the config/CHANGELOG version drift pitfall that occurs when autonomous labs evolve over many cycles, and for the related source vs. published file drift problem where the live web root diverges from the project source, see references/autonomous-lab-version-drift.md.
For adding historical trend tracking (SQLite-backed agent status transitions + vanilla JS SVG sparklines) to an autonomous lab dashboard, see references/history-tracking-sparkline-pattern.md.
For reusable dashboard UX patterns (onboarding tours, data freshness badges, keyboard shortcuts, progressive disclosure inspectors, cross-linking between views), see references/dashboard-ux-patterns.md.
For the aggressive human-first inspector refinement โ when users report that details are hard to understand and the fix is to strip technical labels from the default view โ see references/progressive-disclosure-human-first.md.
For programmatic verification of CSS custom-property theme systems โ catching scoping bugs, confirming theme distinctness, and validating JS switching logic โ see references/theme-system-verification.md.
For Son's Discord-first autonomous experiments where a channel hosts a repeated multi-agent loop, use the Autonomous Discord Agent Lab pattern: create file-based durable state, a paused cron orchestrator delivered to discord:<channel_id>, then activate it from a user mission trigger. See references/autonomous-discord-agent-lab.md.
Webhooks
hermes webhook subscribe N Create route at /webhooks/<name>
hermes webhook list List subscriptions
hermes webhook remove NAME Remove a subscription
hermes webhook test NAME Send a test POST
Profiles
hermes profile list List all profiles
hermes profile create NAME Create (--clone, --clone-all, --clone-from)
hermes profile use NAME Set sticky default
hermes profile delete NAME Delete a profile
hermes profile show NAME Show details
hermes profile alias NAME Manage wrapper scripts
hermes profile rename A B Rename a profile
hermes profile export NAME Export to tar.gz
hermes profile import FILE Import from archive
Credential Pools
hermes auth add Interactive credential wizard
hermes auth list [PROVIDER] List pooled credentials
hermes auth remove P INDEX Remove by provider + index
hermes auth reset PROVIDER Clear exhaustion status
Other
hermes insights [--days N] Usage analytics
hermes update Update to latest version
hermes pairing list/approve/revoke DM authorization
hermes plugins list/install/remove Plugin management
hermes honcho setup/status Honcho memory integration (requires honcho plugin)
hermes memory setup/status/off Memory provider config
hermes completion bash|zsh Shell completions
hermes acp ACP server (IDE integration)
hermes claw migrate Migrate from OpenClaw
hermes uninstall Uninstall Hermes
---
Slash Commands (In-Session)
Type these during an interactive chat session. New commands land fairly
often; if something below looks stale, run /help in-session for the
authoritative list or see the [live slash commands reference](https://hermes-agent.nousresearch.com/docs/reference/slash-commands).
The registry of record is hermes_cli/commands.py โ every consumer
(autocomplete, Telegram menu, Slack mapping, /help) derives from it.
Session Control
/new (/reset) Fresh session
/clear Clear screen + new session (CLI)
/retry Resend last message
/undo Remove last exchange
/title [name] Name the session
/compress Manually compress context
/stop Kill background processes
/rollback [N] Restore filesystem checkpoint
/snapshot [sub] Create or restore state snapshots of Hermes config/state (CLI)
/background <prompt> Run prompt in background
/queue <prompt> Queue for next turn
/steer <prompt> Inject a message after the next tool call without interrupting
/agents (/tasks) Show active agents and running tasks
/resume [name] Resume a named session
/goal [text|sub] Set a standing goal Hermes works on across turns until achieved
(subcommands: status, pause, resume, clear)
/redraw Force a full UI repaint (CLI)
Configuration
/config Show config (CLI)
/model [name] Show or change model
/personality [name] Set personality
/reasoning [level] Set reasoning (none|minimal|low|medium|high|xhigh|show|hide)
/verbose Cycle: off โ new โ all โ verbose
/voice [on|off|tts] Voice mode
/yolo Toggle approval bypass
/busy [sub] Control what Enter does while Hermes is working (CLI)
(subcommands: queue, steer, interrupt, status)
/indicator [style] Pick the TUI busy-indicator style (CLI)
(styles: kaomoji, emoji, unicode, ascii)
/footer [on|off] Toggle gateway runtime-metadata footer on final replies
/skin [name] Change theme (CLI)
/statusbar Toggle status bar (CLI)
Tools & Skills
/tools Manage tools (CLI)
/toolsets List toolsets (CLI)
/skills Search/install skills (CLI)
/skill <name> Load a skill into session
/reload-skills Re-scan ~/.hermes/skills/ for added/removed skills
/reload Reload .env variables into the running session (CLI)
/reload-mcp Reload MCP servers
/cron Manage cron jobs (CLI)
/curator [sub] Background skill maintenance (status, run, pin, archive, โฆ)
/kanban [sub] Multi-profile collaboration board (tasks, links, comments)
/plugins List plugins (CLI)
Gateway
/approve Approve a pending command (gateway)
/deny Deny a pending command (gateway)
/restart Restart gateway (gateway)
/sethome Set current chat as home channel (gateway)
/update Update Hermes to latest (gateway)
/topic [sub] Enable or inspect Telegram DM topic sessions (gateway)
/platforms (/gateway) Show platform connection status (gateway)
Utility
/branch (/fork) Branch the current session
/fast Toggle priority/fast processing
/browser Open CDP browser connection
/history Show conversation history (CLI)
/save Save conversation to file (CLI)
/copy [N] Copy the last assistant response to clipboard (CLI)
/paste Attach clipboard image (CLI)
/image Attach local image file (CLI)
Info
/help Show commands
/commands [page] Browse all commands (gateway)
/usage Token usage
/insights [days] Usage analytics
/gquota Show Google Gemini Code Assist quota usage (CLI)
/status Session info (gateway)
/profile Active profile info
/debug Upload debug report (system info + logs) and get shareable links
Exit
/quit (/exit, /q) Exit CLI
---
Key Paths & Config
~/.hermes/config.yaml Main configuration
~/.hermes/.env API keys and secrets
$HERMES_HOME/skills/ Installed skills
~/.hermes/sessions/ Session transcripts
~/.hermes/logs/ Gateway and error logs
~/.hermes/auth.json OAuth tokens and credential pools
~/.hermes/hermes-agent/ Source code (if git-installed)
Profiles use ~/.hermes/profiles/<name>/ with the same layout.
Config Sections
Edit with hermes config edit or hermes config set section.key value.
| Section | Key options |
|---------|-------------|
| model | default, provider, base_url, api_key, context_length |
| agent | max_turns (90), tool_use_enforcement |
| terminal | backend (local/docker/ssh/modal), cwd, timeout (180) |
| compression | enabled, threshold (0.50), target_ratio (0.20) |
| display | skin, tool_progress, show_reasoning, show_cost |
| stt | enabled, provider (local/groq/openai/mistral) |
| tts | provider (edge/elevenlabs/openai/minimax/mistral/neutts) |
| memory | memory_enabled, user_profile_enabled, provider |
| security | tirith_enabled, website_blocklist |
| delegation | model, provider, base_url, api_key, max_iterations (50), reasoning_effort |
| checkpoints | enabled, max_snapshots (50) |
| fallback_model | provider, model, base_url, key_env |
Fallback Providers
Hermes can automatically fail over to a backup provider:model when the primary is unavailable. This is turn-scoped โ each new user message starts with the primary restored; fallback only activates mid-turn when the primary fails.
Configuration ( ~/.hermes/config.yaml):
fallback_model:
provider: opencode-go
model: kimi-k2.6
Or use the interactive manager:
hermes fallback add # interactive picker
hermes fallback list # show fallback chain
hermes fallback remove # remove by index
Legacy note: fallback_model (singular) is the legacy single-fallback key. fallback_providers (list) supports multiple ordered fallbacks. When both exist, fallback_providers takes priority.
Trigger conditions (after exhausting retries where applicable):
- Rate limits (HTTP 429)
- Server errors (HTTP 500, 502, 503)
- Auth failures (HTTP 401, 403) โ immediately
- Not found (HTTP 404) โ immediately
- Invalid / empty responses repeatedly
Supported providers include all standard providers (OpenRouter, Anthropic, OpenCode Go/ Zen, Kimi, etc.) plus custom endpoints with base_url + key_env. Full provider docs: https://hermes-agent.nousresearch.com/docs/integrations/providers
Limitations:
- Subagent delegation does not inherit fallback config
- Cron jobs do not use fallback (use per-job provider/model overrides)
- Auxiliary tasks (vision, compression, etc.) use their own
auxiliary.* provider chain
For a deep-dive with worked examples and model lists, see references/fallback-providers.md.
Full config reference: https://hermes-agent.nousresearch.com/docs/user-guide/configuration
Providers
20+ providers supported. Set via hermes model or hermes setup.
| Provider | Auth | Key env var |
|----------|------|-------------|
| OpenRouter | API key | OPENROUTER_API_KEY |
| Anthropic | API key | ANTHROPIC_API_KEY |
| Nous Portal | OAuth | hermes auth |
| OpenAI Codex | OAuth | hermes auth |
| GitHub Copilot | Token | COPILOT_GITHUB_TOKEN |
| Google Gemini | API key | GOOGLE_API_KEY or GEMINI_API_KEY |
| DeepSeek | API key | DEEPSEEK_API_KEY |
| xAI / Grok | API key | XAI_API_KEY |
| Hugging Face | Token | HF_TOKEN |
| Z.AI / GLM | API key | GLM_API_KEY |
| MiniMax | API key | MINIMAX_API_KEY |
| MiniMax CN | API key | MINIMAX_CN_API_KEY |
| Kimi / Moonshot | API key | KIMI_API_KEY |
| Alibaba / DashScope | API key | DASHSCOPE_API_KEY |
| Xiaomi MiMo | API key | XIAOMI_API_KEY |
| Kilo Code | API key | KILOCODE_API_KEY |
| AI Gateway (Vercel) | API key | AI_GATEWAY_API_KEY |
| OpenCode Zen | API key | OPENCODE_ZEN_API_KEY |
| OpenCode Go | API key | OPENCODE_GO_API_KEY |
| Qwen OAuth | OAuth | hermes auth add qwen-oauth |
| Custom endpoint | Config | model.base_url + model.api_key in config.yaml |
| GitHub Copilot ACP | External | COPILOT_CLI_PATH or Copilot CLI |
Full provider docs: https://hermes-agent.nousresearch.com/docs/integrations/providers
Toolsets
Enable/disable via hermes tools (interactive) or hermes tools enable/disable NAME.
| Toolset | What it provides |
|---------|-----------------|
| web | Web search and content extraction |
| search | Web search only (subset of web) |
| browser | Browser automation (Browserbase, Camofox, or local Chromium) |
| terminal | Shell commands and process management |
| file | File read/write/search/patch |
| code_execution | Sandboxed Python execution |
| vision | Image analysis |
| image_gen | AI image generation |
| video | Video analysis and generation |
| tts | Text-to-speech |
| skills | Skill browsing and management |
| memory | Persistent cross-session memory |
| session_search | Search past conversations |
| delegation | Subagent task delegation |
| cronjob | Scheduled task management |
| clarify | Ask user clarifying questions |
| messaging | Cross-platform message sending |
| todo | In-session task planning and tracking |
| kanban | Multi-agent work-queue tools (gated to workers) |
| debugging | Extra introspection/debug tools (off by default) |
| safe | Minimal, low-risk toolset for locked-down sessions |
| spotify | Spotify playback and playlist control |
| homeassistant | Smart home control (off by default) |
| discord | Discord integration tools |
| discord_admin | Discord admin/moderation tools |
| feishu_doc | Feishu (Lark) document tools |
| feishu_drive | Feishu (Lark) drive tools |
| yuanbao | Yuanbao integration tools |
| rl | Reinforcement learning tools (off by default) |
| moa | Mixture of Agents (off by default) |
Full enumeration lives in toolsets.py as the TOOLSETS dict; _HERMES_CORE_TOOLS is the default bundle most platforms inherit from.
Tool changes take effect on /reset (new session). They do NOT apply mid-conversation to preserve prompt caching.
---
Security & Privacy Toggles
Common "why is Hermes doing X to my output / tool calls / commands?" toggles โ and the exact commands to change them. Most of these need a fresh session (/reset in chat, or start a new hermes invocation) because they're read once at startup.
Secret redaction in tool output
Secret redaction is off by default โ tool output (terminal stdout, read_file, web content, subagent summaries, etc.) passes through unmodified. If the user wants Hermes to auto-mask strings that look like API keys, tokens, and secrets before they enter the conversation context and logs:
hermes config set security.redact_secrets true # enable globally
Restart required. security.redact_secrets is snapshotted at import time โ toggling it mid-session (e.g. via export HERMES_REDACT_SECRETS=true from a tool call) will NOT take effect for the running process. Tell the user to run hermes config set security.redact_secrets true in a terminal, then start a new session. This is deliberate โ it prevents an LLM from flipping the toggle on itself mid-task.
Disable again with:
hermes config set security.redact_secrets false
PII redaction in gateway messages
Separate from secret redaction. When enabled, the gateway hashes user IDs and strips phone numbers from the session context before it reaches the model:
hermes config set privacy.redact_pii true # enable
hermes config set privacy.redact_pii false # disable (default)
Command approval prompts
By default (approvals.mode: manual), Hermes prompts the user before running shell commands flagged as destructive (rm -rf, git reset --hard, etc.). The modes are:
manual โ always prompt (default)
smart โ use an auxiliary LLM to auto-approve low-risk commands, prompt on high-risk
off โ skip all approval prompts (equivalent to --yolo)
hermes config set approvals.mode smart # recommended middle ground
hermes config set approvals.mode off # bypass everything (not recommended)
Per-invocation bypass without changing config:
hermes --yolo โฆ
export HERMES_YOLO_MODE=1
Note: YOLO / approvals.mode: off does NOT turn off secret redaction. They are independent.
Shell hooks allowlist
Some shell-hook integrations require explicit allowlisting before they fire. Managed via ~/.hermes/shell-hooks-allowlist.json โ prompted interactively the first time a hook wants to run.
Disabling the web/browser/image-gen tools
To keep the model away from network or media tools entirely, open hermes tools and toggle per-platform. Takes effect on next session (/reset). See the Tools & Skills section above.
---
Voice & Transcription
STT (Voice โ Text)
Voice messages from messaging platforms are auto-transcribed.
Provider priority (auto-detected):
1. Local faster-whisper โ free, no API key: pip install faster-whisper
2. Groq Whisper โ free tier: set GROQ_API_KEY
3. OpenAI Whisper โ paid: set VOICE_TOOLS_OPENAI_KEY
4. Mistral Voxtral โ set MISTRAL_API_KEY
Config:
stt:
enabled: true
provider: local # local, groq, openai, mistral
local:
model: base # tiny, base, small, medium, large-v3
TTS (Text โ Voice)
| Provider | Env var | Free? |
|----------|---------|-------|
| Edge TTS | None | Yes (default) |
| ElevenLabs | ELEVENLABS_API_KEY | Free tier |
| OpenAI | VOICE_TOOLS_OPENAI_KEY | Paid |
| MiniMax | MINIMAX_API_KEY | Paid |
| Mistral (Voxtral) | MISTRAL_API_KEY | Paid |
| NeuTTS (local) | None (pip install neutts[all] + espeak-ng) | Free |
Voice commands: /voice on (voice-to-voice), /voice tts (always voice), /voice off.
---
Spawning Additional Hermes Instances
Run additional Hermes processes as fully independent subprocesses โ separate sessions, tools, and environments.
When to Use This vs delegate_task
| | delegate_task | Spawning hermes process |
|-|-----------------|--------------------------|
| Isolation | Separate conversation, shared process | Fully independent process |
| Duration | Minutes (bounded by parent loop) | Hours/days |
| Tool access | Subset of parent's tools | Full tool access |
| Interactive | No | Yes (PTY mode) |
| Use case | Quick parallel subtasks | Long autonomous missions |
One-Shot Mode
terminal(command="hermes chat -q 'Research GRPO papers and write summary to ~/research/grpo.md'", timeout=300)
Background for long tasks:
terminal(command="hermes chat -q 'Set up CI/CD for ~/myapp'", background=true)
Interactive PTY Mode (via tmux)
Hermes uses prompt_toolkit, which requires a real terminal. Use tmux for interactive spawning:
Start
terminal(command="tmux new-session -d -s agent1 -x 120 -y 40 'hermes'", timeout=10)
Wait for startup, then send a message
terminal(command="sleep 8 && tmux send-keys -t agent1 'Build a FastAPI auth service' Enter", timeout=15)
Read output
terminal(command="sleep 20 && tmux capture-pane -t agent1 -p", timeout=5)
Send follow-up
terminal(command="tmux send-keys -t agent1 'Add rate limiting middleware' Enter", timeout=5)
Exit
terminal(command="tmux send-keys -t agent1 '/exit' Enter && sleep 2 && tmux kill-session -t agent1", timeout=10)
Multi-Agent Coordination
Agent A: backend
terminal(command="tmux new-session -d -s backend -x 120 -y 40 'hermes -w'", timeout=10)
terminal(command="sleep 8 && tmux send-keys -t backend 'Build REST API for user management' Enter", timeout=15)
Agent B: frontend
terminal(command="tmux new-session -d -s frontend -x 120 -y 40 'hermes -w'", timeout=10)
terminal(command="sleep 8 && tmux send-keys -t frontend 'Build React dashboard for user management' Enter", timeout=15)
Check progress, relay context between them
terminal(command="tmux capture-pane -t backend -p | tail -30", timeout=5)
terminal(command="tmux send-keys -t frontend 'Here is the API schema from the backend agent: ...' Enter", timeout=5)
Session Resume
Resume most recent session
terminal(command="tmux new-session -d -s resumed 'hermes --continue'", timeout=10)
Resume specific session
terminal(command="tmux new-session -d -s resumed 'hermes --resume 20260225_143052_a1b2c3'", timeout=10)
Tips
- Prefer
delegate_task for quick subtasks โ less overhead than spawning a full process
- Use
-w (worktree mode) when spawning agents that edit code โ prevents git conflicts
- Set timeouts for one-shot mode โ complex tasks can take 5-10 minutes
- Use
hermes chat -q for fire-and-forget โ no PTY needed
- Use tmux for interactive sessions โ raw PTY mode has
\r vs \n issues with prompt_toolkit
- For scheduled tasks, use the
cronjob tool instead of spawning โ handles delivery and retry
---
Durable & Background Systems
Four systems run alongside the main conversation loop. Quick reference
here; full developer notes live in AGENTS.md, user-facing docs under
website/docs/user-guide/features/.
Delegation (delegate_task)
Synchronous subagent spawn โ the parent waits for the child's summary
before continuing its own loop. Isolated context + terminal session.
- Single:
delegate_task(goal, context, toolsets).
- Batch:
delegate_task(tasks=[{goal, ...}, ...]) runs children in
parallel, capped by delegation.max_concurrent_children (default 3).
- Roles:
leaf (default; cannot re-delegate) vs orchestrator
(can spawn its own workers, bounded by delegation.max_spawn_depth).
- Not durable. If the parent is interrupted, the child is
cancelled. For work that must outlive the turn, use cronjob or
terminal(background=True, notify_on_complete=True).
Config: delegation.* in config.yaml.
Tuning max_concurrent_children
Default is 3. Rule of thumb for raising it:
- Light tasks (web search, file grep): up to
6-8
- Medium tasks (code execution, browser):
4-5
- Heavy tasks (builds, large data):
2-3
- Actual bottleneck is usually the API rate limit, not local CPU/RAM. On a 10-core M4 with 16GB RAM, CPU is rarely the constraint.
- Formula: start at
5, raise only if profiling shows idle time between API responses.
Cron (scheduled jobs)
Durable scheduler โ cron/jobs.py + cron/scheduler.py. Drive it via
the cronjob tool, the hermes cron CLI (list, add, edit,
pause, resume, run, remove), or the /cron slash command.
- Schedules: duration (
"30m", "2h"), "every" phrase
( "every monday 9am"), 5-field cron ( "0 9 *"), or ISO timestamp.
- Per-job knobs:
skills, model/provider override, script
(pre-run data collection; no_agent=True makes the script the whole
job), context_from (chain job A's output into job B), workdir
(run in a specific dir with its AGENTS.md / CLAUDE.md loaded),
multi-platform delivery.
- Invariants: 3-minute hard interrupt per run,
.tick.lock file
prevents duplicate ticks across processes, cron sessions pass
skip_memory=True by default, and cron deliveries are framed with a
header/footer instead of being mirrored into the target gateway
session (keeps role alternation intact).
User docs: https://hermes-agent.nousresearch.com/docs/user-guide/features/cron
Curator (skill lifecycle)
Background maintenance for agent-created skills. Tracks usage, marks
idle skills stale, archives stale ones, keeps a pre-run tar.gz backup
so nothing is lost.
- CLI:
hermes curator <verb> โ status, run, pause, resume,
pin, unpin, archive, restore, prune, backup, rollback.
- Slash:
/curator <subcommand> mirrors the CLI.
- Scope: only touches skills with
created_by: "agent" provenance.
Bundled + hub-installed skills are off-limits. Never deletes โ
max destructive action is archive. Pinned skills are exempt from
every auto-transition and every LLM review pass.
- Telemetry: sidecar at
~/.hermes/skills/.usage.json holds
per-skill use_count, view_count, patch_count,
last_activity_at, state, pinned.
Config: curator.* (enabled, interval_hours, min_idle_hours,
stale_after_days, archive_after_days, backup.*).
User docs: https://hermes-agent.nousresearch.com/docs/user-guide/features/curator
Dreaming (periodic memory/skill consolidation)
For Anthropic-style "dreaming" workflows, combine cron + session_search + memory + skills + curator into a scheduled review loop. Start with a weekly, proposal-only report that audits recent sessions, repeated user corrections, memory conflicts, skill patch candidates, and cron/automation improvements. Do not automatically delete/replace memory or patch/archive skills unless the user explicitly approves the proposed changes. See references/weekly-dreaming-routine.md for the recommended prompt, report format, safety policy, and cron creation pattern.
Kanban (multi-agent work queue)
Durable SQLite board for multi-profile / multi-worker collaboration.
Users drive it via hermes kanban <verb>; dispatcher-spawned workers
see a focused kanban_* toolset gated by HERMES_KANBAN_TASK so the
schema footprint is zero outside worker processes.
- CLI verbs (common):
init, create, list (alias ls),
show, assign, link, unlink, comment, complete, block,
unblock, archive, tail. Less common: watch, stats, runs,
log, dispatch, daemon, gc.
- Worker toolset:
kanban_show, kanban_complete, kanban_block,
kanban_heartbeat, kanban_comment, kanban_create, kanban_link.
- Dispatcher runs inside the gateway by default
( kanban.dispatch_in_gateway: true) โ reclaims stale claims,
promotes ready tasks, atomically claims, spawns assigned profiles.
Auto-blocks a task after ~5 consecutive spawn failures.
- Isolation: board is the hard boundary (workers get
HERMES_KANBAN_BOARD pinned in env); tenant is a soft namespace
within a board for workspace-path + memory-key isolation.
User docs: https://hermes-agent.nousresearch.com/docs/user-guide/features/kanban
Log Relay (Hermes โ Discord)
A background Python script that tails ~/.hermes/logs/*.log and batches lines to a Discord channel. Includes session-ID extraction, rate-limit handling, and auto-restart via launchd/systemd. Useful for remote monitoring and audit trails.
- Reference:
references/discord-log-relay.md โ full setup, tuning, macOS/Linux service install, pitfalls.
- Template:
templates/discord-log-relay.py โ copy, set CHANNEL_ID, and deploy.
- Discord operations:
references/discord-operating-planes.md โ channel-purpose routing, periodic-summary vs Dreaming report formats, and safety/cost notes for Discord-first Hermes deployments.
Key pitfall: ask the user about batch frequency upfront rather than defaulting to real-time streaming. Most users prefer 10-minute or hourly batches. High-volume raw logs should be batched, summarized, or stored out-of-band; avoid Discord message storms during error loops.
Weekly Dreaming / Memory Curation
For long-running Hermes deployments, users may want an Anthropic-style "Dreaming" loop: a scheduled review that consolidates experience, proposes memory/skill/cron changes, and identifies what to keep, weaken, archive, or delete. Hermes has the building blocks (sessions, session_search, memory, skills, curator, cron), but the safe default is proposal mode:
1. Inspect recent usage and sessions.
2. Extract repeated success patterns, failure patterns, and user corrections.
3. Propose memory updates/removals without applying them silently.
4. Propose skill patches/archive candidates and cron/reporting improvements.
5. End with explicit approval checkboxes.
Do not silently rewrite or delete memory/skills from a Dreaming report unless the user explicitly authorized automatic application. See references/discord-operating-planes.md for a report template and routing heuristics.
---
Windows-Specific Quirks
Hermes runs natively on Windows (PowerShell, cmd, Windows Terminal, git-bash
mintty, VS Code integrated terminal). Most of it just works, but a handful
of differences between Win32 and POSIX have bitten us โ document new ones
here as you hit them so the next person (or the next session) doesn't
rediscover them from scratch.
Input / Keybindings
Alt+Enter doesn't insert a newline. Windows Terminal intercepts Alt+Enter
at the terminal layer to toggle fullscreen โ the keystroke never reaches
prompt_toolkit. Use Ctrl+Enter instead. Windows Terminal delivers
Ctrl+Enter as LF ( c-j), distinct from plain Enter ( c-m / CR), and the
CLI binds c-j to newline insertion on win32 only (see
_bind_prompt_submit_keys + the Windows-only c-j binding in cli.py).
Side effect: the raw Ctrl+J keystroke also inserts a newline on Windows โ
unavoidable, because Windows Terminal collapses Ctrl+Enter and Ctrl+J to
the same keycode at the Win32 console API layer. No conflicting binding
existed for Ctrl+J on Windows, so this is a harmless side effect.
mintty / git-bash behaves the same (fullscreen on Alt+Enter) unless you
disable Alt+Fn shortcuts in Options โ Keys. Easier to just use Ctrl+Enter.
Diagnosing keybindings. Run python scripts/keystroke_diagnostic.py
(repo root) to see exactly how prompt_toolkit identifies each keystroke
in the current terminal. Answers questions like "does Shift+Enter come
through as a distinct key?" (almost never โ most terminals collapse it
to plain Enter) or "what byte sequence is my terminal sending for
Ctrl+Enter?" This is how the Ctrl+Enter = c-j fact was established.
Config / Files
HTTP 400 "No models provided" on first run. config.yaml was saved
with a UTF-8 BOM (common when Windows apps write it). Re-save as UTF-8
without BOM. hermes config edit writes without BOM; manual edits in
Notepad are the usual culprit.
execute_code / Sandbox
WinError 10106 ("The requested service provider could not be loaded
or initialized") from the sandbox child process โ it can't create an
AF_INET socket, so the loopback-TCP RPC fallback fails before
connect(). Root cause is usually not a broken Winsock LSP; it's
Hermes's own env scrubber dropping SYSTEMROOT / WINDIR / COMSPEC
from the child env. Python's socket module needs SYSTEMROOT to locate
mswsock.dll. Fixed via the _WINDOWS_ESSENTIAL_ENV_VARS allowlist in
tools/code_execution_tool.py. If you still hit it, echo os.environ
inside an execute_code block to confirm SYSTEMROOT is set. Full
diagnostic recipe in references/execute-code-sandbox-env-windows.md.
Testing / Contributing
scripts/run_tests.sh doesn't work as-is on Windows โ it looks for
POSIX venv layouts ( .venv/bin/activate). The Hermes-installed venv at
venv/Scripts/ has no pip or pytest either (stripped for install size).
Workaround: install pytest + pytest-xdist + pyyaml into a system Python
3.11 user site, then invoke pytest directly with PYTHONPATH set:
"/c/Program Files/Python311/python" -m pip install --user pytest pytest-xdist pyyaml
export PYTHONPATH="$(pwd)"
"/c/Program Files/Python311/python" -m pytest tests/foo/test_bar.py -v --tb=short -n 0
Use -n 0, not -n 4 โ pyproject.toml's default addopts already
includes -n, and the wrapper's CI-parity guarantees don't apply off POSIX.
POSIX-only tests need skip guards. Common markers already in the codebase:
- Symlinks โ elevated privileges on Windows
0o600 file modes โ POSIX mode bits not enforced on NTFS by default
signal.SIGALRM โ Unix-only (see tests/conftest.py::_enforce_test_timeout)
- Winsock / Windows-specific regressions โ
@pytest.mark.skipif(sys.platform != "win32", ...)
Use the existing skip-pattern style (sys.platform == "win32" or
sys.platform.startswith("win")) to stay consistent with the rest of the
suite.
Path / Filesystem
Line endings. Git may warn LF will be replaced by CRLF the next time
Git touches it. Cosmetic โ the repo's .gitattributes normalizes. Don't
let editors auto-convert committed POSIX-newline files to CRLF.
Forward slashes work almost everywhere. C:/Users/... is accepted by
every Hermes tool and most Windows APIs. Prefer forward slashes in code
and logs โ avoids shell-escaping backslashes in bash.
---
Troubleshooting
Voice not working
1. Check stt.enabled: true in config.yaml
2. Verify provider: pip install faster-whisper or set API key
3. In gateway: /restart. In CLI: exit and relaunch.
Tool not available
1. hermes tools โ check if toolset is enabled for your platform
2. Some tools need env vars (check .env)
3. /reset after enabling tools
Model/provider issues
1. hermes doctor โ check config and dependencies
2. hermes auth add <provider> โ re-authenticate OAuth providers (use --type oauth)
3. Check .env has the right API key
4. Copilot 403: gh auth login tokens do NOT work for Copilot API. You must use the Copilot-specific OAuth device code flow via hermes model โ GitHub Copilot.
Changes not taking effect
- Tools/skills:
/reset starts a new session with updated toolset
- Config changes: In gateway:
/restart. In CLI: exit and relaunch.
- Code changes: Restart the CLI or gateway process
Deployed web dashboard shows stale CSS or theme changes
- Browser cache: Add
?v=N cache-busting query strings to CSS/JS/theme links in HTML.
- Service Worker cache: Bump
CACHE_NAME in sw.js to invalidate old shell caches.
- Data freshness: Use
fetch(url, {cache:'no-store'}) for live JSON feeds.
- See
references/static-site-cache-invalidation.md for the full diagnostic recipe.
Dashboard inspector feels too technical
- The default inspector view should contain only plain-language sentences: headline, "what they're doing now", "why it matters", and a silent visual progress bar (no text label).
- Move all technical fields (source IDs, confidence scores, progress labels, status slugs, badges) behind a "Show technical details" toggle.
- If users say "details are hard to understand," the fix is to remove more fields from the default view, not to add explanations. Explanations of technical fields are still technical.
- See
references/progressive-disclosure-human-first.md for the aggressive simplification pattern.
Skills not showing
1. hermes skills list โ verify installed
2. hermes skills config โ check platform enablement
3. Load explicitly: /skill name or hermes -s name
Gateway issues
Check logs first:
grep -i "failed to send\|error" ~/.hermes/logs/gateway.log | tail -20
Common gateway problems:
- Gateway dies on SSH logout: Enable linger:
sudo loginctl enable-linger $USER
- Gateway dies on WSL2 close: WSL2 requires
systemd=true in /etc/wsl.conf for systemd services to work. Without it, gateway falls back to nohup (dies when session closes).
- Gateway crash loop: Reset the failed state:
systemctl --user reset-failed hermes-gateway
- macOS: bot shows offline after idle time: The gateway runs as a user agent (
LimitLoadToSessionType=Aqua), so macOS suspends it when the system sleeps. The platform websocket drops and the bot appears offline until the network returns. Fix: keep the Mac awake (System Settings -> Energy -> Prevent automatic sleeping, or caffeinate -d -i -s -u &). Low Power Mode makes this worse, not better. See references/macos-gateway-sleep-disconnect.md for the full diagnostic recipe.
Platform-specific issues
- Discord bot silent: Must enable Message Content Intent in Bot โ Privileged Gateway Intents. See full Discord setup reference:
references/discord-gateway-setup.md.
- Slack bot only works in DMs: Must subscribe to
message.channels event. Without it, the bot ignores public channels.
- Windows-specific issues (
Alt+Enter newline, WinError 10106, UTF-8 BOM config, test suite, line endings): see the dedicated Windows-Specific Quirks section above.
Auxiliary models not working
If auxiliary tasks (vision, compression, session_search) fail silently, the auto provider can't find a backend. Either set OPENROUTER_API_KEY or GOOGLE_API_KEY, or explicitly configure each auxiliary task's provider:
hermes config set auxiliary.vision.provider <your_provider>
hermes config set auxiliary.vision.model <model_name>
Full system auth provisioning
For a one-shot workflow to maximize available credentials โ installing gh, generating SSH keys, configuring git, enabling all Hermes toolsets, and auditing current auth state โ see references/system-auth-setup.md.
Editing large files with patch
When a file is read with read_file(offset=...) (pagination), the tool warns that the view is partial. If you attempt patch without re-reading the full file first, you will likely hit non-unique match errors or corrupt the file. Fix: always call read_file without offset to load the whole file before patching. For append-only updates (e.g., adding a cycle log entry to state.md), do not use terminal(command="cat >> file << 'EOF'...EOF") โ the terminal tool on macOS/Linux misinterprets heredoc << as backgrounding and fails. Instead, write a short Python script via write_file and execute it with terminal(command="python3 /tmp/script.py"). See references/terminal-heredoc-workaround.md for the full pattern.
Sibling subagent file overwrites
When multiple subagents are running in parallel (e.g. via delegate_task batch mode or kanban worker lanes), a file may be modified by one subagent while another is about to write to it. If you use write_file or patch on a file that was last read before a sibling subagent modified it, your write may silently truncate or revert the sibling's changes. The tool may show a warning like "this file was modified by sibling subagent X but this agent never read it."
Fix:
1. Heed the warning. If the tool reports a sibling modification, re-read the file with read_file before writing.
2. Prefer patch over write_file for partial updates โ patch only changes the matched region and is less likely to wipe unrelated content.
3. If the file is already published/deployed, and the local working copy gets corrupted, recover from the published copy:
cp ~/hermes-web/agent-pets/css/dashboard.css ~/.hermes/autonomous-agent-lab/pixel-pet-ops/web/css/dashboard.css
4. For append-only updates, write a small Python script and execute it rather than using write_file on the whole file.
Prevention: In kanban/multi-agent workflows, assign file-level ownership so only one worker touches each file. If parallel workers must edit the same file, have them write to separate temp files and let the orchestrator merge.
---
Windows-Specific Quirks
| Looking for... | Location |
|----------------|----------|
| Config options | hermes config edit or [Configuration docs](https://hermes-agent.nousresearch.com/docs/user-guide/configuration) |
| Available tools | hermes tools list or [Tools reference](https://hermes-agent.nousresearch.com/docs/reference/tools-reference) |
| Slash commands | /help in session or [Slash commands reference](https://hermes-agent.nousresearch.com/docs/reference/slash-commands) |
| Skills catalog | hermes skills browse or [Skills catalog](https://hermes-agent.nousresearch.com/docs/reference/skills-catalog) |
| Provider setup | hermes model or [Providers guide](https://hermes-agent.nousresearch.com/docs/integrations/providers) |
| Platform setup | hermes gateway setup or [Messaging docs](https://hermes-agent.nousresearch.com/docs/user-guide/messaging/) |
| MCP servers | hermes mcp list or [MCP guide](https://hermes-agent.nousresearch.com/docs/user-guide/features/mcp) |
| Profiles | hermes profile list or [Profiles docs](https://hermes-agent.nousresearch.com/docs/user-guide/profiles) |
| Cron jobs | hermes cron list or [Cron docs](https://hermes-agent.nousresearch.com/docs/user-guide/features/cron) |
| Memory | hermes memory status or [Memory docs](https://hermes-agent.nousresearch.com/docs/user-guide/features/memory) |
| Env variables | hermes config env-path or [Env vars reference](https://hermes-agent.nousresearch.com/docs/reference/environment-variables) |
| CLI commands | hermes --help or [CLI reference](https://hermes-agent.nousresearch.com/docs/reference/cli-commands) |
| Gateway logs | ~/.hermes/logs/gateway.log |
| Session files | ~/.hermes/sessions/ or hermes sessions browse |
| Source code | ~/.hermes/hermes-agent/ |
---
Contributor Quick Reference
For occasional contributors and PR authors. Full developer docs: https://hermes-agent.nousresearch.com/docs/developer-guide/
Project Layout
hermes-agent/
โโโ run_agent.py # AIAgent โ core conversation loop
โโโ model_tools.py # Tool discovery and dispatch
โโโ toolsets.py # Toolset definitions
โโโ cli.py # Interactive CLI (HermesCLI)
โโโ hermes_state.py # SQLite session store
โโโ agent/ # Prompt builder, context compression, memory, model routing, credential pooling, skill dispatch
โโโ hermes_cli/ # CLI subcommands, config, setup, commands
โ โโโ commands.py # Slash command registry (CommandDef)
โ โโโ config.py # DEFAULT_CONFIG, env var definitions
โ โโโ main.py # CLI entry point and argparse
โโโ tools/ # One file per tool
โ โโโ registry.py # Central tool registry
โโโ gateway/ # Messaging gateway
โ โโโ platforms/ # Platform adapters (telegram, discord, etc.)
โโโ cron/ # Job scheduler
โโโ tests/ # ~3000 pytest tests
โโโ website/ # Docusaurus docs site
Config: ~/.hermes/config.yaml (settings), ~/.hermes/.env (API keys).
Adding a Tool (3 files)
1. Create tools/your_tool.py:
import json, os
from tools.registry import registry
def check_requirements() -> bool:
return bool(os.getenv("EXAMPLE_API_KEY"))
def example_tool(param: str, task_id: str = None) -> str:
return json.dumps({"success": True, "data": "..."})
registry.register(
name="example_tool",
toolset="example",
schema={"name": "example_tool", "description": "...", "parameters": {...}},
handler=lambda args, **kw: example_tool(
param=args.get("param", ""), task_id=kw.get("task_id")),
check_fn=check_requirements,
requires_env=["EXAMPLE_API_KEY"],
)
2. Add to toolsets.py โ _HERMES_CORE_TOOLS list.
Auto-discovery: any tools/*.py file with a top-level registry.register() call is imported automatically โ no manual list needed.
All handlers must return JSON strings. Use get_hermes_home() for paths, never hardcode ~/.hermes.
Adding a Slash Command
1. Add CommandDef to COMMAND_REGISTRY in hermes_cli/commands.py
2. Add handler in cli.py โ process_command()
3. (Optional) Add gateway handler in gateway/run.py
All consumers (help text, autocomplete, Telegram menu, Slack mapping) derive from the central registry automatically.
Agent Loop (High Level)
run_conversation():
1. Build system prompt
2. Loop while iterations < max:
a. Call LLM (OpenAI-format messages + tool schemas)
b. If tool_calls โ dispatch each via handle_function_call() โ append results โ continue
c. If text response โ return
3. Context compression triggers automatically near token limit
Testing
python -m pytest tests/ -o 'addopts=' -q # Full suite
python -m pytest tests/tools/ -q # Specific area
- Tests auto-redirect
HERMES_HOME to temp dirs โ never touch real ~/.hermes/
- Run full suite before pushing any change
- Use
-o 'addopts=' to clear any baked-in pytest flags
Windows contributors: scripts/run_tests.sh currently looks for POSIX venvs ( .venv/bin/activate / venv/bin/activate) and will error out on Windows where the layout is venv/Scripts/activate + python.exe. The Hermes-installed venv at venv/Scripts/ also has no pip or pytest โ it's stripped for end-user install size. Workaround: install pytest + pytest-xdist + pyyaml into a system Python 3.11 user site ( /c/Program Files/Python311/python -m pip install --user pytest pytest-xdist pyyaml), then run tests directly:
export PYTHONPATH="$(pwd)"
"/c/Program Files/Python311/python" -m pytest tests/tools/test_foo.py -v --tb=short -n 0
Use -n 0 (not -n 4) because pyproject.toml's default addopts already includes -n, and the wrapper's CI-parity story doesn't apply off-POSIX.
Cross-platform test guards: tests that use POSIX-only syscalls need a skip marker. Common ones already in the codebase:
- Symlink creation โ
@pytest.mark.skipif(sys.platform == "win32", reason="Symlinks require elevated privileges on Windows") (see tests/cron/test_cron_script.py)
- POSIX file modes (0o600, etc.) โ
@pytest.mark.skipif(sys.platform.startswith("win"), reason="POSIX mode bits not enforced on Windows") (see tests/hermes_cli/test_auth_toctou_file_modes.py)
signal.SIGALRM โ Unix-only (see tests/conftest.py::_enforce_test_timeout)
- Live Winsock / Windows-specific regression tests โ
@pytest.mark.skipif(sys.platform != "win32", reason="Windows-specific regression")
Monkeypatching sys.platform is not enough when the code under test also calls platform.system() / platform.release() / platform.mac_ver(). Those functions re-read the real OS independently, so a test that sets sys.platform = "linux" on a Windows runner will still see platform.system() == "Windows" and route through the Windows branch. Patch all three together:
monkeypatch.setattr(sys, "platform", "linux")
monkeypatch.setattr(platform, "system", lambda: "Linux")
monkeypatch.setattr(platform, "release", lambda: "6.8.0-generic")
See tests/agent/test_prompt_builder.py::TestEnvironmentHints for a worked example.
Extending the system prompt's execution-environment block
Factual guidance about the host OS, user home, cwd, terminal backend, and shell (bash vs. PowerShell on Windows) is emitted from agent/prompt_builder.py::build_environment_hints(). This is also where the WSL hint and per-backend probe logic live. The convention:
- Local terminal backend โ emit host info (OS,
$HOME, cwd) + Windows-specific notes (hostname โ username, terminal uses bash not PowerShell).
- Remote terminal backend (anything in
_REMOTE_TERMINAL_BACKENDS: docker, singularity, modal, daytona, ssh, vercel_sandbox, managed_modal) โ suppress host info entirely and describe only the backend. A live uname/whoami/pwd probe runs inside the backend via tools.environments.get_environment(...).execute(...), cached per process in _BACKEND_PROBE_CACHE, with a static fallback if the probe times out.
- Key fact for prompt authoring: when
TERMINAL_ENV != "local", every file tool (read_file, write_file, patch, search_files) runs inside the backend container, not on the host. The system prompt must never describe the host in that case โ the agent can't touch it.
Full design notes, the exact emitted strings, and testing pitfalls:
references/prompt-builder-environment-hints.md.
Refactor-safety pattern (POSIX-equivalence guard): when you extract inline logic into a helper that adds Windows/platform-specific behavior, keep a _legacy_<name> oracle function in the test file that's a verbatim copy of the old code, then parametrize-diff against it. Example: tests/tools/test_code_execution_windows_env.py::TestPosixEquivalence. This locks in the invariant that POSIX behavior is bit-for-bit identical and makes any future drift fail loudly with a clear diff.
Commit Conventions
type: concise subject line
Optional body.
Types: fix:, feat:, refactor:, docs:, chore:
Key Rules
- Never break prompt caching โ don't change context, tools, or system prompt mid-conversation
- Message role alternation โ never two assistant or two user messages in a row
- Use
get_hermes_home() from hermes_constants for all paths (profile-safe)
- Config values go in
config.yaml, secrets go in .env
- New tools need a
check_fn so they only appear when requirements are met
[IMPORTANT: The user has invoked the "kanban-orchestrator" skill, indicating they want you to follow its instructions. The full skill content is loaded below.]
---
name: kanban-orchestrator
description: Decomposition playbook + anti-temptation rules for an orchestrator profile routing work through Kanban. The "don't do the work yourself" rule and the basic lifecycle are auto-injected into every kanban worker's system prompt; this skill is the deeper playbook when you're specifically playing the orchestrator role.
version: 3.0.0
platforms: [linux, macos, windows]
metadata:
hermes:
tags: [kanban, multi-agent, orchestration, routing]
related_skills: [kanban-worker]
---
Kanban Orchestrator โ Decomposition Playbook
> The core worker lifecycle (including the kanban_create fan-out pattern and the "decompose, don't execute" rule) is auto-injected into every kanban process via the KANBAN_GUIDANCE system-prompt block. This skill is the deeper playbook when you're an orchestrator profile whose whole job is routing.
Profiles are user-configured โ not a fixed roster
Hermes setups vary widely. Some users run a single profile that does everything; some run a small fleet (docker-worker, cron-worker); some run a curated specialist team they've named themselves. There is no default specialist roster โ the orchestrator skill does not know what profiles exist on this machine.
Before fanning out, you must ground the decomposition in the profiles that actually exist. The dispatcher silently fails to spawn unknown assignee names โ it doesn't autocorrect, doesn't suggest, doesn't fall back. So a card assigned to researcher on a setup that only has docker-worker just sits in ready forever.
Step 0: discover available profiles before planning.
Use one of these:
hermes profile list โ prints the table of profiles configured on this machine. Run it through your terminal tool if you have one; otherwise ask the user.
kanban_list(assignee="<some-name>") โ sanity-check a single name. Returns an empty list (rather than an error) for an unknown assignee, so this only confirms a name you're already considering.
- Just ask the user. "What profiles do you have set up?" is a fine first turn when the goal needs more than one specialist.
Cache the result in your working memory for the rest of the conversation. Re-asking every turn wastes a tool call.
When to use the board (vs. just doing the work)
Create Kanban tasks when any of these are true:
1. Multiple specialists are needed. Research + analysis + writing is three profiles.
2. The work should survive a crash or restart. Long-running, recurring, or important.
3. The user might want to interject. Human-in-the-loop at any step.
4. Multiple subtasks can run in parallel. Fan-out for speed.
5. Review / iteration is expected. A reviewer profile loops on drafter output.
6. The audit trail matters. Board rows persist in SQLite forever.
If none of those apply โ it's a small one-shot reasoning task โ use delegate_task instead or answer the user directly.
The anti-temptation rules
Your job description says "route, don't execute." The rules that enforce that:
- Do not execute the work yourself. Your restricted toolset usually doesn't even include terminal/file/code/web for implementation. If you find yourself "just fixing this quickly" โ stop and create a task for the right specialist.
- For any concrete task, create a Kanban task and assign it. Every single time.
- Split multi-lane requests before creating cards. A user prompt can contain several independent workstreams. Extract those lanes first, then create one card per lane instead of bundling unrelated work into a single implementer card.
- Run independent lanes in parallel. If two cards do not need each other's output, leave them unlinked so the dispatcher can fan them out. Link only true data dependencies.
- If no specialist fits the available profiles, ask the user which profile to create or which existing profile to use. Do not invent profile names; the dispatcher will silently drop unknown assignees.
- Decompose, route, and summarize โ that's the whole job.
Exception: micro-UI polish cycles
There is one narrow exception where the orchestrator may execute directly instead of creating Kanban cards: tiny UI-only polish cycles (e.g., adding a CSS class, a theme preview dot, a hover state, a cross-link, or a HUD button) that are purely presentational, require no cross-file logic changes, and fit comfortably inside a single bounded cycle with no need for review or parallel work. If the change is limited to HTML/CSS/JS cosmetics, no other profile has a stake in it, and the user did not ask for a design review, the orchestrator should just edit and publish rather than paying the kanban-overhead tax. This exception does NOT apply to architecture changes, adapter logic, plugin interfaces, or anything that touches the data layer.
Decomposition playbook
Step 1 โ Understand the goal
Ask clarifying questions if the goal is ambiguous. Cheap to ask; expensive to spawn the wrong fleet.
Step 2 โ Sketch the task graph
Before creating anything, draft the graph out loud (in your response to the user). Treat every concrete workstream as a candidate card:
1. Extract the lanes from the request.
2. Map each lane to one of the profiles you discovered in Step 0. If a lane doesn't fit any existing profile, ask the user which to use or create.
3. Decide whether each lane is independent or gated by another lane.
4. Create independent lanes as parallel cards with no parent links.
5. Create synthesis/review/integration cards with parent links to the lanes they depend on.
Examples of prompts that should fan out (using placeholder profile names โ substitute whatever exists on the user's setup):
- "Build an app" โ one card to a design-oriented profile for product/UI direction, one or two cards to engineering profiles for implementation, plus a later integration/review card if the user has a reviewer profile.
- "Fix blockers and check model variants" โ one implementation card for the blocker fixes plus one discovery/research card for config/source verification. A final reviewer card can depend on both.
- "Research docs and implement" โ a docs-research card can run in parallel with a codebase-discovery card; implementation waits only if it truly needs those findings.
- "Analyze this screenshot and find the related code" โ one card to a vision-capable profile for the visual analysis while another searches the codebase.
Words like "also," "finally," or "and" do not automatically imply a dependency. They often mean "make sure this is covered before reporting back." Only link tasks when one card cannot start until another card's output exists.
Show the graph to the user before creating cards. Let them correct it โ including which actual profile name should own each lane.
Step 3 โ Create tasks and link
Use the profile names from Step 0. The example below uses placeholders <profile-A>, <profile-B>, <profile-C> โ replace them with what the user actually has.
t1 = kanban_create(
title="research: Postgres cost vs current",
assignee="<profile-A>", # whichever profile handles research on this setup
body="Compare estimated infrastructure costs, migration costs, and ongoing ops costs over a 3-year window. Sources: AWS/GCP pricing, team time estimates, current Postgres bills from peers.",
tenant=os.environ.get("HERMES_TENANT"),
)["task_id"]
t2 = kanban_create(
title="research: Postgres performance vs current",
assignee="<profile-A>", # same profile, run in parallel
body="Compare query latency, throughput, and scaling characteristics at our expected data volume (~500GB, 10k QPS peak). Sources: benchmark papers, public case studies, pgbench results if easy.",
)["task_id"]
t3 = kanban_create(
title="synthesize migration recommendation",
assignee="<profile-B>", # whichever profile does synthesis/analysis
body="Read the findings from T1 (cost) and T2 (performance). Produce a 1-page recommendation with explicit trade-offs and a go/no-go call.",
parents=[t1, t2],
)["task_id"]
t4 = kanban_create(
title="draft decision memo",
assignee="<profile-C>", # whichever profile drafts user-facing prose
body="Turn the analyst's recommendation into a 2-page memo for the CTO. Match the tone of previous decision memos in the team's knowledge base.",
parents=[t3],
)["task_id"]
parents=[...] gates promotion โ children stay in todo until every parent reaches done, then auto-promote to ready. No manual coordination needed; the dispatcher and dependency engine handle it.
Step 4 โ Complete your own task
If you were spawned as a task yourself (e.g. a planner profile was assigned T0: "investigate Postgres migration"), mark it done with a summary of what you created:
kanban_complete(
summary="decomposed into T1-T4: 2 research lanes in parallel, 1 synthesis on their outputs, 1 prose draft on the recommendation",
metadata={
"task_graph": {
"T1": {"assignee": "<profile-A>", "parents": []},
"T2": {"assignee": "<profile-A>", "parents": []},
"T3": {"assignee": "<profile-B>", "parents": ["T1", "T2"]},
"T4": {"assignee": "<profile-C>", "parents": ["T3"]},
},
},
)
Step 5 โ Report back to the user
Tell them what you created in plain prose, naming the actual profiles you used:
> I've queued 4 tasks:
> - T1 (<profile-A>): cost comparison
> - T2 (<profile-A>): performance comparison, in parallel with T1
> - T3 (<profile-B>): synthesizes T1 + T2 into a recommendation
> - T4 (<profile-C>): turns T3 into a CTO memo
>
> The dispatcher will pick up T1 and T2 now. T3 starts when both finish. You'll get a gateway ping when T4 completes. Use the dashboard or hermes kanban tail <id> to follow along.
Common patterns
Fan-out + fan-in (research โ synthesize): N research-style cards with no parents, one synthesis card with all of them as parents.
Parallel implementation + validation: one implementer card makes the change while one explorer/researcher card verifies config, docs, or source mapping. A reviewer card can depend on both. Do not make the implementer own unrelated verification just because the user mentioned both in one sentence.
Pipeline with gates: planner โ implementer โ reviewer. Each stage's parents=[previous_task]. Reviewer blocks or completes; if reviewer blocks, the operator unblocks with feedback and respawns.
Same-profile queue: N tasks, all assigned to the same profile, no dependencies between them. Dispatcher serializes โ that profile processes them in priority order, accumulating experience in its own memory.
Parallel UI/frontend lanes: When the goal touches multiple independent HTML/CSS/JS files (e.g., a dashboard page and a 2D gather view), fan out to separate subagents per file. Each lane edits its own file, then the orchestrator integrates, fixes cross-file references (theme paths, shared JSON endpoints), and publishes. This avoids merge conflicts in single-file HTML dashboards and keeps each subagent's context focused. See references/parallel-ui-lanes-and-publishing.md for the post-subagent integration checklist and rsync safety notes.
Human-in-the-loop: Any task can kanban_block() to wait for input. Dispatcher respawns after /unblock. The comment thread carries the full context.
Pitfalls
Inventing profile names that don't exist. The dispatcher silently fails to spawn unknown assignees โ the card just sits in ready forever. Always assign to a profile from your Step 0 discovery; ask the user if you're unsure.
Bundling independent lanes into one card. If the user asks for two independent outcomes, create two cards. Example: "fix blockers and check model variants" is not one fixer task; create a fixer/engineer card for the fixes and an explorer/researcher card for the variant check, then optionally gate review on both.
Over-linking because of wording. "Finally check X" may still be parallel with implementation if X is static config, docs, or source discovery. Link it after implementation only when the check depends on the implementation result.
Forgetting dependency links. If the task graph says research -> implement -> review, do not create all tasks as independent ready cards. Use parent links so implement/review cannot run before their inputs exist.
Reassignment vs. new task. If a reviewer blocks with "needs changes," create a NEW task linked from the reviewer's task โ don't re-run the same task with a stern look. The new task is assigned to the original implementer profile.
Argument order for links. kanban_link(parent_id=..., child_id=...) โ parent first. Mixing them up demotes the wrong task to todo.
Ignoring explicit user feedback to keep building infrastructure. When the user says a specific UX issue (legibility, theme switching, movement density) is "immediate priority," treat it as P0 and route it before deeper packaging/architecture work. Infrastructure polish feels productive, but shipping user-visible fixes is what matters. Create cards for the UX feedback first, then resume infrastructure lanes.
Treating status: complete as immutable when user feedback says otherwise. A state.md that says status: complete does not override a user's report that a completion criterion is actually broken. If the user says "theme switching is not working" and the Final Completion Condition requires "working UI theme switcher," the mission is not complete. Reactivate immediately: set status: active, append a reactivation cycle log, and fix the issue. Do not burn cycles on post-complete verification while the user is reporting active defects.
Don't pre-create the whole graph if the shape depends on intermediate findings. If T3's structure depends on what T1 and T2 find, let T3 exist as a "synthesize findings" task whose own first step is to read parent handoffs and plan the rest. Orchestrators can spawn orchestrators.
Tenant inheritance. If HERMES_TENANT is set in your env, pass tenant=os.environ.get("HERMES_TENANT") on every kanban_create call so child tasks stay in the same namespace.
Verifying cross-file references after directory reorganization. When subagents edit HTML/CSS/JS files and the directory structure shifts (e.g., moving files from root into web/dashboard/ and web/gather/), relative asset paths ( themes/default/theme.css, ./ops-data.json) often break. After subagents finish, the orchestrator must grep for href= and src= in moved files and fix relative paths before publishing. Subagents don't know the final publish layout โ the orchestrator does.
Destructive sync wipes needed files. Commands like rsync -av --delete will delete destination files that aren't in the source list. If you publish a directory tree piecemeal (e.g., copy web/dashboard/ first, then web/gather/ separately), --delete on the first rsync will erase the gather files before the second rsync runs. Either list all source paths in a single rsync invocation, or omit --delete and use cp -r / rsync -av without deletion when doing staged copies.
Recovering stuck workers
When a worker profile keeps crashing, hallucinating, or getting blocked by its own mistakes (usually: wrong model, missing skill, broken credential), the kanban dashboard flags the task with a โ badge and opens a Recovery section in the drawer. Three primary actions:
1. Reclaim (or hermes kanban reclaim <task_id>) โ abort the running worker immediately and reset the task to ready. The existing claim TTL is ~15 min; this is the fast path out.
2. Reassign (or hermes kanban reassign <task_id> <new-profile> --reclaim) โ switch the task to a different profile (one that exists on this setup) and let the dispatcher pick it up with a fresh worker.
3. Change profile model โ the dashboard prints a copy-paste hint for hermes -p <profile> model since profile config lives on disk; edit it in a terminal, then Reclaim to retry with the new model.
Hallucination warnings appear on tasks where a worker's kanban_complete(created_cards=[...]) claim included card ids that don't exist or weren't created by the worker's profile (the gate blocks the completion), or where the free-form summary references t_<hex> ids that don't resolve (advisory prose scan, non-blocking). Both produce audit events that persist even after recovery actions โ the trail stays for debugging.
The user has provided the following instruction alongside the skill invocation: [IMPORTANT: You are running as a scheduled cron job. DELIVERY: Your final response will be automatically delivered to the user โ do NOT use send_message or try to deliver the output yourself. Just produce your report/output as your final response and the system handles the rest. SILENT: If there is genuinely nothing new to report, respond with exactly "[SILENT]" (nothing else) to suppress delivery. Never combine [SILENT] with content โ either report your findings normally, or say [SILENT] and nothing more.]
You are the 15-minute Orchestrator for Son's Autonomous Agent Lab v1, reporting to Discord channel ID 1505805763824586952.
Durable state path: /Users/jooho-hermes/.hermes/autonomous-agent-lab/state.md
Working directory for experiment artifacts: /Users/jooho-hermes/.hermes/autonomous-agent-lab/
Preferred published web root: /Users/jooho-hermes/hermes-web/agent-pets/
Top-level directive from Son:
- The project has evolved from a personal dashboard into an INSTALLABLE PRODUCT that external Hermes users can deploy.
- The final target is a self-contained, configurable, publishable solution: "Hermes Pixel Pet Ops Office".
- Do NOT shrink the mission into a small static MVP and autonomously stop.
- The Gather.town-style 2D spatial office is a first-class feature, not a side page.
Latest UX feedback from Son (treat as immediate priority before deeper packaging work):
- Details are hard for a human to understand. Add human-first summaries, plain-language labels, and progressive disclosure: summary first, technical details second.
- Gather Town version has too many agents roaming around. Reduce default movement, add density/speed controls, cluster agents by room/task, and add focus/calm mode.
- Theme switching is not visibly working. Implement real UI theme switcher with persistence and clear visual theme changes.
Key product requirements (installable solution level):
1. Config-driven architecture: all paths, URLs, colors, names, room layouts via config.yaml. No hardcoded references to jooho-hermes.
2. Self-contained package: clear directory structure (src/, web/, config/, docs/, scripts/), install script, requirements.txt.
3. Pluggable data adapter: support multiple backends via plugin architecture.
4. Themeable frontend: CSS variables driven from config, swappable themes, plus a working UI theme switcher.
5. Multi-tenant ready: works for any Hermes instance.
6. Build/Deploy ready: Dockerfile or docker-compose, or clear static-server setup.
7. Documentation: README, architecture docs, configuration reference, contributor guide.
8. Human-comprehensible UX: plain-language summaries and progressive disclosure for technical detail.
9. Gather.town calm mode: adjustable movement density/speed and less chaotic defaults.
10. Versioned releases: CHANGELOG.md, semantic versioning, release packaging.
Mission model:
- Read state.md first before doing anything else.
- If state.md says
status: inactive or has no Current Mission, do not invent work. Return exactly: ๐ก Autonomous Agent Lab ๋๊ธฐ์ค โ Son์ด ํธ๋ฆฌ๊ฑฐ/๋ฏธ์
์ ์ฃผ๋ฉด 15๋ถ ์ฌ์ดํด์ ์์ํฉ๋๋ค.
- If state.md says
status: active, run one bounded 15-minute cycle toward the full installable solution.
- If state.md says
status: complete, verify that the Final Completion Condition in state.md is truly met. If it is not fully met, reactivate or report that state needs correction.
Cycle procedure when active:
1. Read state.md first. Extract current mission, constraints, previous cycle log, and Final Completion Condition.
2. Decide the next smallest useful step toward installable solution quality. Focus on: architecture, configurability, documentation, and clean separation of concerns.
3. Use delegate_task for independent subagent lanes when helpful.
4. Prefer concrete progress: refactor to config-driven, add install scripts, create docs, add Docker support, theme system, plugin architecture.
5. Update state.md with a new cycle log entry before final reporting.
6. Completion rule: only set status: complete when every item under state.md Final Completion Condition is satisfied. A non-installable MVP is not complete.
7. Stop/block only if Son explicitly stops/redirects, a safety boundary is reached, or a hard blocker needs Son's decision.
Link requirement (never forget):
- Every cycle report MUST include at least one direct viewable link to the published dashboard/artifact.
- The canonical URL:
http://hermes-mac-mini.tail46b3c6.ts.net:8099/agent-pets/
- Include gather town URL too:
http://hermes-mac-mini.tail46b3c6.ts.net:8099/agent-pets/gather/
Final Discord message format:
[Autonomous Agent Lab v1 / Cycle N]
๋ชฉํ:
์ํ:
๊ฒฐ๊ณผ:
๊ฒ์ฆ:
๋ค์:
์ํ:
Safety/quality rules:
- Do not handle secrets, passwords, API keys, payment, permission dialogs, or destructive commands.
- Do not claim completion without updating state.md.
- Do not rely on Discord history as durable state.
- Do not spam raw logs; summarize lane outputs and verification.
- Keep working in /Users/jooho-hermes/.hermes/autonomous-agent-lab/ and publish only to /Users/jooho-hermes/hermes-web/agent-pets/ unless the state file says otherwise.
Design/UX priorities:
- Mobile responsiveness is first-class.
- Character animation/movement is desired.
- Every cycle report must include published links.
- This is now a product engineering mission. Architecture, configurability, and documentation matter as much as visuals.
Response
[Autonomous Agent Lab v1 / Cycle 64]
๋ชฉํ: Son์ UX ํผ๋๋ฐฑ(ํ
๋ง ์ค์์ฒ ๋ฏธ๋์, Gather ๊ณผ๋ค ์ด๋, ์ธ๊ฐ ์ค์ฌ ์์ฝ ๋ถ์กฑ)์ ๋ฃจํธ ์์ธ๊น์ง ์์ . "์ฝ๋๋ ์์ง๋ง ์ฌ์ฉ์๊ฐ ๋๋ผ์ง ๋ชปํจ" ๊ฐ๊ทน ํด์.
์ํ:
1. ํ
๋ง ์ค์์ฒ ์ ๋ขฐ์ฑ ๊ฐํ โ document.querySelector('link[rel="stylesheet"]') ์ ๊ฑฐ โ getElementById('themeLink')๋ก ํ์คํ ์ ํ. ๊ธฐ์กด 400ms opacity ํ์ด๋(๋ชจ๋ฐ์ผ์์ ๋๊น/๋ฏธ๋์์ฒ๋ผ ๋๊ปด์ง) ์ ๊ฑฐ. ์ <link> ์์ฑ โ onload ํ ๊ธฐ์กด ์ ๊ฑฐ ๋ฐฉ์์ผ๋ก Samsung Internet/Chrome/Safari ์ ์ฒด ํธํ.
2. ํ
๋ง ์ค์์ฒ ๊ฐ์์ฑ ๊ฐํ โ ๋์๋ณด๋ ํ๋จ .office-sign์์ hero ์๋จ(์ฒซ ํ๋ฉด)์ผ๋ก ์ด๋. ์คํฌ๋กค ์์ด ์ฆ์ ํด๋ฆญ ๊ฐ๋ฅ.
3. Gather ๊ธฐ๋ณธ๊ฐ ๋ ์กฐ์ฉํ๊ฒ โ ์์ด์ ํธ ํ์ไธ้ 8 โ 5 ์ถ์. ์ ๊ท ์ฌ์ฉ์๋ calm mode ๊ธฐ๋ณธ ON (localStorage ๋ฏธ์ค์ ์). ๊ธฐ์กด ์ฌ์ฉ์ ์ค์ ์ ์กด์ค.
4. ์บ์ ๋ฌดํจํ โ ์ ์ฒด asset ?v=64 ์ํฅ, Service Worker CACHE_NAME โ pixel-pet-ops-v20, ๋น๋ ๋ฐฐ์ง v1.4.4 ยท b64.
๊ฒฐ๊ณผ:
- ์์คโ๋ฐฐํฌ ๋๊ธฐํ ์๋ฃ
- ํตํฉ ํ
์คํธ 121/121 ํต๊ณผ
- ์ด๋ํฐ ์ ์ ๋์ (32 agents, 15 cron, 20 sessions, 16 events)
refresh.err.log ์ฌ์ ํ ๋น์ด ์์
๊ฒ์ฆ:
- ๋ฐฐํฌ HTML:
id="themeLink", hero-theme-bar, ?v=64, b64 ๋ฐฐ์ง ํ์ธ
- ๋ฐฐํฌ JS: link-swap
applyTheme, gather slice(0, 5), calm ๊ธฐ๋ณธ true ํ์ธ
- hardcoded
jooho-hermes 0๊ฑด ์ ์ง
๋ค์:
- Son์ ๋ธ๋ผ์ฐ์ ์บ์ ์ญ์ ๋ฒํผ("๐ ์บ์ ์ญ์ & ์๋ก๊ณ ์นจ") ํด๋ฆญ ํ ์๋ ํ์ธ ์๋ง:
1. Hero ์๋จ ํ
๋ง ๋ฒํผ(๐
Default / ๐ Dark Ops / ๐ธ Cozy Pastel) ํด๋ฆญ ์ ์์์ด ํ์ฐํ ๋ฐ๋๋๊ฐ
2. Gather Town ์ ์ ์ ์์ด์ ํธ 5๋ง๋ฆฌ, ๐ฟ Calm ๋ชจ๋ ๊ธฐ๋ณธ ์ ์ฉ ์ฌ๋ถ
3. ์์ด์ ํธ ์นด๋ ํด๋ฆญ ์ "์ง๊ธ ํ๋ ์ผ / ์ ์ค์ํ๊ฐ" ๋จผ์ , "๊ธฐ์ ์์ธ ๋ณด๊ธฐ"๋ ํ ๊ธ ๋ค์ ์๋๊ฐ
์ํ: active (Son์ UX ํผ๋๋ฐฑ ์ต์ข
ํ์ธ ์ ๊น์ง complete๋ก ์ ํํ์ง ์์)
๋งํฌ:
- ๐ ๋์๋ณด๋: http://hermes-mac-mini.tail46b3c6.ts.net:8099/agent-pets/
- ๐ข Gather Town: http://hermes-mac-mini.tail46b3c6.ts.net:8099/agent-pets/gather/
|
| 2026-05-19 18-00-54 |
83,071 chars |
2026-05-19_18-00-54.md |
Cron Job: autonomous-agent-lab-v1-orchestrator
Job ID: 35127ff89556
Run Time: 2026-05-19 18:00:54
Schedule: every 15m
Prompt
[IMPORTANT: The user has invoked the "hermes-agent" skill, indicating they want you to follow its instructions. The full skill content is loaded below.]
---
name: hermes-agent
description: "Configure, extend, or contribute to Hermes Agent."
version: 2.1.0
author: Hermes Agent + Teknium
license: MIT
platforms: [linux, macos, windows]
metadata:
hermes:
tags: [hermes, setup, configuration, multi-agent, spawning, cli, gateway, development]
homepage: https://github.com/NousResearch/hermes-agent
related_skills: [claude-code, codex, opencode]
---
Hermes Agent
Hermes Agent is an open-source AI agent framework by Nous Research that runs in your terminal, messaging platforms, and IDEs. It belongs to the same category as Claude Code (Anthropic), Codex (OpenAI), and OpenClaw โ autonomous coding and task-execution agents that use tool calling to interact with your system. Hermes works with any LLM provider (OpenRouter, Anthropic, OpenAI, DeepSeek, local models, and 15+ others) and runs on Linux, macOS, and WSL.
What makes Hermes different:
- Self-improving through skills โ Hermes learns from experience by saving reusable procedures as skills. When it solves a complex problem, discovers a workflow, or gets corrected, it can persist that knowledge as a skill document that loads into future sessions. Skills accumulate over time, making the agent better at your specific tasks and environment.
- Persistent memory across sessions โ remembers who you are, your preferences, environment details, and lessons learned. Pluggable memory backends (built-in, Honcho, Mem0, and more) let you choose how memory works.
- Multi-platform gateway โ the same agent runs on Telegram, Discord, Slack, WhatsApp, Signal, Matrix, Email, and 10+ other platforms with full tool access, not just chat.
- Provider-agnostic โ swap models and providers mid-workflow without changing anything else. Credential pools rotate across multiple API keys automatically.
- Profiles โ run multiple independent Hermes instances with isolated configs, sessions, skills, and memory.
- Extensible โ plugins, MCP servers, custom tools, webhook triggers, cron scheduling, and the full Python ecosystem.
People use Hermes for software development, research, system administration, data analysis, content creation, home automation, and anything else that benefits from an AI agent with persistent context and full system access.
This skill helps you work with Hermes Agent effectively โ setting it up, configuring features, spawning additional agent instances, troubleshooting issues, finding the right commands and settings, and understanding how the system works when you need to extend or contribute to it.
Docs: https://hermes-agent.nousresearch.com/docs/
Quick Start
Install
curl -fsSL https://raw.githubusercontent.com/NousResearch/hermes-agent/main/scripts/install.sh | bash
Interactive chat (default)
hermes
Single query
hermes chat -q "What is the capital of France?"
Setup wizard
hermes setup
Change model/provider
hermes model
Check health
hermes doctor
---
CLI Reference
Global Flags
hermes [flags] [command]
--version, -V Show version
--resume, -r SESSION Resume session by ID or title
--continue, -c [NAME] Resume by name, or most recent session
--worktree, -w Isolated git worktree mode (parallel agents)
--skills, -s SKILL Preload skills (comma-separate or repeat)
--profile, -p NAME Use a named profile
--yolo Skip dangerous command approval
--pass-session-id Include session ID in system prompt
No subcommand defaults to chat.
Chat
hermes chat [flags]
-q, --query TEXT Single query, non-interactive
-m, --model MODEL Model (e.g. anthropic/claude-sonnet-4)
-t, --toolsets LIST Comma-separated toolsets
--provider PROVIDER Force provider (openrouter, anthropic, nous, etc.)
-v, --verbose Verbose output
-Q, --quiet Suppress banner, spinner, tool previews
--checkpoints Enable filesystem checkpoints (/rollback)
--source TAG Session source tag (default: cli)
Configuration
hermes setup [section] Interactive wizard (model|terminal|gateway|tools|agent)
hermes model Interactive model/provider picker
hermes config View current config
hermes config edit Open config.yaml in $EDITOR
hermes config set KEY VAL Set a config value
hermes config path Print config.yaml path
hermes config env-path Print .env path
hermes config check Check for missing/outdated config
hermes config migrate Update config with new options
hermes doctor [--fix] Check dependencies and config
Credential Pools
hermes auth add Interactive credential wizard (oauth, api-key)
hermes auth list [PROVIDER] List pooled credentials
hermes auth remove P INDEX Remove by provider + index
hermes auth reset PROVIDER Clear exhaustion status
hermes logout Clear stored auth
Tools & Skills
hermes tools Interactive tool enable/disable (curses UI)
hermes tools list Show all tools and status
hermes tools enable NAME Enable a toolset
hermes tools disable NAME Disable a toolset
hermes skills list List installed skills
hermes skills search QUERY Search the skills hub
hermes skills install ID Install a skill (ID can be a hub identifier OR a direct https://โฆ/SKILL.md URL; pass --name to override when frontmatter has no name)
hermes skills inspect ID Preview without installing
hermes skills config Enable/disable skills per platform
hermes skills check Check for updates
hermes skills update Update outdated skills
hermes skills uninstall N Remove a hub skill
hermes skills publish PATH Publish to registry
hermes skills browse Browse all available skills
hermes skills tap add REPO Add a GitHub repo as skill source
MCP Servers
hermes mcp serve Run Hermes as an MCP server
hermes mcp add NAME Add an MCP server (--url or --command)
hermes mcp remove NAME Remove an MCP server
hermes mcp list List configured servers
hermes mcp test NAME Test connection
hermes mcp configure NAME Toggle tool selection
Gateway (Messaging Platforms)
hermes gateway run Start gateway foreground
hermes gateway install Install as background service
hermes gateway start/stop Control the service
hermes gateway restart Restart the service
hermes gateway status Check status
hermes gateway setup Configure platforms
Supported platforms: Telegram, Discord, Slack, WhatsApp, Signal, Email, SMS, Matrix, Mattermost, Home Assistant, DingTalk, Feishu, WeCom, BlueBubbles (iMessage), Weixin (WeChat), API Server, Webhooks. Open WebUI connects via the API Server adapter.
Platform docs: https://hermes-agent.nousresearch.com/docs/user-guide/messaging/
Discord-specific walkthrough (token, intents, service install, access control): see references/discord-gateway-setup.md in this skill.
- Per-channel personas and skill bindings: see
references/gateway-channel-personas.md (works on Discord, Slack, Telegram, Mattermost, Matrix).
- For long-running Discord-first operations, purpose-specific channel routing, periodic summaries, weekly Dreaming/audit reports, and log-safety patterns: see
references/discord-operating-planes.md.
- For broad Hermes/LifeOS/SQAF ecosystem audits (cron inventory, live services, dashboards, provider/model warnings, and control-plane gaps), see
references/ecosystem-audit.md.
Sessions
hermes sessions list List recent sessions
hermes sessions browse Interactive picker
hermes sessions export OUT Export to JSONL
hermes sessions rename ID T Rename a session
hermes sessions delete ID Delete a session
hermes sessions prune Clean up old sessions (--older-than N days)
hermes sessions stats Session store statistics
For browser-based viewing of existing Hermes CLI/Discord/cron session transcripts, prefer a lightweight static export from ~/.hermes/state.db into a private web root instead of assuming Open WebUI can browse Hermes' native session store. See references/hermes-session-static-web-viewer.md for the SQLite schema, static HTML export workflow, redaction/truncation cautions, and the user's Mac mini deployment (/hermes-sessions/ under the Tailscale-only ~/hermes-web site).
For cron job execution history, the same static-export pattern applies to ~/.hermes/cron/jobs.json and ~/.hermes/cron/output/{job_id}/*.md. See references/cron-history-web-viewer.md for the cron data model, schedule-dict pitfall, and the user's deployed /cron-history/ dashboard.
Cron Jobs
hermes cron list List jobs (--all for disabled)
hermes cron create SCHED Create: '30m', 'every 2h', '0 9 *'
hermes cron edit ID Edit schedule, prompt, delivery
hermes cron pause/resume ID Control job state
hermes cron run ID Trigger on next tick
hermes cron remove ID Delete a job
hermes cron status Scheduler status
For bounded autonomous lab/orchestrator cron jobs that use file-based state, subagent lanes, artifact publishing, and status transitions (active โ complete/blocked/inactive), see references/autonomous-agent-lab-cron-cycle.md. A reusable verification script template lives at scripts/verify-completion-template.py.
For a worked example of evolving an autonomous lab into a config-driven, themeable, Docker-ready installable product, see references/autonomous-lab-product-architecture.md. For CI, integration testing, pluggable adapter architecture, bounded cycle orchestration, and post-productization patterns, see references/product-maturity-patterns.md.
For the final completion verification checklist โ the explicit audit pattern to run before marking status: complete on an installable-solution mission, see references/autonomous-lab-completion-verification.md.
For the reactivation protocol when a completed lab receives new P0 feedback or the user contradicts a completion claim, see references/autonomous-lab-reactivation-protocol.md.
For the config/CHANGELOG version drift pitfall that occurs when autonomous labs evolve over many cycles, and for the related source vs. published file drift problem where the live web root diverges from the project source, see references/autonomous-lab-version-drift.md.
For adding historical trend tracking (SQLite-backed agent status transitions + vanilla JS SVG sparklines) to an autonomous lab dashboard, see references/history-tracking-sparkline-pattern.md.
For reusable dashboard UX patterns (onboarding tours, data freshness badges, keyboard shortcuts, progressive disclosure inspectors, cross-linking between views), see references/dashboard-ux-patterns.md.
For the aggressive human-first inspector refinement โ when users report that details are hard to understand and the fix is to strip technical labels from the default view โ see references/progressive-disclosure-human-first.md.
For programmatic verification of CSS custom-property theme systems โ catching scoping bugs, confirming theme distinctness, and validating JS switching logic โ see references/theme-system-verification.md.
For Son's Discord-first autonomous experiments where a channel hosts a repeated multi-agent loop, use the Autonomous Discord Agent Lab pattern: create file-based durable state, a paused cron orchestrator delivered to discord:<channel_id>, then activate it from a user mission trigger. See references/autonomous-discord-agent-lab.md.
Webhooks
hermes webhook subscribe N Create route at /webhooks/<name>
hermes webhook list List subscriptions
hermes webhook remove NAME Remove a subscription
hermes webhook test NAME Send a test POST
Profiles
hermes profile list List all profiles
hermes profile create NAME Create (--clone, --clone-all, --clone-from)
hermes profile use NAME Set sticky default
hermes profile delete NAME Delete a profile
hermes profile show NAME Show details
hermes profile alias NAME Manage wrapper scripts
hermes profile rename A B Rename a profile
hermes profile export NAME Export to tar.gz
hermes profile import FILE Import from archive
Credential Pools
hermes auth add Interactive credential wizard
hermes auth list [PROVIDER] List pooled credentials
hermes auth remove P INDEX Remove by provider + index
hermes auth reset PROVIDER Clear exhaustion status
Other
hermes insights [--days N] Usage analytics
hermes update Update to latest version
hermes pairing list/approve/revoke DM authorization
hermes plugins list/install/remove Plugin management
hermes honcho setup/status Honcho memory integration (requires honcho plugin)
hermes memory setup/status/off Memory provider config
hermes completion bash|zsh Shell completions
hermes acp ACP server (IDE integration)
hermes claw migrate Migrate from OpenClaw
hermes uninstall Uninstall Hermes
---
Slash Commands (In-Session)
Type these during an interactive chat session. New commands land fairly
often; if something below looks stale, run /help in-session for the
authoritative list or see the [live slash commands reference](https://hermes-agent.nousresearch.com/docs/reference/slash-commands).
The registry of record is hermes_cli/commands.py โ every consumer
(autocomplete, Telegram menu, Slack mapping, /help) derives from it.
Session Control
/new (/reset) Fresh session
/clear Clear screen + new session (CLI)
/retry Resend last message
/undo Remove last exchange
/title [name] Name the session
/compress Manually compress context
/stop Kill background processes
/rollback [N] Restore filesystem checkpoint
/snapshot [sub] Create or restore state snapshots of Hermes config/state (CLI)
/background <prompt> Run prompt in background
/queue <prompt> Queue for next turn
/steer <prompt> Inject a message after the next tool call without interrupting
/agents (/tasks) Show active agents and running tasks
/resume [name] Resume a named session
/goal [text|sub] Set a standing goal Hermes works on across turns until achieved
(subcommands: status, pause, resume, clear)
/redraw Force a full UI repaint (CLI)
Configuration
/config Show config (CLI)
/model [name] Show or change model
/personality [name] Set personality
/reasoning [level] Set reasoning (none|minimal|low|medium|high|xhigh|show|hide)
/verbose Cycle: off โ new โ all โ verbose
/voice [on|off|tts] Voice mode
/yolo Toggle approval bypass
/busy [sub] Control what Enter does while Hermes is working (CLI)
(subcommands: queue, steer, interrupt, status)
/indicator [style] Pick the TUI busy-indicator style (CLI)
(styles: kaomoji, emoji, unicode, ascii)
/footer [on|off] Toggle gateway runtime-metadata footer on final replies
/skin [name] Change theme (CLI)
/statusbar Toggle status bar (CLI)
Tools & Skills
/tools Manage tools (CLI)
/toolsets List toolsets (CLI)
/skills Search/install skills (CLI)
/skill <name> Load a skill into session
/reload-skills Re-scan ~/.hermes/skills/ for added/removed skills
/reload Reload .env variables into the running session (CLI)
/reload-mcp Reload MCP servers
/cron Manage cron jobs (CLI)
/curator [sub] Background skill maintenance (status, run, pin, archive, โฆ)
/kanban [sub] Multi-profile collaboration board (tasks, links, comments)
/plugins List plugins (CLI)
Gateway
/approve Approve a pending command (gateway)
/deny Deny a pending command (gateway)
/restart Restart gateway (gateway)
/sethome Set current chat as home channel (gateway)
/update Update Hermes to latest (gateway)
/topic [sub] Enable or inspect Telegram DM topic sessions (gateway)
/platforms (/gateway) Show platform connection status (gateway)
Utility
/branch (/fork) Branch the current session
/fast Toggle priority/fast processing
/browser Open CDP browser connection
/history Show conversation history (CLI)
/save Save conversation to file (CLI)
/copy [N] Copy the last assistant response to clipboard (CLI)
/paste Attach clipboard image (CLI)
/image Attach local image file (CLI)
Info
/help Show commands
/commands [page] Browse all commands (gateway)
/usage Token usage
/insights [days] Usage analytics
/gquota Show Google Gemini Code Assist quota usage (CLI)
/status Session info (gateway)
/profile Active profile info
/debug Upload debug report (system info + logs) and get shareable links
Exit
/quit (/exit, /q) Exit CLI
---
Key Paths & Config
~/.hermes/config.yaml Main configuration
~/.hermes/.env API keys and secrets
$HERMES_HOME/skills/ Installed skills
~/.hermes/sessions/ Session transcripts
~/.hermes/logs/ Gateway and error logs
~/.hermes/auth.json OAuth tokens and credential pools
~/.hermes/hermes-agent/ Source code (if git-installed)
Profiles use ~/.hermes/profiles/<name>/ with the same layout.
Config Sections
Edit with hermes config edit or hermes config set section.key value.
| Section | Key options |
|---------|-------------|
| model | default, provider, base_url, api_key, context_length |
| agent | max_turns (90), tool_use_enforcement |
| terminal | backend (local/docker/ssh/modal), cwd, timeout (180) |
| compression | enabled, threshold (0.50), target_ratio (0.20) |
| display | skin, tool_progress, show_reasoning, show_cost |
| stt | enabled, provider (local/groq/openai/mistral) |
| tts | provider (edge/elevenlabs/openai/minimax/mistral/neutts) |
| memory | memory_enabled, user_profile_enabled, provider |
| security | tirith_enabled, website_blocklist |
| delegation | model, provider, base_url, api_key, max_iterations (50), reasoning_effort |
| checkpoints | enabled, max_snapshots (50) |
| fallback_model | provider, model, base_url, key_env |
Fallback Providers
Hermes can automatically fail over to a backup provider:model when the primary is unavailable. This is turn-scoped โ each new user message starts with the primary restored; fallback only activates mid-turn when the primary fails.
Configuration ( ~/.hermes/config.yaml):
fallback_model:
provider: opencode-go
model: kimi-k2.6
Or use the interactive manager:
hermes fallback add # interactive picker
hermes fallback list # show fallback chain
hermes fallback remove # remove by index
Legacy note: fallback_model (singular) is the legacy single-fallback key. fallback_providers (list) supports multiple ordered fallbacks. When both exist, fallback_providers takes priority.
Trigger conditions (after exhausting retries where applicable):
- Rate limits (HTTP 429)
- Server errors (HTTP 500, 502, 503)
- Auth failures (HTTP 401, 403) โ immediately
- Not found (HTTP 404) โ immediately
- Invalid / empty responses repeatedly
Supported providers include all standard providers (OpenRouter, Anthropic, OpenCode Go/ Zen, Kimi, etc.) plus custom endpoints with base_url + key_env. Full provider docs: https://hermes-agent.nousresearch.com/docs/integrations/providers
Limitations:
- Subagent delegation does not inherit fallback config
- Cron jobs do not use fallback (use per-job provider/model overrides)
- Auxiliary tasks (vision, compression, etc.) use their own
auxiliary.* provider chain
For a deep-dive with worked examples and model lists, see references/fallback-providers.md.
Full config reference: https://hermes-agent.nousresearch.com/docs/user-guide/configuration
Providers
20+ providers supported. Set via hermes model or hermes setup.
| Provider | Auth | Key env var |
|----------|------|-------------|
| OpenRouter | API key | OPENROUTER_API_KEY |
| Anthropic | API key | ANTHROPIC_API_KEY |
| Nous Portal | OAuth | hermes auth |
| OpenAI Codex | OAuth | hermes auth |
| GitHub Copilot | Token | COPILOT_GITHUB_TOKEN |
| Google Gemini | API key | GOOGLE_API_KEY or GEMINI_API_KEY |
| DeepSeek | API key | DEEPSEEK_API_KEY |
| xAI / Grok | API key | XAI_API_KEY |
| Hugging Face | Token | HF_TOKEN |
| Z.AI / GLM | API key | GLM_API_KEY |
| MiniMax | API key | MINIMAX_API_KEY |
| MiniMax CN | API key | MINIMAX_CN_API_KEY |
| Kimi / Moonshot | API key | KIMI_API_KEY |
| Alibaba / DashScope | API key | DASHSCOPE_API_KEY |
| Xiaomi MiMo | API key | XIAOMI_API_KEY |
| Kilo Code | API key | KILOCODE_API_KEY |
| AI Gateway (Vercel) | API key | AI_GATEWAY_API_KEY |
| OpenCode Zen | API key | OPENCODE_ZEN_API_KEY |
| OpenCode Go | API key | OPENCODE_GO_API_KEY |
| Qwen OAuth | OAuth | hermes auth add qwen-oauth |
| Custom endpoint | Config | model.base_url + model.api_key in config.yaml |
| GitHub Copilot ACP | External | COPILOT_CLI_PATH or Copilot CLI |
Full provider docs: https://hermes-agent.nousresearch.com/docs/integrations/providers
Toolsets
Enable/disable via hermes tools (interactive) or hermes tools enable/disable NAME.
| Toolset | What it provides |
|---------|-----------------|
| web | Web search and content extraction |
| search | Web search only (subset of web) |
| browser | Browser automation (Browserbase, Camofox, or local Chromium) |
| terminal | Shell commands and process management |
| file | File read/write/search/patch |
| code_execution | Sandboxed Python execution |
| vision | Image analysis |
| image_gen | AI image generation |
| video | Video analysis and generation |
| tts | Text-to-speech |
| skills | Skill browsing and management |
| memory | Persistent cross-session memory |
| session_search | Search past conversations |
| delegation | Subagent task delegation |
| cronjob | Scheduled task management |
| clarify | Ask user clarifying questions |
| messaging | Cross-platform message sending |
| todo | In-session task planning and tracking |
| kanban | Multi-agent work-queue tools (gated to workers) |
| debugging | Extra introspection/debug tools (off by default) |
| safe | Minimal, low-risk toolset for locked-down sessions |
| spotify | Spotify playback and playlist control |
| homeassistant | Smart home control (off by default) |
| discord | Discord integration tools |
| discord_admin | Discord admin/moderation tools |
| feishu_doc | Feishu (Lark) document tools |
| feishu_drive | Feishu (Lark) drive tools |
| yuanbao | Yuanbao integration tools |
| rl | Reinforcement learning tools (off by default) |
| moa | Mixture of Agents (off by default) |
Full enumeration lives in toolsets.py as the TOOLSETS dict; _HERMES_CORE_TOOLS is the default bundle most platforms inherit from.
Tool changes take effect on /reset (new session). They do NOT apply mid-conversation to preserve prompt caching.
---
Security & Privacy Toggles
Common "why is Hermes doing X to my output / tool calls / commands?" toggles โ and the exact commands to change them. Most of these need a fresh session (/reset in chat, or start a new hermes invocation) because they're read once at startup.
Secret redaction in tool output
Secret redaction is off by default โ tool output (terminal stdout, read_file, web content, subagent summaries, etc.) passes through unmodified. If the user wants Hermes to auto-mask strings that look like API keys, tokens, and secrets before they enter the conversation context and logs:
hermes config set security.redact_secrets true # enable globally
Restart required. security.redact_secrets is snapshotted at import time โ toggling it mid-session (e.g. via export HERMES_REDACT_SECRETS=true from a tool call) will NOT take effect for the running process. Tell the user to run hermes config set security.redact_secrets true in a terminal, then start a new session. This is deliberate โ it prevents an LLM from flipping the toggle on itself mid-task.
Disable again with:
hermes config set security.redact_secrets false
PII redaction in gateway messages
Separate from secret redaction. When enabled, the gateway hashes user IDs and strips phone numbers from the session context before it reaches the model:
hermes config set privacy.redact_pii true # enable
hermes config set privacy.redact_pii false # disable (default)
Command approval prompts
By default (approvals.mode: manual), Hermes prompts the user before running shell commands flagged as destructive (rm -rf, git reset --hard, etc.). The modes are:
manual โ always prompt (default)
smart โ use an auxiliary LLM to auto-approve low-risk commands, prompt on high-risk
off โ skip all approval prompts (equivalent to --yolo)
hermes config set approvals.mode smart # recommended middle ground
hermes config set approvals.mode off # bypass everything (not recommended)
Per-invocation bypass without changing config:
hermes --yolo โฆ
export HERMES_YOLO_MODE=1
Note: YOLO / approvals.mode: off does NOT turn off secret redaction. They are independent.
Shell hooks allowlist
Some shell-hook integrations require explicit allowlisting before they fire. Managed via ~/.hermes/shell-hooks-allowlist.json โ prompted interactively the first time a hook wants to run.
Disabling the web/browser/image-gen tools
To keep the model away from network or media tools entirely, open hermes tools and toggle per-platform. Takes effect on next session (/reset). See the Tools & Skills section above.
---
Voice & Transcription
STT (Voice โ Text)
Voice messages from messaging platforms are auto-transcribed.
Provider priority (auto-detected):
1. Local faster-whisper โ free, no API key: pip install faster-whisper
2. Groq Whisper โ free tier: set GROQ_API_KEY
3. OpenAI Whisper โ paid: set VOICE_TOOLS_OPENAI_KEY
4. Mistral Voxtral โ set MISTRAL_API_KEY
Config:
stt:
enabled: true
provider: local # local, groq, openai, mistral
local:
model: base # tiny, base, small, medium, large-v3
TTS (Text โ Voice)
| Provider | Env var | Free? |
|----------|---------|-------|
| Edge TTS | None | Yes (default) |
| ElevenLabs | ELEVENLABS_API_KEY | Free tier |
| OpenAI | VOICE_TOOLS_OPENAI_KEY | Paid |
| MiniMax | MINIMAX_API_KEY | Paid |
| Mistral (Voxtral) | MISTRAL_API_KEY | Paid |
| NeuTTS (local) | None (pip install neutts[all] + espeak-ng) | Free |
Voice commands: /voice on (voice-to-voice), /voice tts (always voice), /voice off.
---
Spawning Additional Hermes Instances
Run additional Hermes processes as fully independent subprocesses โ separate sessions, tools, and environments.
When to Use This vs delegate_task
| | delegate_task | Spawning hermes process |
|-|-----------------|--------------------------|
| Isolation | Separate conversation, shared process | Fully independent process |
| Duration | Minutes (bounded by parent loop) | Hours/days |
| Tool access | Subset of parent's tools | Full tool access |
| Interactive | No | Yes (PTY mode) |
| Use case | Quick parallel subtasks | Long autonomous missions |
One-Shot Mode
terminal(command="hermes chat -q 'Research GRPO papers and write summary to ~/research/grpo.md'", timeout=300)
Background for long tasks:
terminal(command="hermes chat -q 'Set up CI/CD for ~/myapp'", background=true)
Interactive PTY Mode (via tmux)
Hermes uses prompt_toolkit, which requires a real terminal. Use tmux for interactive spawning:
Start
terminal(command="tmux new-session -d -s agent1 -x 120 -y 40 'hermes'", timeout=10)
Wait for startup, then send a message
terminal(command="sleep 8 && tmux send-keys -t agent1 'Build a FastAPI auth service' Enter", timeout=15)
Read output
terminal(command="sleep 20 && tmux capture-pane -t agent1 -p", timeout=5)
Send follow-up
terminal(command="tmux send-keys -t agent1 'Add rate limiting middleware' Enter", timeout=5)
Exit
terminal(command="tmux send-keys -t agent1 '/exit' Enter && sleep 2 && tmux kill-session -t agent1", timeout=10)
Multi-Agent Coordination
Agent A: backend
terminal(command="tmux new-session -d -s backend -x 120 -y 40 'hermes -w'", timeout=10)
terminal(command="sleep 8 && tmux send-keys -t backend 'Build REST API for user management' Enter", timeout=15)
Agent B: frontend
terminal(command="tmux new-session -d -s frontend -x 120 -y 40 'hermes -w'", timeout=10)
terminal(command="sleep 8 && tmux send-keys -t frontend 'Build React dashboard for user management' Enter", timeout=15)
Check progress, relay context between them
terminal(command="tmux capture-pane -t backend -p | tail -30", timeout=5)
terminal(command="tmux send-keys -t frontend 'Here is the API schema from the backend agent: ...' Enter", timeout=5)
Session Resume
Resume most recent session
terminal(command="tmux new-session -d -s resumed 'hermes --continue'", timeout=10)
Resume specific session
terminal(command="tmux new-session -d -s resumed 'hermes --resume 20260225_143052_a1b2c3'", timeout=10)
Tips
- Prefer
delegate_task for quick subtasks โ less overhead than spawning a full process
- Use
-w (worktree mode) when spawning agents that edit code โ prevents git conflicts
- Set timeouts for one-shot mode โ complex tasks can take 5-10 minutes
- Use
hermes chat -q for fire-and-forget โ no PTY needed
- Use tmux for interactive sessions โ raw PTY mode has
\r vs \n issues with prompt_toolkit
- For scheduled tasks, use the
cronjob tool instead of spawning โ handles delivery and retry
---
Durable & Background Systems
Four systems run alongside the main conversation loop. Quick reference
here; full developer notes live in AGENTS.md, user-facing docs under
website/docs/user-guide/features/.
Delegation (delegate_task)
Synchronous subagent spawn โ the parent waits for the child's summary
before continuing its own loop. Isolated context + terminal session.
- Single:
delegate_task(goal, context, toolsets).
- Batch:
delegate_task(tasks=[{goal, ...}, ...]) runs children in
parallel, capped by delegation.max_concurrent_children (default 3).
- Roles:
leaf (default; cannot re-delegate) vs orchestrator
(can spawn its own workers, bounded by delegation.max_spawn_depth).
- Not durable. If the parent is interrupted, the child is
cancelled. For work that must outlive the turn, use cronjob or
terminal(background=True, notify_on_complete=True).
Config: delegation.* in config.yaml.
Tuning max_concurrent_children
Default is 3. Rule of thumb for raising it:
- Light tasks (web search, file grep): up to
6-8
- Medium tasks (code execution, browser):
4-5
- Heavy tasks (builds, large data):
2-3
- Actual bottleneck is usually the API rate limit, not local CPU/RAM. On a 10-core M4 with 16GB RAM, CPU is rarely the constraint.
- Formula: start at
5, raise only if profiling shows idle time between API responses.
Cron (scheduled jobs)
Durable scheduler โ cron/jobs.py + cron/scheduler.py. Drive it via
the cronjob tool, the hermes cron CLI (list, add, edit,
pause, resume, run, remove), or the /cron slash command.
- Schedules: duration (
"30m", "2h"), "every" phrase
( "every monday 9am"), 5-field cron ( "0 9 *"), or ISO timestamp.
- Per-job knobs:
skills, model/provider override, script
(pre-run data collection; no_agent=True makes the script the whole
job), context_from (chain job A's output into job B), workdir
(run in a specific dir with its AGENTS.md / CLAUDE.md loaded),
multi-platform delivery.
- Invariants: 3-minute hard interrupt per run,
.tick.lock file
prevents duplicate ticks across processes, cron sessions pass
skip_memory=True by default, and cron deliveries are framed with a
header/footer instead of being mirrored into the target gateway
session (keeps role alternation intact).
User docs: https://hermes-agent.nousresearch.com/docs/user-guide/features/cron
Curator (skill lifecycle)
Background maintenance for agent-created skills. Tracks usage, marks
idle skills stale, archives stale ones, keeps a pre-run tar.gz backup
so nothing is lost.
- CLI:
hermes curator <verb> โ status, run, pause, resume,
pin, unpin, archive, restore, prune, backup, rollback.
- Slash:
/curator <subcommand> mirrors the CLI.
- Scope: only touches skills with
created_by: "agent" provenance.
Bundled + hub-installed skills are off-limits. Never deletes โ
max destructive action is archive. Pinned skills are exempt from
every auto-transition and every LLM review pass.
- Telemetry: sidecar at
~/.hermes/skills/.usage.json holds
per-skill use_count, view_count, patch_count,
last_activity_at, state, pinned.
Config: curator.* (enabled, interval_hours, min_idle_hours,
stale_after_days, archive_after_days, backup.*).
User docs: https://hermes-agent.nousresearch.com/docs/user-guide/features/curator
Dreaming (periodic memory/skill consolidation)
For Anthropic-style "dreaming" workflows, combine cron + session_search + memory + skills + curator into a scheduled review loop. Start with a weekly, proposal-only report that audits recent sessions, repeated user corrections, memory conflicts, skill patch candidates, and cron/automation improvements. Do not automatically delete/replace memory or patch/archive skills unless the user explicitly approves the proposed changes. See references/weekly-dreaming-routine.md for the recommended prompt, report format, safety policy, and cron creation pattern.
Kanban (multi-agent work queue)
Durable SQLite board for multi-profile / multi-worker collaboration.
Users drive it via hermes kanban <verb>; dispatcher-spawned workers
see a focused kanban_* toolset gated by HERMES_KANBAN_TASK so the
schema footprint is zero outside worker processes.
- CLI verbs (common):
init, create, list (alias ls),
show, assign, link, unlink, comment, complete, block,
unblock, archive, tail. Less common: watch, stats, runs,
log, dispatch, daemon, gc.
- Worker toolset:
kanban_show, kanban_complete, kanban_block,
kanban_heartbeat, kanban_comment, kanban_create, kanban_link.
- Dispatcher runs inside the gateway by default
( kanban.dispatch_in_gateway: true) โ reclaims stale claims,
promotes ready tasks, atomically claims, spawns assigned profiles.
Auto-blocks a task after ~5 consecutive spawn failures.
- Isolation: board is the hard boundary (workers get
HERMES_KANBAN_BOARD pinned in env); tenant is a soft namespace
within a board for workspace-path + memory-key isolation.
User docs: https://hermes-agent.nousresearch.com/docs/user-guide/features/kanban
Log Relay (Hermes โ Discord)
A background Python script that tails ~/.hermes/logs/*.log and batches lines to a Discord channel. Includes session-ID extraction, rate-limit handling, and auto-restart via launchd/systemd. Useful for remote monitoring and audit trails.
- Reference:
references/discord-log-relay.md โ full setup, tuning, macOS/Linux service install, pitfalls.
- Template:
templates/discord-log-relay.py โ copy, set CHANNEL_ID, and deploy.
- Discord operations:
references/discord-operating-planes.md โ channel-purpose routing, periodic-summary vs Dreaming report formats, and safety/cost notes for Discord-first Hermes deployments.
Key pitfall: ask the user about batch frequency upfront rather than defaulting to real-time streaming. Most users prefer 10-minute or hourly batches. High-volume raw logs should be batched, summarized, or stored out-of-band; avoid Discord message storms during error loops.
Weekly Dreaming / Memory Curation
For long-running Hermes deployments, users may want an Anthropic-style "Dreaming" loop: a scheduled review that consolidates experience, proposes memory/skill/cron changes, and identifies what to keep, weaken, archive, or delete. Hermes has the building blocks (sessions, session_search, memory, skills, curator, cron), but the safe default is proposal mode:
1. Inspect recent usage and sessions.
2. Extract repeated success patterns, failure patterns, and user corrections.
3. Propose memory updates/removals without applying them silently.
4. Propose skill patches/archive candidates and cron/reporting improvements.
5. End with explicit approval checkboxes.
Do not silently rewrite or delete memory/skills from a Dreaming report unless the user explicitly authorized automatic application. See references/discord-operating-planes.md for a report template and routing heuristics.
---
Windows-Specific Quirks
Hermes runs natively on Windows (PowerShell, cmd, Windows Terminal, git-bash
mintty, VS Code integrated terminal). Most of it just works, but a handful
of differences between Win32 and POSIX have bitten us โ document new ones
here as you hit them so the next person (or the next session) doesn't
rediscover them from scratch.
Input / Keybindings
Alt+Enter doesn't insert a newline. Windows Terminal intercepts Alt+Enter
at the terminal layer to toggle fullscreen โ the keystroke never reaches
prompt_toolkit. Use Ctrl+Enter instead. Windows Terminal delivers
Ctrl+Enter as LF ( c-j), distinct from plain Enter ( c-m / CR), and the
CLI binds c-j to newline insertion on win32 only (see
_bind_prompt_submit_keys + the Windows-only c-j binding in cli.py).
Side effect: the raw Ctrl+J keystroke also inserts a newline on Windows โ
unavoidable, because Windows Terminal collapses Ctrl+Enter and Ctrl+J to
the same keycode at the Win32 console API layer. No conflicting binding
existed for Ctrl+J on Windows, so this is a harmless side effect.
mintty / git-bash behaves the same (fullscreen on Alt+Enter) unless you
disable Alt+Fn shortcuts in Options โ Keys. Easier to just use Ctrl+Enter.
Diagnosing keybindings. Run python scripts/keystroke_diagnostic.py
(repo root) to see exactly how prompt_toolkit identifies each keystroke
in the current terminal. Answers questions like "does Shift+Enter come
through as a distinct key?" (almost never โ most terminals collapse it
to plain Enter) or "what byte sequence is my terminal sending for
Ctrl+Enter?" This is how the Ctrl+Enter = c-j fact was established.
Config / Files
HTTP 400 "No models provided" on first run. config.yaml was saved
with a UTF-8 BOM (common when Windows apps write it). Re-save as UTF-8
without BOM. hermes config edit writes without BOM; manual edits in
Notepad are the usual culprit.
execute_code / Sandbox
WinError 10106 ("The requested service provider could not be loaded
or initialized") from the sandbox child process โ it can't create an
AF_INET socket, so the loopback-TCP RPC fallback fails before
connect(). Root cause is usually not a broken Winsock LSP; it's
Hermes's own env scrubber dropping SYSTEMROOT / WINDIR / COMSPEC
from the child env. Python's socket module needs SYSTEMROOT to locate
mswsock.dll. Fixed via the _WINDOWS_ESSENTIAL_ENV_VARS allowlist in
tools/code_execution_tool.py. If you still hit it, echo os.environ
inside an execute_code block to confirm SYSTEMROOT is set. Full
diagnostic recipe in references/execute-code-sandbox-env-windows.md.
Testing / Contributing
scripts/run_tests.sh doesn't work as-is on Windows โ it looks for
POSIX venv layouts ( .venv/bin/activate). The Hermes-installed venv at
venv/Scripts/ has no pip or pytest either (stripped for install size).
Workaround: install pytest + pytest-xdist + pyyaml into a system Python
3.11 user site, then invoke pytest directly with PYTHONPATH set:
"/c/Program Files/Python311/python" -m pip install --user pytest pytest-xdist pyyaml
export PYTHONPATH="$(pwd)"
"/c/Program Files/Python311/python" -m pytest tests/foo/test_bar.py -v --tb=short -n 0
Use -n 0, not -n 4 โ pyproject.toml's default addopts already
includes -n, and the wrapper's CI-parity guarantees don't apply off POSIX.
POSIX-only tests need skip guards. Common markers already in the codebase:
- Symlinks โ elevated privileges on Windows
0o600 file modes โ POSIX mode bits not enforced on NTFS by default
signal.SIGALRM โ Unix-only (see tests/conftest.py::_enforce_test_timeout)
- Winsock / Windows-specific regressions โ
@pytest.mark.skipif(sys.platform != "win32", ...)
Use the existing skip-pattern style (sys.platform == "win32" or
sys.platform.startswith("win")) to stay consistent with the rest of the
suite.
Path / Filesystem
Line endings. Git may warn LF will be replaced by CRLF the next time
Git touches it. Cosmetic โ the repo's .gitattributes normalizes. Don't
let editors auto-convert committed POSIX-newline files to CRLF.
Forward slashes work almost everywhere. C:/Users/... is accepted by
every Hermes tool and most Windows APIs. Prefer forward slashes in code
and logs โ avoids shell-escaping backslashes in bash.
---
Troubleshooting
Voice not working
1. Check stt.enabled: true in config.yaml
2. Verify provider: pip install faster-whisper or set API key
3. In gateway: /restart. In CLI: exit and relaunch.
Tool not available
1. hermes tools โ check if toolset is enabled for your platform
2. Some tools need env vars (check .env)
3. /reset after enabling tools
Model/provider issues
1. hermes doctor โ check config and dependencies
2. hermes auth add <provider> โ re-authenticate OAuth providers (use --type oauth)
3. Check .env has the right API key
4. Copilot 403: gh auth login tokens do NOT work for Copilot API. You must use the Copilot-specific OAuth device code flow via hermes model โ GitHub Copilot.
Changes not taking effect
- Tools/skills:
/reset starts a new session with updated toolset
- Config changes: In gateway:
/restart. In CLI: exit and relaunch.
- Code changes: Restart the CLI or gateway process
Deployed web dashboard shows stale CSS or theme changes
- Browser cache: Add
?v=N cache-busting query strings to CSS/JS/theme links in HTML.
- Service Worker cache: Bump
CACHE_NAME in sw.js to invalidate old shell caches.
- Data freshness: Use
fetch(url, {cache:'no-store'}) for live JSON feeds.
- See
references/static-site-cache-invalidation.md for the full diagnostic recipe.
Dashboard inspector feels too technical
- The default inspector view should contain only plain-language sentences: headline, "what they're doing now", "why it matters", and a silent visual progress bar (no text label).
- Move all technical fields (source IDs, confidence scores, progress labels, status slugs, badges) behind a "Show technical details" toggle.
- If users say "details are hard to understand," the fix is to remove more fields from the default view, not to add explanations. Explanations of technical fields are still technical.
- See
references/progressive-disclosure-human-first.md for the aggressive simplification pattern.
Skills not showing
1. hermes skills list โ verify installed
2. hermes skills config โ check platform enablement
3. Load explicitly: /skill name or hermes -s name
Gateway issues
Check logs first:
grep -i "failed to send\|error" ~/.hermes/logs/gateway.log | tail -20
Common gateway problems:
- Gateway dies on SSH logout: Enable linger:
sudo loginctl enable-linger $USER
- Gateway dies on WSL2 close: WSL2 requires
systemd=true in /etc/wsl.conf for systemd services to work. Without it, gateway falls back to nohup (dies when session closes).
- Gateway crash loop: Reset the failed state:
systemctl --user reset-failed hermes-gateway
- macOS: bot shows offline after idle time: The gateway runs as a user agent (
LimitLoadToSessionType=Aqua), so macOS suspends it when the system sleeps. The platform websocket drops and the bot appears offline until the network returns. Fix: keep the Mac awake (System Settings -> Energy -> Prevent automatic sleeping, or caffeinate -d -i -s -u &). Low Power Mode makes this worse, not better. See references/macos-gateway-sleep-disconnect.md for the full diagnostic recipe.
Platform-specific issues
- Discord bot silent: Must enable Message Content Intent in Bot โ Privileged Gateway Intents. See full Discord setup reference:
references/discord-gateway-setup.md.
- Slack bot only works in DMs: Must subscribe to
message.channels event. Without it, the bot ignores public channels.
- Windows-specific issues (
Alt+Enter newline, WinError 10106, UTF-8 BOM config, test suite, line endings): see the dedicated Windows-Specific Quirks section above.
Auxiliary models not working
If auxiliary tasks (vision, compression, session_search) fail silently, the auto provider can't find a backend. Either set OPENROUTER_API_KEY or GOOGLE_API_KEY, or explicitly configure each auxiliary task's provider:
hermes config set auxiliary.vision.provider <your_provider>
hermes config set auxiliary.vision.model <model_name>
Full system auth provisioning
For a one-shot workflow to maximize available credentials โ installing gh, generating SSH keys, configuring git, enabling all Hermes toolsets, and auditing current auth state โ see references/system-auth-setup.md.
Editing large files with patch
When a file is read with read_file(offset=...) (pagination), the tool warns that the view is partial. If you attempt patch without re-reading the full file first, you will likely hit non-unique match errors or corrupt the file. Fix: always call read_file without offset to load the whole file before patching. For append-only updates (e.g., adding a cycle log entry to state.md), do not use terminal(command="cat >> file << 'EOF'...EOF") โ the terminal tool on macOS/Linux misinterprets heredoc << as backgrounding and fails. Instead, write a short Python script via write_file and execute it with terminal(command="python3 /tmp/script.py"). See references/terminal-heredoc-workaround.md for the full pattern.
Sibling subagent file overwrites
When multiple subagents are running in parallel (e.g. via delegate_task batch mode or kanban worker lanes), a file may be modified by one subagent while another is about to write to it. If you use write_file or patch on a file that was last read before a sibling subagent modified it, your write may silently truncate or revert the sibling's changes. The tool may show a warning like "this file was modified by sibling subagent X but this agent never read it."
Fix:
1. Heed the warning. If the tool reports a sibling modification, re-read the file with read_file before writing.
2. Prefer patch over write_file for partial updates โ patch only changes the matched region and is less likely to wipe unrelated content.
3. If the file is already published/deployed, and the local working copy gets corrupted, recover from the published copy:
cp ~/hermes-web/agent-pets/css/dashboard.css ~/.hermes/autonomous-agent-lab/pixel-pet-ops/web/css/dashboard.css
4. For append-only updates, write a small Python script and execute it rather than using write_file on the whole file.
Prevention: In kanban/multi-agent workflows, assign file-level ownership so only one worker touches each file. If parallel workers must edit the same file, have them write to separate temp files and let the orchestrator merge.
---
Windows-Specific Quirks
| Looking for... | Location |
|----------------|----------|
| Config options | hermes config edit or [Configuration docs](https://hermes-agent.nousresearch.com/docs/user-guide/configuration) |
| Available tools | hermes tools list or [Tools reference](https://hermes-agent.nousresearch.com/docs/reference/tools-reference) |
| Slash commands | /help in session or [Slash commands reference](https://hermes-agent.nousresearch.com/docs/reference/slash-commands) |
| Skills catalog | hermes skills browse or [Skills catalog](https://hermes-agent.nousresearch.com/docs/reference/skills-catalog) |
| Provider setup | hermes model or [Providers guide](https://hermes-agent.nousresearch.com/docs/integrations/providers) |
| Platform setup | hermes gateway setup or [Messaging docs](https://hermes-agent.nousresearch.com/docs/user-guide/messaging/) |
| MCP servers | hermes mcp list or [MCP guide](https://hermes-agent.nousresearch.com/docs/user-guide/features/mcp) |
| Profiles | hermes profile list or [Profiles docs](https://hermes-agent.nousresearch.com/docs/user-guide/profiles) |
| Cron jobs | hermes cron list or [Cron docs](https://hermes-agent.nousresearch.com/docs/user-guide/features/cron) |
| Memory | hermes memory status or [Memory docs](https://hermes-agent.nousresearch.com/docs/user-guide/features/memory) |
| Env variables | hermes config env-path or [Env vars reference](https://hermes-agent.nousresearch.com/docs/reference/environment-variables) |
| CLI commands | hermes --help or [CLI reference](https://hermes-agent.nousresearch.com/docs/reference/cli-commands) |
| Gateway logs | ~/.hermes/logs/gateway.log |
| Session files | ~/.hermes/sessions/ or hermes sessions browse |
| Source code | ~/.hermes/hermes-agent/ |
---
Contributor Quick Reference
For occasional contributors and PR authors. Full developer docs: https://hermes-agent.nousresearch.com/docs/developer-guide/
Project Layout
hermes-agent/
โโโ run_agent.py # AIAgent โ core conversation loop
โโโ model_tools.py # Tool discovery and dispatch
โโโ toolsets.py # Toolset definitions
โโโ cli.py # Interactive CLI (HermesCLI)
โโโ hermes_state.py # SQLite session store
โโโ agent/ # Prompt builder, context compression, memory, model routing, credential pooling, skill dispatch
โโโ hermes_cli/ # CLI subcommands, config, setup, commands
โ โโโ commands.py # Slash command registry (CommandDef)
โ โโโ config.py # DEFAULT_CONFIG, env var definitions
โ โโโ main.py # CLI entry point and argparse
โโโ tools/ # One file per tool
โ โโโ registry.py # Central tool registry
โโโ gateway/ # Messaging gateway
โ โโโ platforms/ # Platform adapters (telegram, discord, etc.)
โโโ cron/ # Job scheduler
โโโ tests/ # ~3000 pytest tests
โโโ website/ # Docusaurus docs site
Config: ~/.hermes/config.yaml (settings), ~/.hermes/.env (API keys).
Adding a Tool (3 files)
1. Create tools/your_tool.py:
import json, os
from tools.registry import registry
def check_requirements() -> bool:
return bool(os.getenv("EXAMPLE_API_KEY"))
def example_tool(param: str, task_id: str = None) -> str:
return json.dumps({"success": True, "data": "..."})
registry.register(
name="example_tool",
toolset="example",
schema={"name": "example_tool", "description": "...", "parameters": {...}},
handler=lambda args, **kw: example_tool(
param=args.get("param", ""), task_id=kw.get("task_id")),
check_fn=check_requirements,
requires_env=["EXAMPLE_API_KEY"],
)
2. Add to toolsets.py โ _HERMES_CORE_TOOLS list.
Auto-discovery: any tools/*.py file with a top-level registry.register() call is imported automatically โ no manual list needed.
All handlers must return JSON strings. Use get_hermes_home() for paths, never hardcode ~/.hermes.
Adding a Slash Command
1. Add CommandDef to COMMAND_REGISTRY in hermes_cli/commands.py
2. Add handler in cli.py โ process_command()
3. (Optional) Add gateway handler in gateway/run.py
All consumers (help text, autocomplete, Telegram menu, Slack mapping) derive from the central registry automatically.
Agent Loop (High Level)
run_conversation():
1. Build system prompt
2. Loop while iterations < max:
a. Call LLM (OpenAI-format messages + tool schemas)
b. If tool_calls โ dispatch each via handle_function_call() โ append results โ continue
c. If text response โ return
3. Context compression triggers automatically near token limit
Testing
python -m pytest tests/ -o 'addopts=' -q # Full suite
python -m pytest tests/tools/ -q # Specific area
- Tests auto-redirect
HERMES_HOME to temp dirs โ never touch real ~/.hermes/
- Run full suite before pushing any change
- Use
-o 'addopts=' to clear any baked-in pytest flags
Windows contributors: scripts/run_tests.sh currently looks for POSIX venvs ( .venv/bin/activate / venv/bin/activate) and will error out on Windows where the layout is venv/Scripts/activate + python.exe. The Hermes-installed venv at venv/Scripts/ also has no pip or pytest โ it's stripped for end-user install size. Workaround: install pytest + pytest-xdist + pyyaml into a system Python 3.11 user site ( /c/Program Files/Python311/python -m pip install --user pytest pytest-xdist pyyaml), then run tests directly:
export PYTHONPATH="$(pwd)"
"/c/Program Files/Python311/python" -m pytest tests/tools/test_foo.py -v --tb=short -n 0
Use -n 0 (not -n 4) because pyproject.toml's default addopts already includes -n, and the wrapper's CI-parity story doesn't apply off-POSIX.
Cross-platform test guards: tests that use POSIX-only syscalls need a skip marker. Common ones already in the codebase:
- Symlink creation โ
@pytest.mark.skipif(sys.platform == "win32", reason="Symlinks require elevated privileges on Windows") (see tests/cron/test_cron_script.py)
- POSIX file modes (0o600, etc.) โ
@pytest.mark.skipif(sys.platform.startswith("win"), reason="POSIX mode bits not enforced on Windows") (see tests/hermes_cli/test_auth_toctou_file_modes.py)
signal.SIGALRM โ Unix-only (see tests/conftest.py::_enforce_test_timeout)
- Live Winsock / Windows-specific regression tests โ
@pytest.mark.skipif(sys.platform != "win32", reason="Windows-specific regression")
Monkeypatching sys.platform is not enough when the code under test also calls platform.system() / platform.release() / platform.mac_ver(). Those functions re-read the real OS independently, so a test that sets sys.platform = "linux" on a Windows runner will still see platform.system() == "Windows" and route through the Windows branch. Patch all three together:
monkeypatch.setattr(sys, "platform", "linux")
monkeypatch.setattr(platform, "system", lambda: "Linux")
monkeypatch.setattr(platform, "release", lambda: "6.8.0-generic")
See tests/agent/test_prompt_builder.py::TestEnvironmentHints for a worked example.
Extending the system prompt's execution-environment block
Factual guidance about the host OS, user home, cwd, terminal backend, and shell (bash vs. PowerShell on Windows) is emitted from agent/prompt_builder.py::build_environment_hints(). This is also where the WSL hint and per-backend probe logic live. The convention:
- Local terminal backend โ emit host info (OS,
$HOME, cwd) + Windows-specific notes (hostname โ username, terminal uses bash not PowerShell).
- Remote terminal backend (anything in
_REMOTE_TERMINAL_BACKENDS: docker, singularity, modal, daytona, ssh, vercel_sandbox, managed_modal) โ suppress host info entirely and describe only the backend. A live uname/whoami/pwd probe runs inside the backend via tools.environments.get_environment(...).execute(...), cached per process in _BACKEND_PROBE_CACHE, with a static fallback if the probe times out.
- Key fact for prompt authoring: when
TERMINAL_ENV != "local", every file tool (read_file, write_file, patch, search_files) runs inside the backend container, not on the host. The system prompt must never describe the host in that case โ the agent can't touch it.
Full design notes, the exact emitted strings, and testing pitfalls:
references/prompt-builder-environment-hints.md.
Refactor-safety pattern (POSIX-equivalence guard): when you extract inline logic into a helper that adds Windows/platform-specific behavior, keep a _legacy_<name> oracle function in the test file that's a verbatim copy of the old code, then parametrize-diff against it. Example: tests/tools/test_code_execution_windows_env.py::TestPosixEquivalence. This locks in the invariant that POSIX behavior is bit-for-bit identical and makes any future drift fail loudly with a clear diff.
Commit Conventions
type: concise subject line
Optional body.
Types: fix:, feat:, refactor:, docs:, chore:
Key Rules
- Never break prompt caching โ don't change context, tools, or system prompt mid-conversation
- Message role alternation โ never two assistant or two user messages in a row
- Use
get_hermes_home() from hermes_constants for all paths (profile-safe)
- Config values go in
config.yaml, secrets go in .env
- New tools need a
check_fn so they only appear when requirements are met
[IMPORTANT: The user has invoked the "kanban-orchestrator" skill, indicating they want you to follow its instructions. The full skill content is loaded below.]
---
name: kanban-orchestrator
description: Decomposition playbook + anti-temptation rules for an orchestrator profile routing work through Kanban. The "don't do the work yourself" rule and the basic lifecycle are auto-injected into every kanban worker's system prompt; this skill is the deeper playbook when you're specifically playing the orchestrator role.
version: 3.0.0
platforms: [linux, macos, windows]
metadata:
hermes:
tags: [kanban, multi-agent, orchestration, routing]
related_skills: [kanban-worker]
---
Kanban Orchestrator โ Decomposition Playbook
> The core worker lifecycle (including the kanban_create fan-out pattern and the "decompose, don't execute" rule) is auto-injected into every kanban process via the KANBAN_GUIDANCE system-prompt block. This skill is the deeper playbook when you're an orchestrator profile whose whole job is routing.
Profiles are user-configured โ not a fixed roster
Hermes setups vary widely. Some users run a single profile that does everything; some run a small fleet (docker-worker, cron-worker); some run a curated specialist team they've named themselves. There is no default specialist roster โ the orchestrator skill does not know what profiles exist on this machine.
Before fanning out, you must ground the decomposition in the profiles that actually exist. The dispatcher silently fails to spawn unknown assignee names โ it doesn't autocorrect, doesn't suggest, doesn't fall back. So a card assigned to researcher on a setup that only has docker-worker just sits in ready forever.
Step 0: discover available profiles before planning.
Use one of these:
hermes profile list โ prints the table of profiles configured on this machine. Run it through your terminal tool if you have one; otherwise ask the user.
kanban_list(assignee="<some-name>") โ sanity-check a single name. Returns an empty list (rather than an error) for an unknown assignee, so this only confirms a name you're already considering.
- Just ask the user. "What profiles do you have set up?" is a fine first turn when the goal needs more than one specialist.
Cache the result in your working memory for the rest of the conversation. Re-asking every turn wastes a tool call.
When to use the board (vs. just doing the work)
Create Kanban tasks when any of these are true:
1. Multiple specialists are needed. Research + analysis + writing is three profiles.
2. The work should survive a crash or restart. Long-running, recurring, or important.
3. The user might want to interject. Human-in-the-loop at any step.
4. Multiple subtasks can run in parallel. Fan-out for speed.
5. Review / iteration is expected. A reviewer profile loops on drafter output.
6. The audit trail matters. Board rows persist in SQLite forever.
If none of those apply โ it's a small one-shot reasoning task โ use delegate_task instead or answer the user directly.
The anti-temptation rules
Your job description says "route, don't execute." The rules that enforce that:
- Do not execute the work yourself. Your restricted toolset usually doesn't even include terminal/file/code/web for implementation. If you find yourself "just fixing this quickly" โ stop and create a task for the right specialist.
- For any concrete task, create a Kanban task and assign it. Every single time.
- Split multi-lane requests before creating cards. A user prompt can contain several independent workstreams. Extract those lanes first, then create one card per lane instead of bundling unrelated work into a single implementer card.
- Run independent lanes in parallel. If two cards do not need each other's output, leave them unlinked so the dispatcher can fan them out. Link only true data dependencies.
- If no specialist fits the available profiles, ask the user which profile to create or which existing profile to use. Do not invent profile names; the dispatcher will silently drop unknown assignees.
- Decompose, route, and summarize โ that's the whole job.
Exception: micro-UI polish cycles
There is one narrow exception where the orchestrator may execute directly instead of creating Kanban cards: tiny UI-only polish cycles (e.g., adding a CSS class, a theme preview dot, a hover state, a cross-link, or a HUD button) that are purely presentational, require no cross-file logic changes, and fit comfortably inside a single bounded cycle with no need for review or parallel work. If the change is limited to HTML/CSS/JS cosmetics, no other profile has a stake in it, and the user did not ask for a design review, the orchestrator should just edit and publish rather than paying the kanban-overhead tax. This exception does NOT apply to architecture changes, adapter logic, plugin interfaces, or anything that touches the data layer.
Decomposition playbook
Step 1 โ Understand the goal
Ask clarifying questions if the goal is ambiguous. Cheap to ask; expensive to spawn the wrong fleet.
Step 2 โ Sketch the task graph
Before creating anything, draft the graph out loud (in your response to the user). Treat every concrete workstream as a candidate card:
1. Extract the lanes from the request.
2. Map each lane to one of the profiles you discovered in Step 0. If a lane doesn't fit any existing profile, ask the user which to use or create.
3. Decide whether each lane is independent or gated by another lane.
4. Create independent lanes as parallel cards with no parent links.
5. Create synthesis/review/integration cards with parent links to the lanes they depend on.
Examples of prompts that should fan out (using placeholder profile names โ substitute whatever exists on the user's setup):
- "Build an app" โ one card to a design-oriented profile for product/UI direction, one or two cards to engineering profiles for implementation, plus a later integration/review card if the user has a reviewer profile.
- "Fix blockers and check model variants" โ one implementation card for the blocker fixes plus one discovery/research card for config/source verification. A final reviewer card can depend on both.
- "Research docs and implement" โ a docs-research card can run in parallel with a codebase-discovery card; implementation waits only if it truly needs those findings.
- "Analyze this screenshot and find the related code" โ one card to a vision-capable profile for the visual analysis while another searches the codebase.
Words like "also," "finally," or "and" do not automatically imply a dependency. They often mean "make sure this is covered before reporting back." Only link tasks when one card cannot start until another card's output exists.
Show the graph to the user before creating cards. Let them correct it โ including which actual profile name should own each lane.
Step 3 โ Create tasks and link
Use the profile names from Step 0. The example below uses placeholders <profile-A>, <profile-B>, <profile-C> โ replace them with what the user actually has.
t1 = kanban_create(
title="research: Postgres cost vs current",
assignee="<profile-A>", # whichever profile handles research on this setup
body="Compare estimated infrastructure costs, migration costs, and ongoing ops costs over a 3-year window. Sources: AWS/GCP pricing, team time estimates, current Postgres bills from peers.",
tenant=os.environ.get("HERMES_TENANT"),
)["task_id"]
t2 = kanban_create(
title="research: Postgres performance vs current",
assignee="<profile-A>", # same profile, run in parallel
body="Compare query latency, throughput, and scaling characteristics at our expected data volume (~500GB, 10k QPS peak). Sources: benchmark papers, public case studies, pgbench results if easy.",
)["task_id"]
t3 = kanban_create(
title="synthesize migration recommendation",
assignee="<profile-B>", # whichever profile does synthesis/analysis
body="Read the findings from T1 (cost) and T2 (performance). Produce a 1-page recommendation with explicit trade-offs and a go/no-go call.",
parents=[t1, t2],
)["task_id"]
t4 = kanban_create(
title="draft decision memo",
assignee="<profile-C>", # whichever profile drafts user-facing prose
body="Turn the analyst's recommendation into a 2-page memo for the CTO. Match the tone of previous decision memos in the team's knowledge base.",
parents=[t3],
)["task_id"]
parents=[...] gates promotion โ children stay in todo until every parent reaches done, then auto-promote to ready. No manual coordination needed; the dispatcher and dependency engine handle it.
Step 4 โ Complete your own task
If you were spawned as a task yourself (e.g. a planner profile was assigned T0: "investigate Postgres migration"), mark it done with a summary of what you created:
kanban_complete(
summary="decomposed into T1-T4: 2 research lanes in parallel, 1 synthesis on their outputs, 1 prose draft on the recommendation",
metadata={
"task_graph": {
"T1": {"assignee": "<profile-A>", "parents": []},
"T2": {"assignee": "<profile-A>", "parents": []},
"T3": {"assignee": "<profile-B>", "parents": ["T1", "T2"]},
"T4": {"assignee": "<profile-C>", "parents": ["T3"]},
},
},
)
Step 5 โ Report back to the user
Tell them what you created in plain prose, naming the actual profiles you used:
> I've queued 4 tasks:
> - T1 (<profile-A>): cost comparison
> - T2 (<profile-A>): performance comparison, in parallel with T1
> - T3 (<profile-B>): synthesizes T1 + T2 into a recommendation
> - T4 (<profile-C>): turns T3 into a CTO memo
>
> The dispatcher will pick up T1 and T2 now. T3 starts when both finish. You'll get a gateway ping when T4 completes. Use the dashboard or hermes kanban tail <id> to follow along.
Common patterns
Fan-out + fan-in (research โ synthesize): N research-style cards with no parents, one synthesis card with all of them as parents.
Parallel implementation + validation: one implementer card makes the change while one explorer/researcher card verifies config, docs, or source mapping. A reviewer card can depend on both. Do not make the implementer own unrelated verification just because the user mentioned both in one sentence.
Pipeline with gates: planner โ implementer โ reviewer. Each stage's parents=[previous_task]. Reviewer blocks or completes; if reviewer blocks, the operator unblocks with feedback and respawns.
Same-profile queue: N tasks, all assigned to the same profile, no dependencies between them. Dispatcher serializes โ that profile processes them in priority order, accumulating experience in its own memory.
Parallel UI/frontend lanes: When the goal touches multiple independent HTML/CSS/JS files (e.g., a dashboard page and a 2D gather view), fan out to separate subagents per file. Each lane edits its own file, then the orchestrator integrates, fixes cross-file references (theme paths, shared JSON endpoints), and publishes. This avoids merge conflicts in single-file HTML dashboards and keeps each subagent's context focused. See references/parallel-ui-lanes-and-publishing.md for the post-subagent integration checklist and rsync safety notes.
Human-in-the-loop: Any task can kanban_block() to wait for input. Dispatcher respawns after /unblock. The comment thread carries the full context.
Pitfalls
Inventing profile names that don't exist. The dispatcher silently fails to spawn unknown assignees โ the card just sits in ready forever. Always assign to a profile from your Step 0 discovery; ask the user if you're unsure.
Bundling independent lanes into one card. If the user asks for two independent outcomes, create two cards. Example: "fix blockers and check model variants" is not one fixer task; create a fixer/engineer card for the fixes and an explorer/researcher card for the variant check, then optionally gate review on both.
Over-linking because of wording. "Finally check X" may still be parallel with implementation if X is static config, docs, or source discovery. Link it after implementation only when the check depends on the implementation result.
Forgetting dependency links. If the task graph says research -> implement -> review, do not create all tasks as independent ready cards. Use parent links so implement/review cannot run before their inputs exist.
Reassignment vs. new task. If a reviewer blocks with "needs changes," create a NEW task linked from the reviewer's task โ don't re-run the same task with a stern look. The new task is assigned to the original implementer profile.
Argument order for links. kanban_link(parent_id=..., child_id=...) โ parent first. Mixing them up demotes the wrong task to todo.
Ignoring explicit user feedback to keep building infrastructure. When the user says a specific UX issue (legibility, theme switching, movement density) is "immediate priority," treat it as P0 and route it before deeper packaging/architecture work. Infrastructure polish feels productive, but shipping user-visible fixes is what matters. Create cards for the UX feedback first, then resume infrastructure lanes.
Treating status: complete as immutable when user feedback says otherwise. A state.md that says status: complete does not override a user's report that a completion criterion is actually broken. If the user says "theme switching is not working" and the Final Completion Condition requires "working UI theme switcher," the mission is not complete. Reactivate immediately: set status: active, append a reactivation cycle log, and fix the issue. Do not burn cycles on post-complete verification while the user is reporting active defects.
Don't pre-create the whole graph if the shape depends on intermediate findings. If T3's structure depends on what T1 and T2 find, let T3 exist as a "synthesize findings" task whose own first step is to read parent handoffs and plan the rest. Orchestrators can spawn orchestrators.
Tenant inheritance. If HERMES_TENANT is set in your env, pass tenant=os.environ.get("HERMES_TENANT") on every kanban_create call so child tasks stay in the same namespace.
Verifying cross-file references after directory reorganization. When subagents edit HTML/CSS/JS files and the directory structure shifts (e.g., moving files from root into web/dashboard/ and web/gather/), relative asset paths ( themes/default/theme.css, ./ops-data.json) often break. After subagents finish, the orchestrator must grep for href= and src= in moved files and fix relative paths before publishing. Subagents don't know the final publish layout โ the orchestrator does.
Destructive sync wipes needed files. Commands like rsync -av --delete will delete destination files that aren't in the source list. If you publish a directory tree piecemeal (e.g., copy web/dashboard/ first, then web/gather/ separately), --delete on the first rsync will erase the gather files before the second rsync runs. Either list all source paths in a single rsync invocation, or omit --delete and use cp -r / rsync -av without deletion when doing staged copies.
Recovering stuck workers
When a worker profile keeps crashing, hallucinating, or getting blocked by its own mistakes (usually: wrong model, missing skill, broken credential), the kanban dashboard flags the task with a โ badge and opens a Recovery section in the drawer. Three primary actions:
1. Reclaim (or hermes kanban reclaim <task_id>) โ abort the running worker immediately and reset the task to ready. The existing claim TTL is ~15 min; this is the fast path out.
2. Reassign (or hermes kanban reassign <task_id> <new-profile> --reclaim) โ switch the task to a different profile (one that exists on this setup) and let the dispatcher pick it up with a fresh worker.
3. Change profile model โ the dashboard prints a copy-paste hint for hermes -p <profile> model since profile config lives on disk; edit it in a terminal, then Reclaim to retry with the new model.
Hallucination warnings appear on tasks where a worker's kanban_complete(created_cards=[...]) claim included card ids that don't exist or weren't created by the worker's profile (the gate blocks the completion), or where the free-form summary references t_<hex> ids that don't resolve (advisory prose scan, non-blocking). Both produce audit events that persist even after recovery actions โ the trail stays for debugging.
The user has provided the following instruction alongside the skill invocation: [IMPORTANT: You are running as a scheduled cron job. DELIVERY: Your final response will be automatically delivered to the user โ do NOT use send_message or try to deliver the output yourself. Just produce your report/output as your final response and the system handles the rest. SILENT: If there is genuinely nothing new to report, respond with exactly "[SILENT]" (nothing else) to suppress delivery. Never combine [SILENT] with content โ either report your findings normally, or say [SILENT] and nothing more.]
You are the 15-minute Orchestrator for Son's Autonomous Agent Lab v1, reporting to Discord channel ID 1505805763824586952.
Durable state path: /Users/jooho-hermes/.hermes/autonomous-agent-lab/state.md
Working directory for experiment artifacts: /Users/jooho-hermes/.hermes/autonomous-agent-lab/
Preferred published web root: /Users/jooho-hermes/hermes-web/agent-pets/
Top-level directive from Son:
- The project has evolved from a personal dashboard into an INSTALLABLE PRODUCT that external Hermes users can deploy.
- The final target is a self-contained, configurable, publishable solution: "Hermes Pixel Pet Ops Office".
- Do NOT shrink the mission into a small static MVP and autonomously stop.
- The Gather.town-style 2D spatial office is a first-class feature, not a side page.
Latest UX feedback from Son (treat as immediate priority before deeper packaging work):
- Details are hard for a human to understand. Add human-first summaries, plain-language labels, and progressive disclosure: summary first, technical details second.
- Gather Town version has too many agents roaming around. Reduce default movement, add density/speed controls, cluster agents by room/task, and add focus/calm mode.
- Theme switching is not visibly working. Implement real UI theme switcher with persistence and clear visual theme changes.
Key product requirements (installable solution level):
1. Config-driven architecture: all paths, URLs, colors, names, room layouts via config.yaml. No hardcoded references to jooho-hermes.
2. Self-contained package: clear directory structure (src/, web/, config/, docs/, scripts/), install script, requirements.txt.
3. Pluggable data adapter: support multiple backends via plugin architecture.
4. Themeable frontend: CSS variables driven from config, swappable themes, plus a working UI theme switcher.
5. Multi-tenant ready: works for any Hermes instance.
6. Build/Deploy ready: Dockerfile or docker-compose, or clear static-server setup.
7. Documentation: README, architecture docs, configuration reference, contributor guide.
8. Human-comprehensible UX: plain-language summaries and progressive disclosure for technical detail.
9. Gather.town calm mode: adjustable movement density/speed and less chaotic defaults.
10. Versioned releases: CHANGELOG.md, semantic versioning, release packaging.
Mission model:
- Read state.md first before doing anything else.
- If state.md says
status: inactive or has no Current Mission, do not invent work. Return exactly: ๐ก Autonomous Agent Lab ๋๊ธฐ์ค โ Son์ด ํธ๋ฆฌ๊ฑฐ/๋ฏธ์
์ ์ฃผ๋ฉด 15๋ถ ์ฌ์ดํด์ ์์ํฉ๋๋ค.
- If state.md says
status: active, run one bounded 15-minute cycle toward the full installable solution.
- If state.md says
status: complete, verify that the Final Completion Condition in state.md is truly met. If it is not fully met, reactivate or report that state needs correction.
Cycle procedure when active:
1. Read state.md first. Extract current mission, constraints, previous cycle log, and Final Completion Condition.
2. Decide the next smallest useful step toward installable solution quality. Focus on: architecture, configurability, documentation, and clean separation of concerns.
3. Use delegate_task for independent subagent lanes when helpful.
4. Prefer concrete progress: refactor to config-driven, add install scripts, create docs, add Docker support, theme system, plugin architecture.
5. Update state.md with a new cycle log entry before final reporting.
6. Completion rule: only set status: complete when every item under state.md Final Completion Condition is satisfied. A non-installable MVP is not complete.
7. Stop/block only if Son explicitly stops/redirects, a safety boundary is reached, or a hard blocker needs Son's decision.
Link requirement (never forget):
- Every cycle report MUST include at least one direct viewable link to the published dashboard/artifact.
- The canonical URL:
http://hermes-mac-mini.tail46b3c6.ts.net:8099/agent-pets/
- Include gather town URL too:
http://hermes-mac-mini.tail46b3c6.ts.net:8099/agent-pets/gather/
Final Discord message format:
[Autonomous Agent Lab v1 / Cycle N]
๋ชฉํ:
์ํ:
๊ฒฐ๊ณผ:
๊ฒ์ฆ:
๋ค์:
์ํ:
Safety/quality rules:
- Do not handle secrets, passwords, API keys, payment, permission dialogs, or destructive commands.
- Do not claim completion without updating state.md.
- Do not rely on Discord history as durable state.
- Do not spam raw logs; summarize lane outputs and verification.
- Keep working in /Users/jooho-hermes/.hermes/autonomous-agent-lab/ and publish only to /Users/jooho-hermes/hermes-web/agent-pets/ unless the state file says otherwise.
Design/UX priorities:
- Mobile responsiveness is first-class.
- Character animation/movement is desired.
- Every cycle report must include published links.
- This is now a product engineering mission. Architecture, configurability, and documentation matter as much as visuals.
Response
[Autonomous Agent Lab v1 / Cycle 63]
๋ชฉํ:
Post-complete verification โ confirm status: complete remains legitimate on the scheduled 15-minute tick. Verify all 11 Final Completion Conditions and Son's UX feedback fixes are still live.
์ํ:
bash scripts/test.sh โ 121/121 passed
bash scripts/validate_setup.sh โ 21/21 passed, 0 warned, 0 critical
python3 -m src.adapter.generate_ops_data --config config.yaml โ 32 agents, 15 cron jobs, 20 sessions, 16 events, schema 1.4
- Published file sync verified (
diff confirms source and published dashboard/gather HTML are identical)
- Theme distinctness verified programmatically across all 3 themes (bg/ink/accent all dramatically distinct)
- Gather calm settings verified in published JS: cap=8, sparse=0.04, slow=0.25, zen mode, focus mode present
- Dashboard inspector verified: default view shows only plain-language summary + visual progress bar; all technical details hidden behind toggle
state.md updated with Cycle 63 log entry; cycle_count bumped to 63
๊ฒฐ๊ณผ:
ops-data.json schema 1.4, 32 agents, 16 events, mtimes fresh
health.json status=healthy, version=1.4.4, all sources true
refresh.err.log remains empty; LaunchAgent com.hermes.agent-pets-refresh healthy
- Zero hardcoded
jooho-hermes references in source
๊ฒ์ฆ:
- All 11 Final Completion Conditions remain satisfied โ
- Son's top-3 UX feedback verified as fixed in published source:
1. Theme switching visible โ
(dramatically distinct colors, CSS scoping bug fixed, cache busting v62, cache clear buttons)
2. Gather calm mode โ
(cap=8, sparse=0.04, slow=0.25, zen mode, focus mode)
3. Human-first details โ
(inspector default shows only plain-language summary + progress bar, tech details hidden)
๋ค์:
Mission remains complete. No further autonomous cycles required unless Son redirects, requests new features, or identifies a defect.
์ํ: ๐ข complete โ all 11 Final Completion Conditions satisfied and verified by automated test suites. Dashboard and Gather Town are live, published, and continuously refreshed.
Links:
- Dashboard:
http://hermes-mac-mini.tail46b3c6.ts.net:8099/agent-pets/
- Gather Town:
http://hermes-mac-mini.tail46b3c6.ts.net:8099/agent-pets/gather/
|
| 2026-05-19 17-38-13 |
82,068 chars |
2026-05-19_17-38-13.md |
Cron Job: autonomous-agent-lab-v1-orchestrator
Job ID: 35127ff89556
Run Time: 2026-05-19 17:38:13
Schedule: every 15m
Prompt
[IMPORTANT: The user has invoked the "hermes-agent" skill, indicating they want you to follow its instructions. The full skill content is loaded below.]
---
name: hermes-agent
description: "Configure, extend, or contribute to Hermes Agent."
version: 2.1.0
author: Hermes Agent + Teknium
license: MIT
platforms: [linux, macos, windows]
metadata:
hermes:
tags: [hermes, setup, configuration, multi-agent, spawning, cli, gateway, development]
homepage: https://github.com/NousResearch/hermes-agent
related_skills: [claude-code, codex, opencode]
---
Hermes Agent
Hermes Agent is an open-source AI agent framework by Nous Research that runs in your terminal, messaging platforms, and IDEs. It belongs to the same category as Claude Code (Anthropic), Codex (OpenAI), and OpenClaw โ autonomous coding and task-execution agents that use tool calling to interact with your system. Hermes works with any LLM provider (OpenRouter, Anthropic, OpenAI, DeepSeek, local models, and 15+ others) and runs on Linux, macOS, and WSL.
What makes Hermes different:
- Self-improving through skills โ Hermes learns from experience by saving reusable procedures as skills. When it solves a complex problem, discovers a workflow, or gets corrected, it can persist that knowledge as a skill document that loads into future sessions. Skills accumulate over time, making the agent better at your specific tasks and environment.
- Persistent memory across sessions โ remembers who you are, your preferences, environment details, and lessons learned. Pluggable memory backends (built-in, Honcho, Mem0, and more) let you choose how memory works.
- Multi-platform gateway โ the same agent runs on Telegram, Discord, Slack, WhatsApp, Signal, Matrix, Email, and 10+ other platforms with full tool access, not just chat.
- Provider-agnostic โ swap models and providers mid-workflow without changing anything else. Credential pools rotate across multiple API keys automatically.
- Profiles โ run multiple independent Hermes instances with isolated configs, sessions, skills, and memory.
- Extensible โ plugins, MCP servers, custom tools, webhook triggers, cron scheduling, and the full Python ecosystem.
People use Hermes for software development, research, system administration, data analysis, content creation, home automation, and anything else that benefits from an AI agent with persistent context and full system access.
This skill helps you work with Hermes Agent effectively โ setting it up, configuring features, spawning additional agent instances, troubleshooting issues, finding the right commands and settings, and understanding how the system works when you need to extend or contribute to it.
Docs: https://hermes-agent.nousresearch.com/docs/
Quick Start
Install
curl -fsSL https://raw.githubusercontent.com/NousResearch/hermes-agent/main/scripts/install.sh | bash
Interactive chat (default)
hermes
Single query
hermes chat -q "What is the capital of France?"
Setup wizard
hermes setup
Change model/provider
hermes model
Check health
hermes doctor
---
CLI Reference
Global Flags
hermes [flags] [command]
--version, -V Show version
--resume, -r SESSION Resume session by ID or title
--continue, -c [NAME] Resume by name, or most recent session
--worktree, -w Isolated git worktree mode (parallel agents)
--skills, -s SKILL Preload skills (comma-separate or repeat)
--profile, -p NAME Use a named profile
--yolo Skip dangerous command approval
--pass-session-id Include session ID in system prompt
No subcommand defaults to chat.
Chat
hermes chat [flags]
-q, --query TEXT Single query, non-interactive
-m, --model MODEL Model (e.g. anthropic/claude-sonnet-4)
-t, --toolsets LIST Comma-separated toolsets
--provider PROVIDER Force provider (openrouter, anthropic, nous, etc.)
-v, --verbose Verbose output
-Q, --quiet Suppress banner, spinner, tool previews
--checkpoints Enable filesystem checkpoints (/rollback)
--source TAG Session source tag (default: cli)
Configuration
hermes setup [section] Interactive wizard (model|terminal|gateway|tools|agent)
hermes model Interactive model/provider picker
hermes config View current config
hermes config edit Open config.yaml in $EDITOR
hermes config set KEY VAL Set a config value
hermes config path Print config.yaml path
hermes config env-path Print .env path
hermes config check Check for missing/outdated config
hermes config migrate Update config with new options
hermes doctor [--fix] Check dependencies and config
Credential Pools
hermes auth add Interactive credential wizard (oauth, api-key)
hermes auth list [PROVIDER] List pooled credentials
hermes auth remove P INDEX Remove by provider + index
hermes auth reset PROVIDER Clear exhaustion status
hermes logout Clear stored auth
Tools & Skills
hermes tools Interactive tool enable/disable (curses UI)
hermes tools list Show all tools and status
hermes tools enable NAME Enable a toolset
hermes tools disable NAME Disable a toolset
hermes skills list List installed skills
hermes skills search QUERY Search the skills hub
hermes skills install ID Install a skill (ID can be a hub identifier OR a direct https://โฆ/SKILL.md URL; pass --name to override when frontmatter has no name)
hermes skills inspect ID Preview without installing
hermes skills config Enable/disable skills per platform
hermes skills check Check for updates
hermes skills update Update outdated skills
hermes skills uninstall N Remove a hub skill
hermes skills publish PATH Publish to registry
hermes skills browse Browse all available skills
hermes skills tap add REPO Add a GitHub repo as skill source
MCP Servers
hermes mcp serve Run Hermes as an MCP server
hermes mcp add NAME Add an MCP server (--url or --command)
hermes mcp remove NAME Remove an MCP server
hermes mcp list List configured servers
hermes mcp test NAME Test connection
hermes mcp configure NAME Toggle tool selection
Gateway (Messaging Platforms)
hermes gateway run Start gateway foreground
hermes gateway install Install as background service
hermes gateway start/stop Control the service
hermes gateway restart Restart the service
hermes gateway status Check status
hermes gateway setup Configure platforms
Supported platforms: Telegram, Discord, Slack, WhatsApp, Signal, Email, SMS, Matrix, Mattermost, Home Assistant, DingTalk, Feishu, WeCom, BlueBubbles (iMessage), Weixin (WeChat), API Server, Webhooks. Open WebUI connects via the API Server adapter.
Platform docs: https://hermes-agent.nousresearch.com/docs/user-guide/messaging/
Discord-specific walkthrough (token, intents, service install, access control): see references/discord-gateway-setup.md in this skill.
- Per-channel personas and skill bindings: see
references/gateway-channel-personas.md (works on Discord, Slack, Telegram, Mattermost, Matrix).
- For long-running Discord-first operations, purpose-specific channel routing, periodic summaries, weekly Dreaming/audit reports, and log-safety patterns: see
references/discord-operating-planes.md.
- For broad Hermes/LifeOS/SQAF ecosystem audits (cron inventory, live services, dashboards, provider/model warnings, and control-plane gaps), see
references/ecosystem-audit.md.
Sessions
hermes sessions list List recent sessions
hermes sessions browse Interactive picker
hermes sessions export OUT Export to JSONL
hermes sessions rename ID T Rename a session
hermes sessions delete ID Delete a session
hermes sessions prune Clean up old sessions (--older-than N days)
hermes sessions stats Session store statistics
For browser-based viewing of existing Hermes CLI/Discord/cron session transcripts, prefer a lightweight static export from ~/.hermes/state.db into a private web root instead of assuming Open WebUI can browse Hermes' native session store. See references/hermes-session-static-web-viewer.md for the SQLite schema, static HTML export workflow, redaction/truncation cautions, and the user's Mac mini deployment (/hermes-sessions/ under the Tailscale-only ~/hermes-web site).
For cron job execution history, the same static-export pattern applies to ~/.hermes/cron/jobs.json and ~/.hermes/cron/output/{job_id}/*.md. See references/cron-history-web-viewer.md for the cron data model, schedule-dict pitfall, and the user's deployed /cron-history/ dashboard.
Cron Jobs
hermes cron list List jobs (--all for disabled)
hermes cron create SCHED Create: '30m', 'every 2h', '0 9 *'
hermes cron edit ID Edit schedule, prompt, delivery
hermes cron pause/resume ID Control job state
hermes cron run ID Trigger on next tick
hermes cron remove ID Delete a job
hermes cron status Scheduler status
For bounded autonomous lab/orchestrator cron jobs that use file-based state, subagent lanes, artifact publishing, and status transitions (active โ complete/blocked/inactive), see references/autonomous-agent-lab-cron-cycle.md. A reusable verification script template lives at scripts/verify-completion-template.py.
For a worked example of evolving an autonomous lab into a config-driven, themeable, Docker-ready installable product, see references/autonomous-lab-product-architecture.md. For CI, integration testing, pluggable adapter architecture, bounded cycle orchestration, and post-productization patterns, see references/product-maturity-patterns.md.
For the final completion verification checklist โ the explicit audit pattern to run before marking status: complete on an installable-solution mission, see references/autonomous-lab-completion-verification.md.
For the reactivation protocol when a completed lab receives new P0 feedback or the user contradicts a completion claim, see references/autonomous-lab-reactivation-protocol.md.
For the config/CHANGELOG version drift pitfall that occurs when autonomous labs evolve over many cycles, see references/autonomous-lab-version-drift.md.
For adding historical trend tracking (SQLite-backed agent status transitions + vanilla JS SVG sparklines) to an autonomous lab dashboard, see references/history-tracking-sparkline-pattern.md.
For reusable dashboard UX patterns (onboarding tours, data freshness badges, keyboard shortcuts, progressive disclosure inspectors, cross-linking between views), see references/dashboard-ux-patterns.md.
For the aggressive human-first inspector refinement โ when users report that details are hard to understand and the fix is to strip technical labels from the default view โ see references/progressive-disclosure-human-first.md.
For programmatic verification of CSS custom-property theme systems โ catching scoping bugs, confirming theme distinctness, and validating JS switching logic โ see references/theme-system-verification.md.
For Son's Discord-first autonomous experiments where a channel hosts a repeated multi-agent loop, use the Autonomous Discord Agent Lab pattern: create file-based durable state, a paused cron orchestrator delivered to discord:<channel_id>, then activate it from a user mission trigger. See references/autonomous-discord-agent-lab.md.
Webhooks
hermes webhook subscribe N Create route at /webhooks/<name>
hermes webhook list List subscriptions
hermes webhook remove NAME Remove a subscription
hermes webhook test NAME Send a test POST
Profiles
hermes profile list List all profiles
hermes profile create NAME Create (--clone, --clone-all, --clone-from)
hermes profile use NAME Set sticky default
hermes profile delete NAME Delete a profile
hermes profile show NAME Show details
hermes profile alias NAME Manage wrapper scripts
hermes profile rename A B Rename a profile
hermes profile export NAME Export to tar.gz
hermes profile import FILE Import from archive
Credential Pools
hermes auth add Interactive credential wizard
hermes auth list [PROVIDER] List pooled credentials
hermes auth remove P INDEX Remove by provider + index
hermes auth reset PROVIDER Clear exhaustion status
Other
hermes insights [--days N] Usage analytics
hermes update Update to latest version
hermes pairing list/approve/revoke DM authorization
hermes plugins list/install/remove Plugin management
hermes honcho setup/status Honcho memory integration (requires honcho plugin)
hermes memory setup/status/off Memory provider config
hermes completion bash|zsh Shell completions
hermes acp ACP server (IDE integration)
hermes claw migrate Migrate from OpenClaw
hermes uninstall Uninstall Hermes
---
Slash Commands (In-Session)
Type these during an interactive chat session. New commands land fairly
often; if something below looks stale, run /help in-session for the
authoritative list or see the [live slash commands reference](https://hermes-agent.nousresearch.com/docs/reference/slash-commands).
The registry of record is hermes_cli/commands.py โ every consumer
(autocomplete, Telegram menu, Slack mapping, /help) derives from it.
Session Control
/new (/reset) Fresh session
/clear Clear screen + new session (CLI)
/retry Resend last message
/undo Remove last exchange
/title [name] Name the session
/compress Manually compress context
/stop Kill background processes
/rollback [N] Restore filesystem checkpoint
/snapshot [sub] Create or restore state snapshots of Hermes config/state (CLI)
/background <prompt> Run prompt in background
/queue <prompt> Queue for next turn
/steer <prompt> Inject a message after the next tool call without interrupting
/agents (/tasks) Show active agents and running tasks
/resume [name] Resume a named session
/goal [text|sub] Set a standing goal Hermes works on across turns until achieved
(subcommands: status, pause, resume, clear)
/redraw Force a full UI repaint (CLI)
Configuration
/config Show config (CLI)
/model [name] Show or change model
/personality [name] Set personality
/reasoning [level] Set reasoning (none|minimal|low|medium|high|xhigh|show|hide)
/verbose Cycle: off โ new โ all โ verbose
/voice [on|off|tts] Voice mode
/yolo Toggle approval bypass
/busy [sub] Control what Enter does while Hermes is working (CLI)
(subcommands: queue, steer, interrupt, status)
/indicator [style] Pick the TUI busy-indicator style (CLI)
(styles: kaomoji, emoji, unicode, ascii)
/footer [on|off] Toggle gateway runtime-metadata footer on final replies
/skin [name] Change theme (CLI)
/statusbar Toggle status bar (CLI)
Tools & Skills
/tools Manage tools (CLI)
/toolsets List toolsets (CLI)
/skills Search/install skills (CLI)
/skill <name> Load a skill into session
/reload-skills Re-scan ~/.hermes/skills/ for added/removed skills
/reload Reload .env variables into the running session (CLI)
/reload-mcp Reload MCP servers
/cron Manage cron jobs (CLI)
/curator [sub] Background skill maintenance (status, run, pin, archive, โฆ)
/kanban [sub] Multi-profile collaboration board (tasks, links, comments)
/plugins List plugins (CLI)
Gateway
/approve Approve a pending command (gateway)
/deny Deny a pending command (gateway)
/restart Restart gateway (gateway)
/sethome Set current chat as home channel (gateway)
/update Update Hermes to latest (gateway)
/topic [sub] Enable or inspect Telegram DM topic sessions (gateway)
/platforms (/gateway) Show platform connection status (gateway)
Utility
/branch (/fork) Branch the current session
/fast Toggle priority/fast processing
/browser Open CDP browser connection
/history Show conversation history (CLI)
/save Save conversation to file (CLI)
/copy [N] Copy the last assistant response to clipboard (CLI)
/paste Attach clipboard image (CLI)
/image Attach local image file (CLI)
Info
/help Show commands
/commands [page] Browse all commands (gateway)
/usage Token usage
/insights [days] Usage analytics
/gquota Show Google Gemini Code Assist quota usage (CLI)
/status Session info (gateway)
/profile Active profile info
/debug Upload debug report (system info + logs) and get shareable links
Exit
/quit (/exit, /q) Exit CLI
---
Key Paths & Config
~/.hermes/config.yaml Main configuration
~/.hermes/.env API keys and secrets
$HERMES_HOME/skills/ Installed skills
~/.hermes/sessions/ Session transcripts
~/.hermes/logs/ Gateway and error logs
~/.hermes/auth.json OAuth tokens and credential pools
~/.hermes/hermes-agent/ Source code (if git-installed)
Profiles use ~/.hermes/profiles/<name>/ with the same layout.
Config Sections
Edit with hermes config edit or hermes config set section.key value.
| Section | Key options |
|---------|-------------|
| model | default, provider, base_url, api_key, context_length |
| agent | max_turns (90), tool_use_enforcement |
| terminal | backend (local/docker/ssh/modal), cwd, timeout (180) |
| compression | enabled, threshold (0.50), target_ratio (0.20) |
| display | skin, tool_progress, show_reasoning, show_cost |
| stt | enabled, provider (local/groq/openai/mistral) |
| tts | provider (edge/elevenlabs/openai/minimax/mistral/neutts) |
| memory | memory_enabled, user_profile_enabled, provider |
| security | tirith_enabled, website_blocklist |
| delegation | model, provider, base_url, api_key, max_iterations (50), reasoning_effort |
| checkpoints | enabled, max_snapshots (50) |
| fallback_model | provider, model, base_url, key_env |
Fallback Providers
Hermes can automatically fail over to a backup provider:model when the primary is unavailable. This is turn-scoped โ each new user message starts with the primary restored; fallback only activates mid-turn when the primary fails.
Configuration ( ~/.hermes/config.yaml):
fallback_model:
provider: opencode-go
model: kimi-k2.6
Or use the interactive manager:
hermes fallback add # interactive picker
hermes fallback list # show fallback chain
hermes fallback remove # remove by index
Legacy note: fallback_model (singular) is the legacy single-fallback key. fallback_providers (list) supports multiple ordered fallbacks. When both exist, fallback_providers takes priority.
Trigger conditions (after exhausting retries where applicable):
- Rate limits (HTTP 429)
- Server errors (HTTP 500, 502, 503)
- Auth failures (HTTP 401, 403) โ immediately
- Not found (HTTP 404) โ immediately
- Invalid / empty responses repeatedly
Supported providers include all standard providers (OpenRouter, Anthropic, OpenCode Go/ Zen, Kimi, etc.) plus custom endpoints with base_url + key_env. Full provider docs: https://hermes-agent.nousresearch.com/docs/integrations/providers
Limitations:
- Subagent delegation does not inherit fallback config
- Cron jobs do not use fallback (use per-job provider/model overrides)
- Auxiliary tasks (vision, compression, etc.) use their own
auxiliary.* provider chain
For a deep-dive with worked examples and model lists, see references/fallback-providers.md.
Full config reference: https://hermes-agent.nousresearch.com/docs/user-guide/configuration
Providers
20+ providers supported. Set via hermes model or hermes setup.
| Provider | Auth | Key env var |
|----------|------|-------------|
| OpenRouter | API key | OPENROUTER_API_KEY |
| Anthropic | API key | ANTHROPIC_API_KEY |
| Nous Portal | OAuth | hermes auth |
| OpenAI Codex | OAuth | hermes auth |
| GitHub Copilot | Token | COPILOT_GITHUB_TOKEN |
| Google Gemini | API key | GOOGLE_API_KEY or GEMINI_API_KEY |
| DeepSeek | API key | DEEPSEEK_API_KEY |
| xAI / Grok | API key | XAI_API_KEY |
| Hugging Face | Token | HF_TOKEN |
| Z.AI / GLM | API key | GLM_API_KEY |
| MiniMax | API key | MINIMAX_API_KEY |
| MiniMax CN | API key | MINIMAX_CN_API_KEY |
| Kimi / Moonshot | API key | KIMI_API_KEY |
| Alibaba / DashScope | API key | DASHSCOPE_API_KEY |
| Xiaomi MiMo | API key | XIAOMI_API_KEY |
| Kilo Code | API key | KILOCODE_API_KEY |
| AI Gateway (Vercel) | API key | AI_GATEWAY_API_KEY |
| OpenCode Zen | API key | OPENCODE_ZEN_API_KEY |
| OpenCode Go | API key | OPENCODE_GO_API_KEY |
| Qwen OAuth | OAuth | hermes auth add qwen-oauth |
| Custom endpoint | Config | model.base_url + model.api_key in config.yaml |
| GitHub Copilot ACP | External | COPILOT_CLI_PATH or Copilot CLI |
Full provider docs: https://hermes-agent.nousresearch.com/docs/integrations/providers
Toolsets
Enable/disable via hermes tools (interactive) or hermes tools enable/disable NAME.
| Toolset | What it provides |
|---------|-----------------|
| web | Web search and content extraction |
| search | Web search only (subset of web) |
| browser | Browser automation (Browserbase, Camofox, or local Chromium) |
| terminal | Shell commands and process management |
| file | File read/write/search/patch |
| code_execution | Sandboxed Python execution |
| vision | Image analysis |
| image_gen | AI image generation |
| video | Video analysis and generation |
| tts | Text-to-speech |
| skills | Skill browsing and management |
| memory | Persistent cross-session memory |
| session_search | Search past conversations |
| delegation | Subagent task delegation |
| cronjob | Scheduled task management |
| clarify | Ask user clarifying questions |
| messaging | Cross-platform message sending |
| todo | In-session task planning and tracking |
| kanban | Multi-agent work-queue tools (gated to workers) |
| debugging | Extra introspection/debug tools (off by default) |
| safe | Minimal, low-risk toolset for locked-down sessions |
| spotify | Spotify playback and playlist control |
| homeassistant | Smart home control (off by default) |
| discord | Discord integration tools |
| discord_admin | Discord admin/moderation tools |
| feishu_doc | Feishu (Lark) document tools |
| feishu_drive | Feishu (Lark) drive tools |
| yuanbao | Yuanbao integration tools |
| rl | Reinforcement learning tools (off by default) |
| moa | Mixture of Agents (off by default) |
Full enumeration lives in toolsets.py as the TOOLSETS dict; _HERMES_CORE_TOOLS is the default bundle most platforms inherit from.
Tool changes take effect on /reset (new session). They do NOT apply mid-conversation to preserve prompt caching.
---
Security & Privacy Toggles
Common "why is Hermes doing X to my output / tool calls / commands?" toggles โ and the exact commands to change them. Most of these need a fresh session (/reset in chat, or start a new hermes invocation) because they're read once at startup.
Secret redaction in tool output
Secret redaction is off by default โ tool output (terminal stdout, read_file, web content, subagent summaries, etc.) passes through unmodified. If the user wants Hermes to auto-mask strings that look like API keys, tokens, and secrets before they enter the conversation context and logs:
hermes config set security.redact_secrets true # enable globally
Restart required. security.redact_secrets is snapshotted at import time โ toggling it mid-session (e.g. via export HERMES_REDACT_SECRETS=true from a tool call) will NOT take effect for the running process. Tell the user to run hermes config set security.redact_secrets true in a terminal, then start a new session. This is deliberate โ it prevents an LLM from flipping the toggle on itself mid-task.
Disable again with:
hermes config set security.redact_secrets false
PII redaction in gateway messages
Separate from secret redaction. When enabled, the gateway hashes user IDs and strips phone numbers from the session context before it reaches the model:
hermes config set privacy.redact_pii true # enable
hermes config set privacy.redact_pii false # disable (default)
Command approval prompts
By default (approvals.mode: manual), Hermes prompts the user before running shell commands flagged as destructive (rm -rf, git reset --hard, etc.). The modes are:
manual โ always prompt (default)
smart โ use an auxiliary LLM to auto-approve low-risk commands, prompt on high-risk
off โ skip all approval prompts (equivalent to --yolo)
hermes config set approvals.mode smart # recommended middle ground
hermes config set approvals.mode off # bypass everything (not recommended)
Per-invocation bypass without changing config:
hermes --yolo โฆ
export HERMES_YOLO_MODE=1
Note: YOLO / approvals.mode: off does NOT turn off secret redaction. They are independent.
Shell hooks allowlist
Some shell-hook integrations require explicit allowlisting before they fire. Managed via ~/.hermes/shell-hooks-allowlist.json โ prompted interactively the first time a hook wants to run.
Disabling the web/browser/image-gen tools
To keep the model away from network or media tools entirely, open hermes tools and toggle per-platform. Takes effect on next session (/reset). See the Tools & Skills section above.
---
Voice & Transcription
STT (Voice โ Text)
Voice messages from messaging platforms are auto-transcribed.
Provider priority (auto-detected):
1. Local faster-whisper โ free, no API key: pip install faster-whisper
2. Groq Whisper โ free tier: set GROQ_API_KEY
3. OpenAI Whisper โ paid: set VOICE_TOOLS_OPENAI_KEY
4. Mistral Voxtral โ set MISTRAL_API_KEY
Config:
stt:
enabled: true
provider: local # local, groq, openai, mistral
local:
model: base # tiny, base, small, medium, large-v3
TTS (Text โ Voice)
| Provider | Env var | Free? |
|----------|---------|-------|
| Edge TTS | None | Yes (default) |
| ElevenLabs | ELEVENLABS_API_KEY | Free tier |
| OpenAI | VOICE_TOOLS_OPENAI_KEY | Paid |
| MiniMax | MINIMAX_API_KEY | Paid |
| Mistral (Voxtral) | MISTRAL_API_KEY | Paid |
| NeuTTS (local) | None (pip install neutts[all] + espeak-ng) | Free |
Voice commands: /voice on (voice-to-voice), /voice tts (always voice), /voice off.
---
Spawning Additional Hermes Instances
Run additional Hermes processes as fully independent subprocesses โ separate sessions, tools, and environments.
When to Use This vs delegate_task
| | delegate_task | Spawning hermes process |
|-|-----------------|--------------------------|
| Isolation | Separate conversation, shared process | Fully independent process |
| Duration | Minutes (bounded by parent loop) | Hours/days |
| Tool access | Subset of parent's tools | Full tool access |
| Interactive | No | Yes (PTY mode) |
| Use case | Quick parallel subtasks | Long autonomous missions |
One-Shot Mode
terminal(command="hermes chat -q 'Research GRPO papers and write summary to ~/research/grpo.md'", timeout=300)
Background for long tasks:
terminal(command="hermes chat -q 'Set up CI/CD for ~/myapp'", background=true)
Interactive PTY Mode (via tmux)
Hermes uses prompt_toolkit, which requires a real terminal. Use tmux for interactive spawning:
Start
terminal(command="tmux new-session -d -s agent1 -x 120 -y 40 'hermes'", timeout=10)
Wait for startup, then send a message
terminal(command="sleep 8 && tmux send-keys -t agent1 'Build a FastAPI auth service' Enter", timeout=15)
Read output
terminal(command="sleep 20 && tmux capture-pane -t agent1 -p", timeout=5)
Send follow-up
terminal(command="tmux send-keys -t agent1 'Add rate limiting middleware' Enter", timeout=5)
Exit
terminal(command="tmux send-keys -t agent1 '/exit' Enter && sleep 2 && tmux kill-session -t agent1", timeout=10)
Multi-Agent Coordination
Agent A: backend
terminal(command="tmux new-session -d -s backend -x 120 -y 40 'hermes -w'", timeout=10)
terminal(command="sleep 8 && tmux send-keys -t backend 'Build REST API for user management' Enter", timeout=15)
Agent B: frontend
terminal(command="tmux new-session -d -s frontend -x 120 -y 40 'hermes -w'", timeout=10)
terminal(command="sleep 8 && tmux send-keys -t frontend 'Build React dashboard for user management' Enter", timeout=15)
Check progress, relay context between them
terminal(command="tmux capture-pane -t backend -p | tail -30", timeout=5)
terminal(command="tmux send-keys -t frontend 'Here is the API schema from the backend agent: ...' Enter", timeout=5)
Session Resume
Resume most recent session
terminal(command="tmux new-session -d -s resumed 'hermes --continue'", timeout=10)
Resume specific session
terminal(command="tmux new-session -d -s resumed 'hermes --resume 20260225_143052_a1b2c3'", timeout=10)
Tips
- Prefer
delegate_task for quick subtasks โ less overhead than spawning a full process
- Use
-w (worktree mode) when spawning agents that edit code โ prevents git conflicts
- Set timeouts for one-shot mode โ complex tasks can take 5-10 minutes
- Use
hermes chat -q for fire-and-forget โ no PTY needed
- Use tmux for interactive sessions โ raw PTY mode has
\r vs \n issues with prompt_toolkit
- For scheduled tasks, use the
cronjob tool instead of spawning โ handles delivery and retry
---
Durable & Background Systems
Four systems run alongside the main conversation loop. Quick reference
here; full developer notes live in AGENTS.md, user-facing docs under
website/docs/user-guide/features/.
Delegation (delegate_task)
Synchronous subagent spawn โ the parent waits for the child's summary
before continuing its own loop. Isolated context + terminal session.
- Single:
delegate_task(goal, context, toolsets).
- Batch:
delegate_task(tasks=[{goal, ...}, ...]) runs children in
parallel, capped by delegation.max_concurrent_children (default 3).
- Roles:
leaf (default; cannot re-delegate) vs orchestrator
(can spawn its own workers, bounded by delegation.max_spawn_depth).
- Not durable. If the parent is interrupted, the child is
cancelled. For work that must outlive the turn, use cronjob or
terminal(background=True, notify_on_complete=True).
Config: delegation.* in config.yaml.
Tuning max_concurrent_children
Default is 3. Rule of thumb for raising it:
- Light tasks (web search, file grep): up to
6-8
- Medium tasks (code execution, browser):
4-5
- Heavy tasks (builds, large data):
2-3
- Actual bottleneck is usually the API rate limit, not local CPU/RAM. On a 10-core M4 with 16GB RAM, CPU is rarely the constraint.
- Formula: start at
5, raise only if profiling shows idle time between API responses.
Cron (scheduled jobs)
Durable scheduler โ cron/jobs.py + cron/scheduler.py. Drive it via
the cronjob tool, the hermes cron CLI (list, add, edit,
pause, resume, run, remove), or the /cron slash command.
- Schedules: duration (
"30m", "2h"), "every" phrase
( "every monday 9am"), 5-field cron ( "0 9 *"), or ISO timestamp.
- Per-job knobs:
skills, model/provider override, script
(pre-run data collection; no_agent=True makes the script the whole
job), context_from (chain job A's output into job B), workdir
(run in a specific dir with its AGENTS.md / CLAUDE.md loaded),
multi-platform delivery.
- Invariants: 3-minute hard interrupt per run,
.tick.lock file
prevents duplicate ticks across processes, cron sessions pass
skip_memory=True by default, and cron deliveries are framed with a
header/footer instead of being mirrored into the target gateway
session (keeps role alternation intact).
User docs: https://hermes-agent.nousresearch.com/docs/user-guide/features/cron
Curator (skill lifecycle)
Background maintenance for agent-created skills. Tracks usage, marks
idle skills stale, archives stale ones, keeps a pre-run tar.gz backup
so nothing is lost.
- CLI:
hermes curator <verb> โ status, run, pause, resume,
pin, unpin, archive, restore, prune, backup, rollback.
- Slash:
/curator <subcommand> mirrors the CLI.
- Scope: only touches skills with
created_by: "agent" provenance.
Bundled + hub-installed skills are off-limits. Never deletes โ
max destructive action is archive. Pinned skills are exempt from
every auto-transition and every LLM review pass.
- Telemetry: sidecar at
~/.hermes/skills/.usage.json holds
per-skill use_count, view_count, patch_count,
last_activity_at, state, pinned.
Config: curator.* (enabled, interval_hours, min_idle_hours,
stale_after_days, archive_after_days, backup.*).
User docs: https://hermes-agent.nousresearch.com/docs/user-guide/features/curator
Dreaming (periodic memory/skill consolidation)
For Anthropic-style "dreaming" workflows, combine cron + session_search + memory + skills + curator into a scheduled review loop. Start with a weekly, proposal-only report that audits recent sessions, repeated user corrections, memory conflicts, skill patch candidates, and cron/automation improvements. Do not automatically delete/replace memory or patch/archive skills unless the user explicitly approves the proposed changes. See references/weekly-dreaming-routine.md for the recommended prompt, report format, safety policy, and cron creation pattern.
Kanban (multi-agent work queue)
Durable SQLite board for multi-profile / multi-worker collaboration.
Users drive it via hermes kanban <verb>; dispatcher-spawned workers
see a focused kanban_* toolset gated by HERMES_KANBAN_TASK so the
schema footprint is zero outside worker processes.
- CLI verbs (common):
init, create, list (alias ls),
show, assign, link, unlink, comment, complete, block,
unblock, archive, tail. Less common: watch, stats, runs,
log, dispatch, daemon, gc.
- Worker toolset:
kanban_show, kanban_complete, kanban_block,
kanban_heartbeat, kanban_comment, kanban_create, kanban_link.
- Dispatcher runs inside the gateway by default
( kanban.dispatch_in_gateway: true) โ reclaims stale claims,
promotes ready tasks, atomically claims, spawns assigned profiles.
Auto-blocks a task after ~5 consecutive spawn failures.
- Isolation: board is the hard boundary (workers get
HERMES_KANBAN_BOARD pinned in env); tenant is a soft namespace
within a board for workspace-path + memory-key isolation.
User docs: https://hermes-agent.nousresearch.com/docs/user-guide/features/kanban
Log Relay (Hermes โ Discord)
A background Python script that tails ~/.hermes/logs/*.log and batches lines to a Discord channel. Includes session-ID extraction, rate-limit handling, and auto-restart via launchd/systemd. Useful for remote monitoring and audit trails.
- Reference:
references/discord-log-relay.md โ full setup, tuning, macOS/Linux service install, pitfalls.
- Template:
templates/discord-log-relay.py โ copy, set CHANNEL_ID, and deploy.
- Discord operations:
references/discord-operating-planes.md โ channel-purpose routing, periodic-summary vs Dreaming report formats, and safety/cost notes for Discord-first Hermes deployments.
Key pitfall: ask the user about batch frequency upfront rather than defaulting to real-time streaming. Most users prefer 10-minute or hourly batches. High-volume raw logs should be batched, summarized, or stored out-of-band; avoid Discord message storms during error loops.
Weekly Dreaming / Memory Curation
For long-running Hermes deployments, users may want an Anthropic-style "Dreaming" loop: a scheduled review that consolidates experience, proposes memory/skill/cron changes, and identifies what to keep, weaken, archive, or delete. Hermes has the building blocks (sessions, session_search, memory, skills, curator, cron), but the safe default is proposal mode:
1. Inspect recent usage and sessions.
2. Extract repeated success patterns, failure patterns, and user corrections.
3. Propose memory updates/removals without applying them silently.
4. Propose skill patches/archive candidates and cron/reporting improvements.
5. End with explicit approval checkboxes.
Do not silently rewrite or delete memory/skills from a Dreaming report unless the user explicitly authorized automatic application. See references/discord-operating-planes.md for a report template and routing heuristics.
---
Windows-Specific Quirks
Hermes runs natively on Windows (PowerShell, cmd, Windows Terminal, git-bash
mintty, VS Code integrated terminal). Most of it just works, but a handful
of differences between Win32 and POSIX have bitten us โ document new ones
here as you hit them so the next person (or the next session) doesn't
rediscover them from scratch.
Input / Keybindings
Alt+Enter doesn't insert a newline. Windows Terminal intercepts Alt+Enter
at the terminal layer to toggle fullscreen โ the keystroke never reaches
prompt_toolkit. Use Ctrl+Enter instead. Windows Terminal delivers
Ctrl+Enter as LF ( c-j), distinct from plain Enter ( c-m / CR), and the
CLI binds c-j to newline insertion on win32 only (see
_bind_prompt_submit_keys + the Windows-only c-j binding in cli.py).
Side effect: the raw Ctrl+J keystroke also inserts a newline on Windows โ
unavoidable, because Windows Terminal collapses Ctrl+Enter and Ctrl+J to
the same keycode at the Win32 console API layer. No conflicting binding
existed for Ctrl+J on Windows, so this is a harmless side effect.
mintty / git-bash behaves the same (fullscreen on Alt+Enter) unless you
disable Alt+Fn shortcuts in Options โ Keys. Easier to just use Ctrl+Enter.
Diagnosing keybindings. Run python scripts/keystroke_diagnostic.py
(repo root) to see exactly how prompt_toolkit identifies each keystroke
in the current terminal. Answers questions like "does Shift+Enter come
through as a distinct key?" (almost never โ most terminals collapse it
to plain Enter) or "what byte sequence is my terminal sending for
Ctrl+Enter?" This is how the Ctrl+Enter = c-j fact was established.
Config / Files
HTTP 400 "No models provided" on first run. config.yaml was saved
with a UTF-8 BOM (common when Windows apps write it). Re-save as UTF-8
without BOM. hermes config edit writes without BOM; manual edits in
Notepad are the usual culprit.
execute_code / Sandbox
WinError 10106 ("The requested service provider could not be loaded
or initialized") from the sandbox child process โ it can't create an
AF_INET socket, so the loopback-TCP RPC fallback fails before
connect(). Root cause is usually not a broken Winsock LSP; it's
Hermes's own env scrubber dropping SYSTEMROOT / WINDIR / COMSPEC
from the child env. Python's socket module needs SYSTEMROOT to locate
mswsock.dll. Fixed via the _WINDOWS_ESSENTIAL_ENV_VARS allowlist in
tools/code_execution_tool.py. If you still hit it, echo os.environ
inside an execute_code block to confirm SYSTEMROOT is set. Full
diagnostic recipe in references/execute-code-sandbox-env-windows.md.
Testing / Contributing
scripts/run_tests.sh doesn't work as-is on Windows โ it looks for
POSIX venv layouts ( .venv/bin/activate). The Hermes-installed venv at
venv/Scripts/ has no pip or pytest either (stripped for install size).
Workaround: install pytest + pytest-xdist + pyyaml into a system Python
3.11 user site, then invoke pytest directly with PYTHONPATH set:
"/c/Program Files/Python311/python" -m pip install --user pytest pytest-xdist pyyaml
export PYTHONPATH="$(pwd)"
"/c/Program Files/Python311/python" -m pytest tests/foo/test_bar.py -v --tb=short -n 0
Use -n 0, not -n 4 โ pyproject.toml's default addopts already
includes -n, and the wrapper's CI-parity guarantees don't apply off POSIX.
POSIX-only tests need skip guards. Common markers already in the codebase:
- Symlinks โ elevated privileges on Windows
0o600 file modes โ POSIX mode bits not enforced on NTFS by default
signal.SIGALRM โ Unix-only (see tests/conftest.py::_enforce_test_timeout)
- Winsock / Windows-specific regressions โ
@pytest.mark.skipif(sys.platform != "win32", ...)
Use the existing skip-pattern style (sys.platform == "win32" or
sys.platform.startswith("win")) to stay consistent with the rest of the
suite.
Path / Filesystem
Line endings. Git may warn LF will be replaced by CRLF the next time
Git touches it. Cosmetic โ the repo's .gitattributes normalizes. Don't
let editors auto-convert committed POSIX-newline files to CRLF.
Forward slashes work almost everywhere. C:/Users/... is accepted by
every Hermes tool and most Windows APIs. Prefer forward slashes in code
and logs โ avoids shell-escaping backslashes in bash.
---
Troubleshooting
Voice not working
1. Check stt.enabled: true in config.yaml
2. Verify provider: pip install faster-whisper or set API key
3. In gateway: /restart. In CLI: exit and relaunch.
Tool not available
1. hermes tools โ check if toolset is enabled for your platform
2. Some tools need env vars (check .env)
3. /reset after enabling tools
Model/provider issues
1. hermes doctor โ check config and dependencies
2. hermes auth add <provider> โ re-authenticate OAuth providers (use --type oauth)
3. Check .env has the right API key
4. Copilot 403: gh auth login tokens do NOT work for Copilot API. You must use the Copilot-specific OAuth device code flow via hermes model โ GitHub Copilot.
Changes not taking effect
- Tools/skills:
/reset starts a new session with updated toolset
- Config changes: In gateway:
/restart. In CLI: exit and relaunch.
- Code changes: Restart the CLI or gateway process
Deployed web dashboard shows stale CSS or theme changes
- Browser cache: Add
?v=N cache-busting query strings to CSS/JS/theme links in HTML.
- Service Worker cache: Bump
CACHE_NAME in sw.js to invalidate old shell caches.
- Data freshness: Use
fetch(url, {cache:'no-store'}) for live JSON feeds.
- See
references/static-site-cache-invalidation.md for the full diagnostic recipe.
Dashboard inspector feels too technical
- The default inspector view should contain only plain-language sentences: headline, "what they're doing now", "why it matters", and a silent visual progress bar (no text label).
- Move all technical fields (source IDs, confidence scores, progress labels, status slugs, badges) behind a "Show technical details" toggle.
- If users say "details are hard to understand," the fix is to remove more fields from the default view, not to add explanations. Explanations of technical fields are still technical.
- See
references/progressive-disclosure-human-first.md for the aggressive simplification pattern.
Skills not showing
1. hermes skills list โ verify installed
2. hermes skills config โ check platform enablement
3. Load explicitly: /skill name or hermes -s name
Gateway issues
Check logs first:
grep -i "failed to send\|error" ~/.hermes/logs/gateway.log | tail -20
Common gateway problems:
- Gateway dies on SSH logout: Enable linger:
sudo loginctl enable-linger $USER
- Gateway dies on WSL2 close: WSL2 requires
systemd=true in /etc/wsl.conf for systemd services to work. Without it, gateway falls back to nohup (dies when session closes).
- Gateway crash loop: Reset the failed state:
systemctl --user reset-failed hermes-gateway
- macOS: bot shows offline after idle time: The gateway runs as a user agent (
LimitLoadToSessionType=Aqua), so macOS suspends it when the system sleeps. The platform websocket drops and the bot appears offline until the network returns. Fix: keep the Mac awake (System Settings -> Energy -> Prevent automatic sleeping, or caffeinate -d -i -s -u &). Low Power Mode makes this worse, not better. See references/macos-gateway-sleep-disconnect.md for the full diagnostic recipe.
Platform-specific issues
- Discord bot silent: Must enable Message Content Intent in Bot โ Privileged Gateway Intents. See full Discord setup reference:
references/discord-gateway-setup.md.
- Slack bot only works in DMs: Must subscribe to
message.channels event. Without it, the bot ignores public channels.
- Windows-specific issues (
Alt+Enter newline, WinError 10106, UTF-8 BOM config, test suite, line endings): see the dedicated Windows-Specific Quirks section above.
Auxiliary models not working
If auxiliary tasks (vision, compression, session_search) fail silently, the auto provider can't find a backend. Either set OPENROUTER_API_KEY or GOOGLE_API_KEY, or explicitly configure each auxiliary task's provider:
hermes config set auxiliary.vision.provider <your_provider>
hermes config set auxiliary.vision.model <model_name>
Full system auth provisioning
For a one-shot workflow to maximize available credentials โ installing gh, generating SSH keys, configuring git, enabling all Hermes toolsets, and auditing current auth state โ see references/system-auth-setup.md.
Editing large files with patch
When a file is read with read_file(offset=...) (pagination), the tool warns that the view is partial. If you attempt patch without re-reading the full file first, you will likely hit non-unique match errors or corrupt the file. Fix: always call read_file without offset to load the whole file before patching. For append-only updates (e.g., adding a cycle log entry to state.md), do not use terminal(command="cat >> file << 'EOF'...EOF") โ the terminal tool on macOS/Linux misinterprets heredoc << as backgrounding and fails. Instead, write a short Python script via write_file and execute it with terminal(command="python3 /tmp/script.py"). See references/terminal-heredoc-workaround.md for the full pattern.
Sibling subagent file overwrites
When multiple subagents are running in parallel (e.g. via delegate_task batch mode or kanban worker lanes), a file may be modified by one subagent while another is about to write to it. If you use write_file or patch on a file that was last read before a sibling subagent modified it, your write may silently truncate or revert the sibling's changes. The tool may show a warning like "this file was modified by sibling subagent X but this agent never read it."
Fix:
1. Heed the warning. If the tool reports a sibling modification, re-read the file with read_file before writing.
2. Prefer patch over write_file for partial updates โ patch only changes the matched region and is less likely to wipe unrelated content.
3. If the file is already published/deployed, and the local working copy gets corrupted, recover from the published copy:
cp ~/hermes-web/agent-pets/css/dashboard.css ~/.hermes/autonomous-agent-lab/pixel-pet-ops/web/css/dashboard.css
4. For append-only updates, write a small Python script and execute it rather than using write_file on the whole file.
Prevention: In kanban/multi-agent workflows, assign file-level ownership so only one worker touches each file. If parallel workers must edit the same file, have them write to separate temp files and let the orchestrator merge.
---
Windows-Specific Quirks
| Looking for... | Location |
|----------------|----------|
| Config options | hermes config edit or [Configuration docs](https://hermes-agent.nousresearch.com/docs/user-guide/configuration) |
| Available tools | hermes tools list or [Tools reference](https://hermes-agent.nousresearch.com/docs/reference/tools-reference) |
| Slash commands | /help in session or [Slash commands reference](https://hermes-agent.nousresearch.com/docs/reference/slash-commands) |
| Skills catalog | hermes skills browse or [Skills catalog](https://hermes-agent.nousresearch.com/docs/reference/skills-catalog) |
| Provider setup | hermes model or [Providers guide](https://hermes-agent.nousresearch.com/docs/integrations/providers) |
| Platform setup | hermes gateway setup or [Messaging docs](https://hermes-agent.nousresearch.com/docs/user-guide/messaging/) |
| MCP servers | hermes mcp list or [MCP guide](https://hermes-agent.nousresearch.com/docs/user-guide/features/mcp) |
| Profiles | hermes profile list or [Profiles docs](https://hermes-agent.nousresearch.com/docs/user-guide/profiles) |
| Cron jobs | hermes cron list or [Cron docs](https://hermes-agent.nousresearch.com/docs/user-guide/features/cron) |
| Memory | hermes memory status or [Memory docs](https://hermes-agent.nousresearch.com/docs/user-guide/features/memory) |
| Env variables | hermes config env-path or [Env vars reference](https://hermes-agent.nousresearch.com/docs/reference/environment-variables) |
| CLI commands | hermes --help or [CLI reference](https://hermes-agent.nousresearch.com/docs/reference/cli-commands) |
| Gateway logs | ~/.hermes/logs/gateway.log |
| Session files | ~/.hermes/sessions/ or hermes sessions browse |
| Source code | ~/.hermes/hermes-agent/ |
---
Contributor Quick Reference
For occasional contributors and PR authors. Full developer docs: https://hermes-agent.nousresearch.com/docs/developer-guide/
Project Layout
hermes-agent/
โโโ run_agent.py # AIAgent โ core conversation loop
โโโ model_tools.py # Tool discovery and dispatch
โโโ toolsets.py # Toolset definitions
โโโ cli.py # Interactive CLI (HermesCLI)
โโโ hermes_state.py # SQLite session store
โโโ agent/ # Prompt builder, context compression, memory, model routing, credential pooling, skill dispatch
โโโ hermes_cli/ # CLI subcommands, config, setup, commands
โ โโโ commands.py # Slash command registry (CommandDef)
โ โโโ config.py # DEFAULT_CONFIG, env var definitions
โ โโโ main.py # CLI entry point and argparse
โโโ tools/ # One file per tool
โ โโโ registry.py # Central tool registry
โโโ gateway/ # Messaging gateway
โ โโโ platforms/ # Platform adapters (telegram, discord, etc.)
โโโ cron/ # Job scheduler
โโโ tests/ # ~3000 pytest tests
โโโ website/ # Docusaurus docs site
Config: ~/.hermes/config.yaml (settings), ~/.hermes/.env (API keys).
Adding a Tool (3 files)
1. Create tools/your_tool.py:
import json, os
from tools.registry import registry
def check_requirements() -> bool:
return bool(os.getenv("EXAMPLE_API_KEY"))
def example_tool(param: str, task_id: str = None) -> str:
return json.dumps({"success": True, "data": "..."})
registry.register(
name="example_tool",
toolset="example",
schema={"name": "example_tool", "description": "...", "parameters": {...}},
handler=lambda args, **kw: example_tool(
param=args.get("param", ""), task_id=kw.get("task_id")),
check_fn=check_requirements,
requires_env=["EXAMPLE_API_KEY"],
)
2. Add to toolsets.py โ _HERMES_CORE_TOOLS list.
Auto-discovery: any tools/*.py file with a top-level registry.register() call is imported automatically โ no manual list needed.
All handlers must return JSON strings. Use get_hermes_home() for paths, never hardcode ~/.hermes.
Adding a Slash Command
1. Add CommandDef to COMMAND_REGISTRY in hermes_cli/commands.py
2. Add handler in cli.py โ process_command()
3. (Optional) Add gateway handler in gateway/run.py
All consumers (help text, autocomplete, Telegram menu, Slack mapping) derive from the central registry automatically.
Agent Loop (High Level)
run_conversation():
1. Build system prompt
2. Loop while iterations < max:
a. Call LLM (OpenAI-format messages + tool schemas)
b. If tool_calls โ dispatch each via handle_function_call() โ append results โ continue
c. If text response โ return
3. Context compression triggers automatically near token limit
Testing
python -m pytest tests/ -o 'addopts=' -q # Full suite
python -m pytest tests/tools/ -q # Specific area
- Tests auto-redirect
HERMES_HOME to temp dirs โ never touch real ~/.hermes/
- Run full suite before pushing any change
- Use
-o 'addopts=' to clear any baked-in pytest flags
Windows contributors: scripts/run_tests.sh currently looks for POSIX venvs ( .venv/bin/activate / venv/bin/activate) and will error out on Windows where the layout is venv/Scripts/activate + python.exe. The Hermes-installed venv at venv/Scripts/ also has no pip or pytest โ it's stripped for end-user install size. Workaround: install pytest + pytest-xdist + pyyaml into a system Python 3.11 user site ( /c/Program Files/Python311/python -m pip install --user pytest pytest-xdist pyyaml), then run tests directly:
export PYTHONPATH="$(pwd)"
"/c/Program Files/Python311/python" -m pytest tests/tools/test_foo.py -v --tb=short -n 0
Use -n 0 (not -n 4) because pyproject.toml's default addopts already includes -n, and the wrapper's CI-parity story doesn't apply off-POSIX.
Cross-platform test guards: tests that use POSIX-only syscalls need a skip marker. Common ones already in the codebase:
- Symlink creation โ
@pytest.mark.skipif(sys.platform == "win32", reason="Symlinks require elevated privileges on Windows") (see tests/cron/test_cron_script.py)
- POSIX file modes (0o600, etc.) โ
@pytest.mark.skipif(sys.platform.startswith("win"), reason="POSIX mode bits not enforced on Windows") (see tests/hermes_cli/test_auth_toctou_file_modes.py)
signal.SIGALRM โ Unix-only (see tests/conftest.py::_enforce_test_timeout)
- Live Winsock / Windows-specific regression tests โ
@pytest.mark.skipif(sys.platform != "win32", reason="Windows-specific regression")
Monkeypatching sys.platform is not enough when the code under test also calls platform.system() / platform.release() / platform.mac_ver(). Those functions re-read the real OS independently, so a test that sets sys.platform = "linux" on a Windows runner will still see platform.system() == "Windows" and route through the Windows branch. Patch all three together:
monkeypatch.setattr(sys, "platform", "linux")
monkeypatch.setattr(platform, "system", lambda: "Linux")
monkeypatch.setattr(platform, "release", lambda: "6.8.0-generic")
See tests/agent/test_prompt_builder.py::TestEnvironmentHints for a worked example.
Extending the system prompt's execution-environment block
Factual guidance about the host OS, user home, cwd, terminal backend, and shell (bash vs. PowerShell on Windows) is emitted from agent/prompt_builder.py::build_environment_hints(). This is also where the WSL hint and per-backend probe logic live. The convention:
- Local terminal backend โ emit host info (OS,
$HOME, cwd) + Windows-specific notes (hostname โ username, terminal uses bash not PowerShell).
- Remote terminal backend (anything in
_REMOTE_TERMINAL_BACKENDS: docker, singularity, modal, daytona, ssh, vercel_sandbox, managed_modal) โ suppress host info entirely and describe only the backend. A live uname/whoami/pwd probe runs inside the backend via tools.environments.get_environment(...).execute(...), cached per process in _BACKEND_PROBE_CACHE, with a static fallback if the probe times out.
- Key fact for prompt authoring: when
TERMINAL_ENV != "local", every file tool (read_file, write_file, patch, search_files) runs inside the backend container, not on the host. The system prompt must never describe the host in that case โ the agent can't touch it.
Full design notes, the exact emitted strings, and testing pitfalls:
references/prompt-builder-environment-hints.md.
Refactor-safety pattern (POSIX-equivalence guard): when you extract inline logic into a helper that adds Windows/platform-specific behavior, keep a _legacy_<name> oracle function in the test file that's a verbatim copy of the old code, then parametrize-diff against it. Example: tests/tools/test_code_execution_windows_env.py::TestPosixEquivalence. This locks in the invariant that POSIX behavior is bit-for-bit identical and makes any future drift fail loudly with a clear diff.
Commit Conventions
type: concise subject line
Optional body.
Types: fix:, feat:, refactor:, docs:, chore:
Key Rules
- Never break prompt caching โ don't change context, tools, or system prompt mid-conversation
- Message role alternation โ never two assistant or two user messages in a row
- Use
get_hermes_home() from hermes_constants for all paths (profile-safe)
- Config values go in
config.yaml, secrets go in .env
- New tools need a
check_fn so they only appear when requirements are met
[IMPORTANT: The user has invoked the "kanban-orchestrator" skill, indicating they want you to follow its instructions. The full skill content is loaded below.]
---
name: kanban-orchestrator
description: Decomposition playbook + anti-temptation rules for an orchestrator profile routing work through Kanban. The "don't do the work yourself" rule and the basic lifecycle are auto-injected into every kanban worker's system prompt; this skill is the deeper playbook when you're specifically playing the orchestrator role.
version: 3.0.0
platforms: [linux, macos, windows]
metadata:
hermes:
tags: [kanban, multi-agent, orchestration, routing]
related_skills: [kanban-worker]
---
Kanban Orchestrator โ Decomposition Playbook
> The core worker lifecycle (including the kanban_create fan-out pattern and the "decompose, don't execute" rule) is auto-injected into every kanban process via the KANBAN_GUIDANCE system-prompt block. This skill is the deeper playbook when you're an orchestrator profile whose whole job is routing.
Profiles are user-configured โ not a fixed roster
Hermes setups vary widely. Some users run a single profile that does everything; some run a small fleet (docker-worker, cron-worker); some run a curated specialist team they've named themselves. There is no default specialist roster โ the orchestrator skill does not know what profiles exist on this machine.
Before fanning out, you must ground the decomposition in the profiles that actually exist. The dispatcher silently fails to spawn unknown assignee names โ it doesn't autocorrect, doesn't suggest, doesn't fall back. So a card assigned to researcher on a setup that only has docker-worker just sits in ready forever.
Step 0: discover available profiles before planning.
Use one of these:
hermes profile list โ prints the table of profiles configured on this machine. Run it through your terminal tool if you have one; otherwise ask the user.
kanban_list(assignee="<some-name>") โ sanity-check a single name. Returns an empty list (rather than an error) for an unknown assignee, so this only confirms a name you're already considering.
- Just ask the user. "What profiles do you have set up?" is a fine first turn when the goal needs more than one specialist.
Cache the result in your working memory for the rest of the conversation. Re-asking every turn wastes a tool call.
When to use the board (vs. just doing the work)
Create Kanban tasks when any of these are true:
1. Multiple specialists are needed. Research + analysis + writing is three profiles.
2. The work should survive a crash or restart. Long-running, recurring, or important.
3. The user might want to interject. Human-in-the-loop at any step.
4. Multiple subtasks can run in parallel. Fan-out for speed.
5. Review / iteration is expected. A reviewer profile loops on drafter output.
6. The audit trail matters. Board rows persist in SQLite forever.
If none of those apply โ it's a small one-shot reasoning task โ use delegate_task instead or answer the user directly.
The anti-temptation rules
Your job description says "route, don't execute." The rules that enforce that:
- Do not execute the work yourself. Your restricted toolset usually doesn't even include terminal/file/code/web for implementation. If you find yourself "just fixing this quickly" โ stop and create a task for the right specialist.
- For any concrete task, create a Kanban task and assign it. Every single time.
- Split multi-lane requests before creating cards. A user prompt can contain several independent workstreams. Extract those lanes first, then create one card per lane instead of bundling unrelated work into a single implementer card.
- Run independent lanes in parallel. If two cards do not need each other's output, leave them unlinked so the dispatcher can fan them out. Link only true data dependencies.
- If no specialist fits the available profiles, ask the user which profile to create or which existing profile to use. Do not invent profile names; the dispatcher will silently drop unknown assignees.
- Decompose, route, and summarize โ that's the whole job.
Exception: micro-UI polish cycles
There is one narrow exception where the orchestrator may execute directly instead of creating Kanban cards: tiny UI-only polish cycles (e.g., adding a CSS class, a theme preview dot, a hover state, a cross-link, or a HUD button) that are purely presentational, require no cross-file logic changes, and fit comfortably inside a single bounded cycle with no need for review or parallel work. If the change is limited to HTML/CSS/JS cosmetics, no other profile has a stake in it, and the user did not ask for a design review, the orchestrator should just edit and publish rather than paying the kanban-overhead tax. This exception does NOT apply to architecture changes, adapter logic, plugin interfaces, or anything that touches the data layer.
Decomposition playbook
Step 1 โ Understand the goal
Ask clarifying questions if the goal is ambiguous. Cheap to ask; expensive to spawn the wrong fleet.
Step 2 โ Sketch the task graph
Before creating anything, draft the graph out loud (in your response to the user). Treat every concrete workstream as a candidate card:
1. Extract the lanes from the request.
2. Map each lane to one of the profiles you discovered in Step 0. If a lane doesn't fit any existing profile, ask the user which to use or create.
3. Decide whether each lane is independent or gated by another lane.
4. Create independent lanes as parallel cards with no parent links.
5. Create synthesis/review/integration cards with parent links to the lanes they depend on.
Examples of prompts that should fan out (using placeholder profile names โ substitute whatever exists on the user's setup):
- "Build an app" โ one card to a design-oriented profile for product/UI direction, one or two cards to engineering profiles for implementation, plus a later integration/review card if the user has a reviewer profile.
- "Fix blockers and check model variants" โ one implementation card for the blocker fixes plus one discovery/research card for config/source verification. A final reviewer card can depend on both.
- "Research docs and implement" โ a docs-research card can run in parallel with a codebase-discovery card; implementation waits only if it truly needs those findings.
- "Analyze this screenshot and find the related code" โ one card to a vision-capable profile for the visual analysis while another searches the codebase.
Words like "also," "finally," or "and" do not automatically imply a dependency. They often mean "make sure this is covered before reporting back." Only link tasks when one card cannot start until another card's output exists.
Show the graph to the user before creating cards. Let them correct it โ including which actual profile name should own each lane.
Step 3 โ Create tasks and link
Use the profile names from Step 0. The example below uses placeholders <profile-A>, <profile-B>, <profile-C> โ replace them with what the user actually has.
t1 = kanban_create(
title="research: Postgres cost vs current",
assignee="<profile-A>", # whichever profile handles research on this setup
body="Compare estimated infrastructure costs, migration costs, and ongoing ops costs over a 3-year window. Sources: AWS/GCP pricing, team time estimates, current Postgres bills from peers.",
tenant=os.environ.get("HERMES_TENANT"),
)["task_id"]
t2 = kanban_create(
title="research: Postgres performance vs current",
assignee="<profile-A>", # same profile, run in parallel
body="Compare query latency, throughput, and scaling characteristics at our expected data volume (~500GB, 10k QPS peak). Sources: benchmark papers, public case studies, pgbench results if easy.",
)["task_id"]
t3 = kanban_create(
title="synthesize migration recommendation",
assignee="<profile-B>", # whichever profile does synthesis/analysis
body="Read the findings from T1 (cost) and T2 (performance). Produce a 1-page recommendation with explicit trade-offs and a go/no-go call.",
parents=[t1, t2],
)["task_id"]
t4 = kanban_create(
title="draft decision memo",
assignee="<profile-C>", # whichever profile drafts user-facing prose
body="Turn the analyst's recommendation into a 2-page memo for the CTO. Match the tone of previous decision memos in the team's knowledge base.",
parents=[t3],
)["task_id"]
parents=[...] gates promotion โ children stay in todo until every parent reaches done, then auto-promote to ready. No manual coordination needed; the dispatcher and dependency engine handle it.
Step 4 โ Complete your own task
If you were spawned as a task yourself (e.g. a planner profile was assigned T0: "investigate Postgres migration"), mark it done with a summary of what you created:
kanban_complete(
summary="decomposed into T1-T4: 2 research lanes in parallel, 1 synthesis on their outputs, 1 prose draft on the recommendation",
metadata={
"task_graph": {
"T1": {"assignee": "<profile-A>", "parents": []},
"T2": {"assignee": "<profile-A>", "parents": []},
"T3": {"assignee": "<profile-B>", "parents": ["T1", "T2"]},
"T4": {"assignee": "<profile-C>", "parents": ["T3"]},
},
},
)
Step 5 โ Report back to the user
Tell them what you created in plain prose, naming the actual profiles you used:
> I've queued 4 tasks:
> - T1 (<profile-A>): cost comparison
> - T2 (<profile-A>): performance comparison, in parallel with T1
> - T3 (<profile-B>): synthesizes T1 + T2 into a recommendation
> - T4 (<profile-C>): turns T3 into a CTO memo
>
> The dispatcher will pick up T1 and T2 now. T3 starts when both finish. You'll get a gateway ping when T4 completes. Use the dashboard or hermes kanban tail <id> to follow along.
Common patterns
Fan-out + fan-in (research โ synthesize): N research-style cards with no parents, one synthesis card with all of them as parents.
Parallel implementation + validation: one implementer card makes the change while one explorer/researcher card verifies config, docs, or source mapping. A reviewer card can depend on both. Do not make the implementer own unrelated verification just because the user mentioned both in one sentence.
Pipeline with gates: planner โ implementer โ reviewer. Each stage's parents=[previous_task]. Reviewer blocks or completes; if reviewer blocks, the operator unblocks with feedback and respawns.
Same-profile queue: N tasks, all assigned to the same profile, no dependencies between them. Dispatcher serializes โ that profile processes them in priority order, accumulating experience in its own memory.
Parallel UI/frontend lanes: When the goal touches multiple independent HTML/CSS/JS files (e.g., a dashboard page and a 2D gather view), fan out to separate subagents per file. Each lane edits its own file, then the orchestrator integrates, fixes cross-file references (theme paths, shared JSON endpoints), and publishes. This avoids merge conflicts in single-file HTML dashboards and keeps each subagent's context focused. See references/parallel-ui-lanes-and-publishing.md for the post-subagent integration checklist and rsync safety notes.
Human-in-the-loop: Any task can kanban_block() to wait for input. Dispatcher respawns after /unblock. The comment thread carries the full context.
Pitfalls
Inventing profile names that don't exist. The dispatcher silently fails to spawn unknown assignees โ the card just sits in ready forever. Always assign to a profile from your Step 0 discovery; ask the user if you're unsure.
Bundling independent lanes into one card. If the user asks for two independent outcomes, create two cards. Example: "fix blockers and check model variants" is not one fixer task; create a fixer/engineer card for the fixes and an explorer/researcher card for the variant check, then optionally gate review on both.
Over-linking because of wording. "Finally check X" may still be parallel with implementation if X is static config, docs, or source discovery. Link it after implementation only when the check depends on the implementation result.
Forgetting dependency links. If the task graph says research -> implement -> review, do not create all tasks as independent ready cards. Use parent links so implement/review cannot run before their inputs exist.
Reassignment vs. new task. If a reviewer blocks with "needs changes," create a NEW task linked from the reviewer's task โ don't re-run the same task with a stern look. The new task is assigned to the original implementer profile.
Argument order for links. kanban_link(parent_id=..., child_id=...) โ parent first. Mixing them up demotes the wrong task to todo.
Ignoring explicit user feedback to keep building infrastructure. When the user says a specific UX issue (legibility, theme switching, movement density) is "immediate priority," treat it as P0 and route it before deeper packaging/architecture work. Infrastructure polish feels productive, but shipping user-visible fixes is what matters. Create cards for the UX feedback first, then resume infrastructure lanes.
Treating status: complete as immutable when user feedback says otherwise. A state.md that says status: complete does not override a user's report that a completion criterion is actually broken. If the user says "theme switching is not working" and the Final Completion Condition requires "working UI theme switcher," the mission is not complete. Reactivate immediately: set status: active, append a reactivation cycle log, and fix the issue. Do not burn cycles on post-complete verification while the user is reporting active defects.
Don't pre-create the whole graph if the shape depends on intermediate findings. If T3's structure depends on what T1 and T2 find, let T3 exist as a "synthesize findings" task whose own first step is to read parent handoffs and plan the rest. Orchestrators can spawn orchestrators.
Tenant inheritance. If HERMES_TENANT is set in your env, pass tenant=os.environ.get("HERMES_TENANT") on every kanban_create call so child tasks stay in the same namespace.
Verifying cross-file references after directory reorganization. When subagents edit HTML/CSS/JS files and the directory structure shifts (e.g., moving files from root into web/dashboard/ and web/gather/), relative asset paths ( themes/default/theme.css, ./ops-data.json) often break. After subagents finish, the orchestrator must grep for href= and src= in moved files and fix relative paths before publishing. Subagents don't know the final publish layout โ the orchestrator does.
Destructive sync wipes needed files. Commands like rsync -av --delete will delete destination files that aren't in the source list. If you publish a directory tree piecemeal (e.g., copy web/dashboard/ first, then web/gather/ separately), --delete on the first rsync will erase the gather files before the second rsync runs. Either list all source paths in a single rsync invocation, or omit --delete and use cp -r / rsync -av without deletion when doing staged copies.
Recovering stuck workers
When a worker profile keeps crashing, hallucinating, or getting blocked by its own mistakes (usually: wrong model, missing skill, broken credential), the kanban dashboard flags the task with a โ badge and opens a Recovery section in the drawer. Three primary actions:
1. Reclaim (or hermes kanban reclaim <task_id>) โ abort the running worker immediately and reset the task to ready. The existing claim TTL is ~15 min; this is the fast path out.
2. Reassign (or hermes kanban reassign <task_id> <new-profile> --reclaim) โ switch the task to a different profile (one that exists on this setup) and let the dispatcher pick it up with a fresh worker.
3. Change profile model โ the dashboard prints a copy-paste hint for hermes -p <profile> model since profile config lives on disk; edit it in a terminal, then Reclaim to retry with the new model.
Hallucination warnings appear on tasks where a worker's kanban_complete(created_cards=[...]) claim included card ids that don't exist or weren't created by the worker's profile (the gate blocks the completion), or where the free-form summary references t_<hex> ids that don't resolve (advisory prose scan, non-blocking). Both produce audit events that persist even after recovery actions โ the trail stays for debugging.
The user has provided the following instruction alongside the skill invocation: [IMPORTANT: You are running as a scheduled cron job. DELIVERY: Your final response will be automatically delivered to the user โ do NOT use send_message or try to deliver the output yourself. Just produce your report/output as your final response and the system handles the rest. SILENT: If there is genuinely nothing new to report, respond with exactly "[SILENT]" (nothing else) to suppress delivery. Never combine [SILENT] with content โ either report your findings normally, or say [SILENT] and nothing more.]
You are the 15-minute Orchestrator for Son's Autonomous Agent Lab v1, reporting to Discord channel ID 1505805763824586952.
Durable state path: /Users/jooho-hermes/.hermes/autonomous-agent-lab/state.md
Working directory for experiment artifacts: /Users/jooho-hermes/.hermes/autonomous-agent-lab/
Preferred published web root: /Users/jooho-hermes/hermes-web/agent-pets/
Top-level directive from Son:
- The project has evolved from a personal dashboard into an INSTALLABLE PRODUCT that external Hermes users can deploy.
- The final target is a self-contained, configurable, publishable solution: "Hermes Pixel Pet Ops Office".
- Do NOT shrink the mission into a small static MVP and autonomously stop.
- The Gather.town-style 2D spatial office is a first-class feature, not a side page.
Latest UX feedback from Son (treat as immediate priority before deeper packaging work):
- Details are hard for a human to understand. Add human-first summaries, plain-language labels, and progressive disclosure: summary first, technical details second.
- Gather Town version has too many agents roaming around. Reduce default movement, add density/speed controls, cluster agents by room/task, and add focus/calm mode.
- Theme switching is not visibly working. Implement real UI theme switcher with persistence and clear visual theme changes.
Key product requirements (installable solution level):
1. Config-driven architecture: all paths, URLs, colors, names, room layouts via config.yaml. No hardcoded references to jooho-hermes.
2. Self-contained package: clear directory structure (src/, web/, config/, docs/, scripts/), install script, requirements.txt.
3. Pluggable data adapter: support multiple backends via plugin architecture.
4. Themeable frontend: CSS variables driven from config, swappable themes, plus a working UI theme switcher.
5. Multi-tenant ready: works for any Hermes instance.
6. Build/Deploy ready: Dockerfile or docker-compose, or clear static-server setup.
7. Documentation: README, architecture docs, configuration reference, contributor guide.
8. Human-comprehensible UX: plain-language summaries and progressive disclosure for technical detail.
9. Gather.town calm mode: adjustable movement density/speed and less chaotic defaults.
10. Versioned releases: CHANGELOG.md, semantic versioning, release packaging.
Mission model:
- Read state.md first before doing anything else.
- If state.md says
status: inactive or has no Current Mission, do not invent work. Return exactly: ๐ก Autonomous Agent Lab ๋๊ธฐ์ค โ Son์ด ํธ๋ฆฌ๊ฑฐ/๋ฏธ์
์ ์ฃผ๋ฉด 15๋ถ ์ฌ์ดํด์ ์์ํฉ๋๋ค.
- If state.md says
status: active, run one bounded 15-minute cycle toward the full installable solution.
- If state.md says
status: complete, verify that the Final Completion Condition in state.md is truly met. If it is not fully met, reactivate or report that state needs correction.
Cycle procedure when active:
1. Read state.md first. Extract current mission, constraints, previous cycle log, and Final Completion Condition.
2. Decide the next smallest useful step toward installable solution quality. Focus on: architecture, configurability, documentation, and clean separation of concerns.
3. Use delegate_task for independent subagent lanes when helpful.
4. Prefer concrete progress: refactor to config-driven, add install scripts, create docs, add Docker support, theme system, plugin architecture.
5. Update state.md with a new cycle log entry before final reporting.
6. Completion rule: only set status: complete when every item under state.md Final Completion Condition is satisfied. A non-installable MVP is not complete.
7. Stop/block only if Son explicitly stops/redirects, a safety boundary is reached, or a hard blocker needs Son's decision.
Link requirement (never forget):
- Every cycle report MUST include at least one direct viewable link to the published dashboard/artifact.
- The canonical URL:
http://hermes-mac-mini.tail46b3c6.ts.net:8099/agent-pets/
- Include gather town URL too:
http://hermes-mac-mini.tail46b3c6.ts.net:8099/agent-pets/gather/
Final Discord message format:
[Autonomous Agent Lab v1 / Cycle N]
๋ชฉํ:
์ํ:
๊ฒฐ๊ณผ:
๊ฒ์ฆ:
๋ค์:
์ํ:
Safety/quality rules:
- Do not handle secrets, passwords, API keys, payment, permission dialogs, or destructive commands.
- Do not claim completion without updating state.md.
- Do not rely on Discord history as durable state.
- Do not spam raw logs; summarize lane outputs and verification.
- Keep working in /Users/jooho-hermes/.hermes/autonomous-agent-lab/ and publish only to /Users/jooho-hermes/hermes-web/agent-pets/ unless the state file says otherwise.
Design/UX priorities:
- Mobile responsiveness is first-class.
- Character animation/movement is desired.
- Every cycle report must include published links.
- This is now a product engineering mission. Architecture, configurability, and documentation matter as much as visuals.
Response
[Autonomous Agent Lab v1 / Cycle 62]
๋ชฉํ:
๋ฒ์ /์บ์ ๋ถ์ผ์น๋ฅผ ํด์ํ๊ณ , 11๊ฐ Final Completion Condition์ด ์ ๋ถ ์ถฉ์กฑ๋จ์ ์ต์ข
๊ฒ์ฆํ์ฌ status: complete ๋ก ๋ง๊ฐํฉ๋๋ค.
์ํ:
1. web/gather/index.html ๋น๋ ๋ฐฐ์ง๋ฅผ b60 โ b62 ๋ก ์์ (์บ์ ๋ฒ์คํธ ๋ฒ์ ๊ณผ ์ผ์น).
2. web/sw.js ์บ์ ๋ฒ์คํธ ๋ฌธ์์ด์ ํผ์ฌ๋ ?v=60/61 ์์ ?v=62 ๋ก ํต์ผ, CACHE_NAME ์ pixel-pet-ops-v18 โ v19 ๋ก ๊ฐฑ์ .
3. ํผ๋ธ๋ฆฌ์ฑ ๋์๋ณด๋์ ๋จ์์๋ ์ด์ ๋ฒ์ ์์ฌ( v1.4.5ยทb61)๋ฅผ ์์ค ๊ธฐ์ค v1.4.4ยทb62 ๋ก ์์ ๋ฎ์ด์ฐ๊ธฐ.
4. scripts/publish.sh ์คํ โ ์์ค์ ํผ๋ธ๋ฆฌ์ ํ์ผ diff 100% ์ผ์น ํ์ธ.
5. scripts/package-release.sh ์ฌ์คํ โ ๋ฆด๋ฆฌ์ฆ tar.gz/zip ์๋ ๋์ผํ b62 ๋ฒ์ ์ ์ฉ ํ์ธ.
6. ์ด๋ํฐ, ํตํฉํ
์คํธ, ๊ฒ์ฆ์คํฌ๋ฆฝํธ ์ ์ฒด ์ฌ์คํ.
๊ฒฐ๊ณผ:
- Dashboard:
http://hermes-mac-mini.tail46b3c6.ts.net:8099/agent-pets/
- Gather Town:
http://hermes-mac-mini.tail46b3c6.ts.net:8099/agent-pets/gather/
- ํตํฉํ
์คํธ: 121/121 passed
- ์ค์น ๊ฒ์ฆ: 21/21 passed
- Adapter: 32 agents, 15 cron, 20 sessions, 16 events, schema 1.4
health.json: healthy, version 1.4.4
ops-data.json / health.json mtime: 60์ด ์ด๋ด ์ ์
refresh.err.log: ๋น์ด ์์, LaunchAgent ์ ์ ๋์ ์ค
๊ฒ์ฆ:
- 11๊ฐ Final Completion Condition ์ ๋ถ ์ถฉ์กฑ โ
- Son UX ํผ๋๋ฐฑ 3๊ฐ์ง(ํ
๋ง ์ ํ, Gather calm ๋ชจ๋, ์ฌ๋ ์ค์ฌ ์์ฝ) ๊ตฌ์กฐ์ ์ผ๋ก ํด๊ฒฐ โ
- ์์ค โ ํผ๋ธ๋ฆฌ์๋ โ ๋ฆด๋ฆฌ์ฆ ํจํค์ง ๋ฒ์ ์ผ์น โ
jooho-hermes ํ๋์ฝ๋ฉ 0๊ฑด โ
๋ค์:
๋ฏธ์
์๋ฃ. Son์ด ์ถ๊ฐ ํผ๋๋ฐฑ์ด๋ ์ ๊ท ๊ธฐ๋ฅ ์์ฒญ์ ์ฃผ์ง ์๋ ํ ๋ ์ด์์ ์์จ ์ฌ์ดํด์ ๋ถํ์ํฉ๋๋ค. ํน์ ์ด์ ์บ์๊ฐ ๋จ์ ์์ ์ ์์ผ๋, ๋์๋ณด๋ ๋๋ Gather Town ํ๋จ์ "๐ ์บ์ ์ญ์ & ์๋ก๊ณ ์นจ" ๋ฒํผ์ ํ ๋ฒ ๋๋ฌ์ฃผ์๋ฉด ์ต์ b62 ๋น๋๊ฐ ํ์คํ ์ ์ฉ๋ฉ๋๋ค.
์ํ: โ
complete (cycle 62)
|
| 2026-05-19 17-13-11 |
81,568 chars |
2026-05-19_17-13-11.md |
Cron Job: autonomous-agent-lab-v1-orchestrator (FAILED)
Job ID: 35127ff89556
Run Time: 2026-05-19 17:13:11
Schedule: every 15m
Prompt
[IMPORTANT: The user has invoked the "hermes-agent" skill, indicating they want you to follow its instructions. The full skill content is loaded below.]
---
name: hermes-agent
description: "Configure, extend, or contribute to Hermes Agent."
version: 2.1.0
author: Hermes Agent + Teknium
license: MIT
platforms: [linux, macos, windows]
metadata:
hermes:
tags: [hermes, setup, configuration, multi-agent, spawning, cli, gateway, development]
homepage: https://github.com/NousResearch/hermes-agent
related_skills: [claude-code, codex, opencode]
---
Hermes Agent
Hermes Agent is an open-source AI agent framework by Nous Research that runs in your terminal, messaging platforms, and IDEs. It belongs to the same category as Claude Code (Anthropic), Codex (OpenAI), and OpenClaw โ autonomous coding and task-execution agents that use tool calling to interact with your system. Hermes works with any LLM provider (OpenRouter, Anthropic, OpenAI, DeepSeek, local models, and 15+ others) and runs on Linux, macOS, and WSL.
What makes Hermes different:
- Self-improving through skills โ Hermes learns from experience by saving reusable procedures as skills. When it solves a complex problem, discovers a workflow, or gets corrected, it can persist that knowledge as a skill document that loads into future sessions. Skills accumulate over time, making the agent better at your specific tasks and environment.
- Persistent memory across sessions โ remembers who you are, your preferences, environment details, and lessons learned. Pluggable memory backends (built-in, Honcho, Mem0, and more) let you choose how memory works.
- Multi-platform gateway โ the same agent runs on Telegram, Discord, Slack, WhatsApp, Signal, Matrix, Email, and 10+ other platforms with full tool access, not just chat.
- Provider-agnostic โ swap models and providers mid-workflow without changing anything else. Credential pools rotate across multiple API keys automatically.
- Profiles โ run multiple independent Hermes instances with isolated configs, sessions, skills, and memory.
- Extensible โ plugins, MCP servers, custom tools, webhook triggers, cron scheduling, and the full Python ecosystem.
People use Hermes for software development, research, system administration, data analysis, content creation, home automation, and anything else that benefits from an AI agent with persistent context and full system access.
This skill helps you work with Hermes Agent effectively โ setting it up, configuring features, spawning additional agent instances, troubleshooting issues, finding the right commands and settings, and understanding how the system works when you need to extend or contribute to it.
Docs: https://hermes-agent.nousresearch.com/docs/
Quick Start
Install
curl -fsSL https://raw.githubusercontent.com/NousResearch/hermes-agent/main/scripts/install.sh | bash
Interactive chat (default)
hermes
Single query
hermes chat -q "What is the capital of France?"
Setup wizard
hermes setup
Change model/provider
hermes model
Check health
hermes doctor
---
CLI Reference
Global Flags
hermes [flags] [command]
--version, -V Show version
--resume, -r SESSION Resume session by ID or title
--continue, -c [NAME] Resume by name, or most recent session
--worktree, -w Isolated git worktree mode (parallel agents)
--skills, -s SKILL Preload skills (comma-separate or repeat)
--profile, -p NAME Use a named profile
--yolo Skip dangerous command approval
--pass-session-id Include session ID in system prompt
No subcommand defaults to chat.
Chat
hermes chat [flags]
-q, --query TEXT Single query, non-interactive
-m, --model MODEL Model (e.g. anthropic/claude-sonnet-4)
-t, --toolsets LIST Comma-separated toolsets
--provider PROVIDER Force provider (openrouter, anthropic, nous, etc.)
-v, --verbose Verbose output
-Q, --quiet Suppress banner, spinner, tool previews
--checkpoints Enable filesystem checkpoints (/rollback)
--source TAG Session source tag (default: cli)
Configuration
hermes setup [section] Interactive wizard (model|terminal|gateway|tools|agent)
hermes model Interactive model/provider picker
hermes config View current config
hermes config edit Open config.yaml in $EDITOR
hermes config set KEY VAL Set a config value
hermes config path Print config.yaml path
hermes config env-path Print .env path
hermes config check Check for missing/outdated config
hermes config migrate Update config with new options
hermes doctor [--fix] Check dependencies and config
Credential Pools
hermes auth add Interactive credential wizard (oauth, api-key)
hermes auth list [PROVIDER] List pooled credentials
hermes auth remove P INDEX Remove by provider + index
hermes auth reset PROVIDER Clear exhaustion status
hermes logout Clear stored auth
Tools & Skills
hermes tools Interactive tool enable/disable (curses UI)
hermes tools list Show all tools and status
hermes tools enable NAME Enable a toolset
hermes tools disable NAME Disable a toolset
hermes skills list List installed skills
hermes skills search QUERY Search the skills hub
hermes skills install ID Install a skill (ID can be a hub identifier OR a direct https://โฆ/SKILL.md URL; pass --name to override when frontmatter has no name)
hermes skills inspect ID Preview without installing
hermes skills config Enable/disable skills per platform
hermes skills check Check for updates
hermes skills update Update outdated skills
hermes skills uninstall N Remove a hub skill
hermes skills publish PATH Publish to registry
hermes skills browse Browse all available skills
hermes skills tap add REPO Add a GitHub repo as skill source
MCP Servers
hermes mcp serve Run Hermes as an MCP server
hermes mcp add NAME Add an MCP server (--url or --command)
hermes mcp remove NAME Remove an MCP server
hermes mcp list List configured servers
hermes mcp test NAME Test connection
hermes mcp configure NAME Toggle tool selection
Gateway (Messaging Platforms)
hermes gateway run Start gateway foreground
hermes gateway install Install as background service
hermes gateway start/stop Control the service
hermes gateway restart Restart the service
hermes gateway status Check status
hermes gateway setup Configure platforms
Supported platforms: Telegram, Discord, Slack, WhatsApp, Signal, Email, SMS, Matrix, Mattermost, Home Assistant, DingTalk, Feishu, WeCom, BlueBubbles (iMessage), Weixin (WeChat), API Server, Webhooks. Open WebUI connects via the API Server adapter.
Platform docs: https://hermes-agent.nousresearch.com/docs/user-guide/messaging/
Discord-specific walkthrough (token, intents, service install, access control): see references/discord-gateway-setup.md in this skill.
- Per-channel personas and skill bindings: see
references/gateway-channel-personas.md (works on Discord, Slack, Telegram, Mattermost, Matrix).
- For long-running Discord-first operations, purpose-specific channel routing, periodic summaries, weekly Dreaming/audit reports, and log-safety patterns: see
references/discord-operating-planes.md.
- For broad Hermes/LifeOS/SQAF ecosystem audits (cron inventory, live services, dashboards, provider/model warnings, and control-plane gaps), see
references/ecosystem-audit.md.
Sessions
hermes sessions list List recent sessions
hermes sessions browse Interactive picker
hermes sessions export OUT Export to JSONL
hermes sessions rename ID T Rename a session
hermes sessions delete ID Delete a session
hermes sessions prune Clean up old sessions (--older-than N days)
hermes sessions stats Session store statistics
For browser-based viewing of existing Hermes CLI/Discord/cron session transcripts, prefer a lightweight static export from ~/.hermes/state.db into a private web root instead of assuming Open WebUI can browse Hermes' native session store. See references/hermes-session-static-web-viewer.md for the SQLite schema, static HTML export workflow, redaction/truncation cautions, and the user's Mac mini deployment (/hermes-sessions/ under the Tailscale-only ~/hermes-web site).
For cron job execution history, the same static-export pattern applies to ~/.hermes/cron/jobs.json and ~/.hermes/cron/output/{job_id}/*.md. See references/cron-history-web-viewer.md for the cron data model, schedule-dict pitfall, and the user's deployed /cron-history/ dashboard.
Cron Jobs
hermes cron list List jobs (--all for disabled)
hermes cron create SCHED Create: '30m', 'every 2h', '0 9 *'
hermes cron edit ID Edit schedule, prompt, delivery
hermes cron pause/resume ID Control job state
hermes cron run ID Trigger on next tick
hermes cron remove ID Delete a job
hermes cron status Scheduler status
For bounded autonomous lab/orchestrator cron jobs that use file-based state, subagent lanes, artifact publishing, and status transitions (active โ complete/blocked/inactive), see references/autonomous-agent-lab-cron-cycle.md. A reusable verification script template lives at scripts/verify-completion-template.py.
For a worked example of evolving an autonomous lab into a config-driven, themeable, Docker-ready installable product, see references/autonomous-lab-product-architecture.md. For CI, integration testing, pluggable adapter architecture, bounded cycle orchestration, and post-productization patterns, see references/product-maturity-patterns.md.
For the final completion verification checklist โ the explicit audit pattern to run before marking status: complete on an installable-solution mission, see references/autonomous-lab-completion-verification.md.
For the reactivation protocol when a completed lab receives new P0 feedback or the user contradicts a completion claim, see references/autonomous-lab-reactivation-protocol.md.
For the config/CHANGELOG version drift pitfall that occurs when autonomous labs evolve over many cycles, see references/autonomous-lab-version-drift.md.
For adding historical trend tracking (SQLite-backed agent status transitions + vanilla JS SVG sparklines) to an autonomous lab dashboard, see references/history-tracking-sparkline-pattern.md.
For reusable dashboard UX patterns (onboarding tours, data freshness badges, keyboard shortcuts, progressive disclosure inspectors, cross-linking between views), see references/dashboard-ux-patterns.md.
For the aggressive human-first inspector refinement โ when users report that details are hard to understand and the fix is to strip technical labels from the default view โ see references/progressive-disclosure-human-first.md.
For programmatic verification of CSS custom-property theme systems โ catching scoping bugs, confirming theme distinctness, and validating JS switching logic โ see references/theme-system-verification.md.
For Son's Discord-first autonomous experiments where a channel hosts a repeated multi-agent loop, use the Autonomous Discord Agent Lab pattern: create file-based durable state, a paused cron orchestrator delivered to discord:<channel_id>, then activate it from a user mission trigger. See references/autonomous-discord-agent-lab.md.
Webhooks
hermes webhook subscribe N Create route at /webhooks/<name>
hermes webhook list List subscriptions
hermes webhook remove NAME Remove a subscription
hermes webhook test NAME Send a test POST
Profiles
hermes profile list List all profiles
hermes profile create NAME Create (--clone, --clone-all, --clone-from)
hermes profile use NAME Set sticky default
hermes profile delete NAME Delete a profile
hermes profile show NAME Show details
hermes profile alias NAME Manage wrapper scripts
hermes profile rename A B Rename a profile
hermes profile export NAME Export to tar.gz
hermes profile import FILE Import from archive
Credential Pools
hermes auth add Interactive credential wizard
hermes auth list [PROVIDER] List pooled credentials
hermes auth remove P INDEX Remove by provider + index
hermes auth reset PROVIDER Clear exhaustion status
Other
hermes insights [--days N] Usage analytics
hermes update Update to latest version
hermes pairing list/approve/revoke DM authorization
hermes plugins list/install/remove Plugin management
hermes honcho setup/status Honcho memory integration (requires honcho plugin)
hermes memory setup/status/off Memory provider config
hermes completion bash|zsh Shell completions
hermes acp ACP server (IDE integration)
hermes claw migrate Migrate from OpenClaw
hermes uninstall Uninstall Hermes
---
Slash Commands (In-Session)
Type these during an interactive chat session. New commands land fairly
often; if something below looks stale, run /help in-session for the
authoritative list or see the [live slash commands reference](https://hermes-agent.nousresearch.com/docs/reference/slash-commands).
The registry of record is hermes_cli/commands.py โ every consumer
(autocomplete, Telegram menu, Slack mapping, /help) derives from it.
Session Control
/new (/reset) Fresh session
/clear Clear screen + new session (CLI)
/retry Resend last message
/undo Remove last exchange
/title [name] Name the session
/compress Manually compress context
/stop Kill background processes
/rollback [N] Restore filesystem checkpoint
/snapshot [sub] Create or restore state snapshots of Hermes config/state (CLI)
/background <prompt> Run prompt in background
/queue <prompt> Queue for next turn
/steer <prompt> Inject a message after the next tool call without interrupting
/agents (/tasks) Show active agents and running tasks
/resume [name] Resume a named session
/goal [text|sub] Set a standing goal Hermes works on across turns until achieved
(subcommands: status, pause, resume, clear)
/redraw Force a full UI repaint (CLI)
Configuration
/config Show config (CLI)
/model [name] Show or change model
/personality [name] Set personality
/reasoning [level] Set reasoning (none|minimal|low|medium|high|xhigh|show|hide)
/verbose Cycle: off โ new โ all โ verbose
/voice [on|off|tts] Voice mode
/yolo Toggle approval bypass
/busy [sub] Control what Enter does while Hermes is working (CLI)
(subcommands: queue, steer, interrupt, status)
/indicator [style] Pick the TUI busy-indicator style (CLI)
(styles: kaomoji, emoji, unicode, ascii)
/footer [on|off] Toggle gateway runtime-metadata footer on final replies
/skin [name] Change theme (CLI)
/statusbar Toggle status bar (CLI)
Tools & Skills
/tools Manage tools (CLI)
/toolsets List toolsets (CLI)
/skills Search/install skills (CLI)
/skill <name> Load a skill into session
/reload-skills Re-scan ~/.hermes/skills/ for added/removed skills
/reload Reload .env variables into the running session (CLI)
/reload-mcp Reload MCP servers
/cron Manage cron jobs (CLI)
/curator [sub] Background skill maintenance (status, run, pin, archive, โฆ)
/kanban [sub] Multi-profile collaboration board (tasks, links, comments)
/plugins List plugins (CLI)
Gateway
/approve Approve a pending command (gateway)
/deny Deny a pending command (gateway)
/restart Restart gateway (gateway)
/sethome Set current chat as home channel (gateway)
/update Update Hermes to latest (gateway)
/topic [sub] Enable or inspect Telegram DM topic sessions (gateway)
/platforms (/gateway) Show platform connection status (gateway)
Utility
/branch (/fork) Branch the current session
/fast Toggle priority/fast processing
/browser Open CDP browser connection
/history Show conversation history (CLI)
/save Save conversation to file (CLI)
/copy [N] Copy the last assistant response to clipboard (CLI)
/paste Attach clipboard image (CLI)
/image Attach local image file (CLI)
Info
/help Show commands
/commands [page] Browse all commands (gateway)
/usage Token usage
/insights [days] Usage analytics
/gquota Show Google Gemini Code Assist quota usage (CLI)
/status Session info (gateway)
/profile Active profile info
/debug Upload debug report (system info + logs) and get shareable links
Exit
/quit (/exit, /q) Exit CLI
---
Key Paths & Config
~/.hermes/config.yaml Main configuration
~/.hermes/.env API keys and secrets
$HERMES_HOME/skills/ Installed skills
~/.hermes/sessions/ Session transcripts
~/.hermes/logs/ Gateway and error logs
~/.hermes/auth.json OAuth tokens and credential pools
~/.hermes/hermes-agent/ Source code (if git-installed)
Profiles use ~/.hermes/profiles/<name>/ with the same layout.
Config Sections
Edit with hermes config edit or hermes config set section.key value.
| Section | Key options |
|---------|-------------|
| model | default, provider, base_url, api_key, context_length |
| agent | max_turns (90), tool_use_enforcement |
| terminal | backend (local/docker/ssh/modal), cwd, timeout (180) |
| compression | enabled, threshold (0.50), target_ratio (0.20) |
| display | skin, tool_progress, show_reasoning, show_cost |
| stt | enabled, provider (local/groq/openai/mistral) |
| tts | provider (edge/elevenlabs/openai/minimax/mistral/neutts) |
| memory | memory_enabled, user_profile_enabled, provider |
| security | tirith_enabled, website_blocklist |
| delegation | model, provider, base_url, api_key, max_iterations (50), reasoning_effort |
| checkpoints | enabled, max_snapshots (50) |
| fallback_model | provider, model, base_url, key_env |
Fallback Providers
Hermes can automatically fail over to a backup provider:model when the primary is unavailable. This is turn-scoped โ each new user message starts with the primary restored; fallback only activates mid-turn when the primary fails.
Configuration ( ~/.hermes/config.yaml):
fallback_model:
provider: opencode-go
model: kimi-k2.6
Or use the interactive manager:
hermes fallback add # interactive picker
hermes fallback list # show fallback chain
hermes fallback remove # remove by index
Legacy note: fallback_model (singular) is the legacy single-fallback key. fallback_providers (list) supports multiple ordered fallbacks. When both exist, fallback_providers takes priority.
Trigger conditions (after exhausting retries where applicable):
- Rate limits (HTTP 429)
- Server errors (HTTP 500, 502, 503)
- Auth failures (HTTP 401, 403) โ immediately
- Not found (HTTP 404) โ immediately
- Invalid / empty responses repeatedly
Supported providers include all standard providers (OpenRouter, Anthropic, OpenCode Go/ Zen, Kimi, etc.) plus custom endpoints with base_url + key_env. Full provider docs: https://hermes-agent.nousresearch.com/docs/integrations/providers
Limitations:
- Subagent delegation does not inherit fallback config
- Cron jobs do not use fallback (use per-job provider/model overrides)
- Auxiliary tasks (vision, compression, etc.) use their own
auxiliary.* provider chain
For a deep-dive with worked examples and model lists, see references/fallback-providers.md.
Full config reference: https://hermes-agent.nousresearch.com/docs/user-guide/configuration
Providers
20+ providers supported. Set via hermes model or hermes setup.
| Provider | Auth | Key env var |
|----------|------|-------------|
| OpenRouter | API key | OPENROUTER_API_KEY |
| Anthropic | API key | ANTHROPIC_API_KEY |
| Nous Portal | OAuth | hermes auth |
| OpenAI Codex | OAuth | hermes auth |
| GitHub Copilot | Token | COPILOT_GITHUB_TOKEN |
| Google Gemini | API key | GOOGLE_API_KEY or GEMINI_API_KEY |
| DeepSeek | API key | DEEPSEEK_API_KEY |
| xAI / Grok | API key | XAI_API_KEY |
| Hugging Face | Token | HF_TOKEN |
| Z.AI / GLM | API key | GLM_API_KEY |
| MiniMax | API key | MINIMAX_API_KEY |
| MiniMax CN | API key | MINIMAX_CN_API_KEY |
| Kimi / Moonshot | API key | KIMI_API_KEY |
| Alibaba / DashScope | API key | DASHSCOPE_API_KEY |
| Xiaomi MiMo | API key | XIAOMI_API_KEY |
| Kilo Code | API key | KILOCODE_API_KEY |
| AI Gateway (Vercel) | API key | AI_GATEWAY_API_KEY |
| OpenCode Zen | API key | OPENCODE_ZEN_API_KEY |
| OpenCode Go | API key | OPENCODE_GO_API_KEY |
| Qwen OAuth | OAuth | hermes auth add qwen-oauth |
| Custom endpoint | Config | model.base_url + model.api_key in config.yaml |
| GitHub Copilot ACP | External | COPILOT_CLI_PATH or Copilot CLI |
Full provider docs: https://hermes-agent.nousresearch.com/docs/integrations/providers
Toolsets
Enable/disable via hermes tools (interactive) or hermes tools enable/disable NAME.
| Toolset | What it provides |
|---------|-----------------|
| web | Web search and content extraction |
| search | Web search only (subset of web) |
| browser | Browser automation (Browserbase, Camofox, or local Chromium) |
| terminal | Shell commands and process management |
| file | File read/write/search/patch |
| code_execution | Sandboxed Python execution |
| vision | Image analysis |
| image_gen | AI image generation |
| video | Video analysis and generation |
| tts | Text-to-speech |
| skills | Skill browsing and management |
| memory | Persistent cross-session memory |
| session_search | Search past conversations |
| delegation | Subagent task delegation |
| cronjob | Scheduled task management |
| clarify | Ask user clarifying questions |
| messaging | Cross-platform message sending |
| todo | In-session task planning and tracking |
| kanban | Multi-agent work-queue tools (gated to workers) |
| debugging | Extra introspection/debug tools (off by default) |
| safe | Minimal, low-risk toolset for locked-down sessions |
| spotify | Spotify playback and playlist control |
| homeassistant | Smart home control (off by default) |
| discord | Discord integration tools |
| discord_admin | Discord admin/moderation tools |
| feishu_doc | Feishu (Lark) document tools |
| feishu_drive | Feishu (Lark) drive tools |
| yuanbao | Yuanbao integration tools |
| rl | Reinforcement learning tools (off by default) |
| moa | Mixture of Agents (off by default) |
Full enumeration lives in toolsets.py as the TOOLSETS dict; _HERMES_CORE_TOOLS is the default bundle most platforms inherit from.
Tool changes take effect on /reset (new session). They do NOT apply mid-conversation to preserve prompt caching.
---
Security & Privacy Toggles
Common "why is Hermes doing X to my output / tool calls / commands?" toggles โ and the exact commands to change them. Most of these need a fresh session (/reset in chat, or start a new hermes invocation) because they're read once at startup.
Secret redaction in tool output
Secret redaction is off by default โ tool output (terminal stdout, read_file, web content, subagent summaries, etc.) passes through unmodified. If the user wants Hermes to auto-mask strings that look like API keys, tokens, and secrets before they enter the conversation context and logs:
hermes config set security.redact_secrets true # enable globally
Restart required. security.redact_secrets is snapshotted at import time โ toggling it mid-session (e.g. via export HERMES_REDACT_SECRETS=true from a tool call) will NOT take effect for the running process. Tell the user to run hermes config set security.redact_secrets true in a terminal, then start a new session. This is deliberate โ it prevents an LLM from flipping the toggle on itself mid-task.
Disable again with:
hermes config set security.redact_secrets false
PII redaction in gateway messages
Separate from secret redaction. When enabled, the gateway hashes user IDs and strips phone numbers from the session context before it reaches the model:
hermes config set privacy.redact_pii true # enable
hermes config set privacy.redact_pii false # disable (default)
Command approval prompts
By default (approvals.mode: manual), Hermes prompts the user before running shell commands flagged as destructive (rm -rf, git reset --hard, etc.). The modes are:
manual โ always prompt (default)
smart โ use an auxiliary LLM to auto-approve low-risk commands, prompt on high-risk
off โ skip all approval prompts (equivalent to --yolo)
hermes config set approvals.mode smart # recommended middle ground
hermes config set approvals.mode off # bypass everything (not recommended)
Per-invocation bypass without changing config:
hermes --yolo โฆ
export HERMES_YOLO_MODE=1
Note: YOLO / approvals.mode: off does NOT turn off secret redaction. They are independent.
Shell hooks allowlist
Some shell-hook integrations require explicit allowlisting before they fire. Managed via ~/.hermes/shell-hooks-allowlist.json โ prompted interactively the first time a hook wants to run.
Disabling the web/browser/image-gen tools
To keep the model away from network or media tools entirely, open hermes tools and toggle per-platform. Takes effect on next session (/reset). See the Tools & Skills section above.
---
Voice & Transcription
STT (Voice โ Text)
Voice messages from messaging platforms are auto-transcribed.
Provider priority (auto-detected):
1. Local faster-whisper โ free, no API key: pip install faster-whisper
2. Groq Whisper โ free tier: set GROQ_API_KEY
3. OpenAI Whisper โ paid: set VOICE_TOOLS_OPENAI_KEY
4. Mistral Voxtral โ set MISTRAL_API_KEY
Config:
stt:
enabled: true
provider: local # local, groq, openai, mistral
local:
model: base # tiny, base, small, medium, large-v3
TTS (Text โ Voice)
| Provider | Env var | Free? |
|----------|---------|-------|
| Edge TTS | None | Yes (default) |
| ElevenLabs | ELEVENLABS_API_KEY | Free tier |
| OpenAI | VOICE_TOOLS_OPENAI_KEY | Paid |
| MiniMax | MINIMAX_API_KEY | Paid |
| Mistral (Voxtral) | MISTRAL_API_KEY | Paid |
| NeuTTS (local) | None (pip install neutts[all] + espeak-ng) | Free |
Voice commands: /voice on (voice-to-voice), /voice tts (always voice), /voice off.
---
Spawning Additional Hermes Instances
Run additional Hermes processes as fully independent subprocesses โ separate sessions, tools, and environments.
When to Use This vs delegate_task
| | delegate_task | Spawning hermes process |
|-|-----------------|--------------------------|
| Isolation | Separate conversation, shared process | Fully independent process |
| Duration | Minutes (bounded by parent loop) | Hours/days |
| Tool access | Subset of parent's tools | Full tool access |
| Interactive | No | Yes (PTY mode) |
| Use case | Quick parallel subtasks | Long autonomous missions |
One-Shot Mode
terminal(command="hermes chat -q 'Research GRPO papers and write summary to ~/research/grpo.md'", timeout=300)
Background for long tasks:
terminal(command="hermes chat -q 'Set up CI/CD for ~/myapp'", background=true)
Interactive PTY Mode (via tmux)
Hermes uses prompt_toolkit, which requires a real terminal. Use tmux for interactive spawning:
Start
terminal(command="tmux new-session -d -s agent1 -x 120 -y 40 'hermes'", timeout=10)
Wait for startup, then send a message
terminal(command="sleep 8 && tmux send-keys -t agent1 'Build a FastAPI auth service' Enter", timeout=15)
Read output
terminal(command="sleep 20 && tmux capture-pane -t agent1 -p", timeout=5)
Send follow-up
terminal(command="tmux send-keys -t agent1 'Add rate limiting middleware' Enter", timeout=5)
Exit
terminal(command="tmux send-keys -t agent1 '/exit' Enter && sleep 2 && tmux kill-session -t agent1", timeout=10)
Multi-Agent Coordination
Agent A: backend
terminal(command="tmux new-session -d -s backend -x 120 -y 40 'hermes -w'", timeout=10)
terminal(command="sleep 8 && tmux send-keys -t backend 'Build REST API for user management' Enter", timeout=15)
Agent B: frontend
terminal(command="tmux new-session -d -s frontend -x 120 -y 40 'hermes -w'", timeout=10)
terminal(command="sleep 8 && tmux send-keys -t frontend 'Build React dashboard for user management' Enter", timeout=15)
Check progress, relay context between them
terminal(command="tmux capture-pane -t backend -p | tail -30", timeout=5)
terminal(command="tmux send-keys -t frontend 'Here is the API schema from the backend agent: ...' Enter", timeout=5)
Session Resume
Resume most recent session
terminal(command="tmux new-session -d -s resumed 'hermes --continue'", timeout=10)
Resume specific session
terminal(command="tmux new-session -d -s resumed 'hermes --resume 20260225_143052_a1b2c3'", timeout=10)
Tips
- Prefer
delegate_task for quick subtasks โ less overhead than spawning a full process
- Use
-w (worktree mode) when spawning agents that edit code โ prevents git conflicts
- Set timeouts for one-shot mode โ complex tasks can take 5-10 minutes
- Use
hermes chat -q for fire-and-forget โ no PTY needed
- Use tmux for interactive sessions โ raw PTY mode has
\r vs \n issues with prompt_toolkit
- For scheduled tasks, use the
cronjob tool instead of spawning โ handles delivery and retry
---
Durable & Background Systems
Four systems run alongside the main conversation loop. Quick reference
here; full developer notes live in AGENTS.md, user-facing docs under
website/docs/user-guide/features/.
Delegation (delegate_task)
Synchronous subagent spawn โ the parent waits for the child's summary
before continuing its own loop. Isolated context + terminal session.
- Single:
delegate_task(goal, context, toolsets).
- Batch:
delegate_task(tasks=[{goal, ...}, ...]) runs children in
parallel, capped by delegation.max_concurrent_children (default 3).
- Roles:
leaf (default; cannot re-delegate) vs orchestrator
(can spawn its own workers, bounded by delegation.max_spawn_depth).
- Not durable. If the parent is interrupted, the child is
cancelled. For work that must outlive the turn, use cronjob or
terminal(background=True, notify_on_complete=True).
Config: delegation.* in config.yaml.
Tuning max_concurrent_children
Default is 3. Rule of thumb for raising it:
- Light tasks (web search, file grep): up to
6-8
- Medium tasks (code execution, browser):
4-5
- Heavy tasks (builds, large data):
2-3
- Actual bottleneck is usually the API rate limit, not local CPU/RAM. On a 10-core M4 with 16GB RAM, CPU is rarely the constraint.
- Formula: start at
5, raise only if profiling shows idle time between API responses.
Cron (scheduled jobs)
Durable scheduler โ cron/jobs.py + cron/scheduler.py. Drive it via
the cronjob tool, the hermes cron CLI (list, add, edit,
pause, resume, run, remove), or the /cron slash command.
- Schedules: duration (
"30m", "2h"), "every" phrase
( "every monday 9am"), 5-field cron ( "0 9 *"), or ISO timestamp.
- Per-job knobs:
skills, model/provider override, script
(pre-run data collection; no_agent=True makes the script the whole
job), context_from (chain job A's output into job B), workdir
(run in a specific dir with its AGENTS.md / CLAUDE.md loaded),
multi-platform delivery.
- Invariants: 3-minute hard interrupt per run,
.tick.lock file
prevents duplicate ticks across processes, cron sessions pass
skip_memory=True by default, and cron deliveries are framed with a
header/footer instead of being mirrored into the target gateway
session (keeps role alternation intact).
User docs: https://hermes-agent.nousresearch.com/docs/user-guide/features/cron
Curator (skill lifecycle)
Background maintenance for agent-created skills. Tracks usage, marks
idle skills stale, archives stale ones, keeps a pre-run tar.gz backup
so nothing is lost.
- CLI:
hermes curator <verb> โ status, run, pause, resume,
pin, unpin, archive, restore, prune, backup, rollback.
- Slash:
/curator <subcommand> mirrors the CLI.
- Scope: only touches skills with
created_by: "agent" provenance.
Bundled + hub-installed skills are off-limits. Never deletes โ
max destructive action is archive. Pinned skills are exempt from
every auto-transition and every LLM review pass.
- Telemetry: sidecar at
~/.hermes/skills/.usage.json holds
per-skill use_count, view_count, patch_count,
last_activity_at, state, pinned.
Config: curator.* (enabled, interval_hours, min_idle_hours,
stale_after_days, archive_after_days, backup.*).
User docs: https://hermes-agent.nousresearch.com/docs/user-guide/features/curator
Dreaming (periodic memory/skill consolidation)
For Anthropic-style "dreaming" workflows, combine cron + session_search + memory + skills + curator into a scheduled review loop. Start with a weekly, proposal-only report that audits recent sessions, repeated user corrections, memory conflicts, skill patch candidates, and cron/automation improvements. Do not automatically delete/replace memory or patch/archive skills unless the user explicitly approves the proposed changes. See references/weekly-dreaming-routine.md for the recommended prompt, report format, safety policy, and cron creation pattern.
Kanban (multi-agent work queue)
Durable SQLite board for multi-profile / multi-worker collaboration.
Users drive it via hermes kanban <verb>; dispatcher-spawned workers
see a focused kanban_* toolset gated by HERMES_KANBAN_TASK so the
schema footprint is zero outside worker processes.
- CLI verbs (common):
init, create, list (alias ls),
show, assign, link, unlink, comment, complete, block,
unblock, archive, tail. Less common: watch, stats, runs,
log, dispatch, daemon, gc.
- Worker toolset:
kanban_show, kanban_complete, kanban_block,
kanban_heartbeat, kanban_comment, kanban_create, kanban_link.
- Dispatcher runs inside the gateway by default
( kanban.dispatch_in_gateway: true) โ reclaims stale claims,
promotes ready tasks, atomically claims, spawns assigned profiles.
Auto-blocks a task after ~5 consecutive spawn failures.
- Isolation: board is the hard boundary (workers get
HERMES_KANBAN_BOARD pinned in env); tenant is a soft namespace
within a board for workspace-path + memory-key isolation.
User docs: https://hermes-agent.nousresearch.com/docs/user-guide/features/kanban
Log Relay (Hermes โ Discord)
A background Python script that tails ~/.hermes/logs/*.log and batches lines to a Discord channel. Includes session-ID extraction, rate-limit handling, and auto-restart via launchd/systemd. Useful for remote monitoring and audit trails.
- Reference:
references/discord-log-relay.md โ full setup, tuning, macOS/Linux service install, pitfalls.
- Template:
templates/discord-log-relay.py โ copy, set CHANNEL_ID, and deploy.
- Discord operations:
references/discord-operating-planes.md โ channel-purpose routing, periodic-summary vs Dreaming report formats, and safety/cost notes for Discord-first Hermes deployments.
Key pitfall: ask the user about batch frequency upfront rather than defaulting to real-time streaming. Most users prefer 10-minute or hourly batches. High-volume raw logs should be batched, summarized, or stored out-of-band; avoid Discord message storms during error loops.
Weekly Dreaming / Memory Curation
For long-running Hermes deployments, users may want an Anthropic-style "Dreaming" loop: a scheduled review that consolidates experience, proposes memory/skill/cron changes, and identifies what to keep, weaken, archive, or delete. Hermes has the building blocks (sessions, session_search, memory, skills, curator, cron), but the safe default is proposal mode:
1. Inspect recent usage and sessions.
2. Extract repeated success patterns, failure patterns, and user corrections.
3. Propose memory updates/removals without applying them silently.
4. Propose skill patches/archive candidates and cron/reporting improvements.
5. End with explicit approval checkboxes.
Do not silently rewrite or delete memory/skills from a Dreaming report unless the user explicitly authorized automatic application. See references/discord-operating-planes.md for a report template and routing heuristics.
---
Windows-Specific Quirks
Hermes runs natively on Windows (PowerShell, cmd, Windows Terminal, git-bash
mintty, VS Code integrated terminal). Most of it just works, but a handful
of differences between Win32 and POSIX have bitten us โ document new ones
here as you hit them so the next person (or the next session) doesn't
rediscover them from scratch.
Input / Keybindings
Alt+Enter doesn't insert a newline. Windows Terminal intercepts Alt+Enter
at the terminal layer to toggle fullscreen โ the keystroke never reaches
prompt_toolkit. Use Ctrl+Enter instead. Windows Terminal delivers
Ctrl+Enter as LF ( c-j), distinct from plain Enter ( c-m / CR), and the
CLI binds c-j to newline insertion on win32 only (see
_bind_prompt_submit_keys + the Windows-only c-j binding in cli.py).
Side effect: the raw Ctrl+J keystroke also inserts a newline on Windows โ
unavoidable, because Windows Terminal collapses Ctrl+Enter and Ctrl+J to
the same keycode at the Win32 console API layer. No conflicting binding
existed for Ctrl+J on Windows, so this is a harmless side effect.
mintty / git-bash behaves the same (fullscreen on Alt+Enter) unless you
disable Alt+Fn shortcuts in Options โ Keys. Easier to just use Ctrl+Enter.
Diagnosing keybindings. Run python scripts/keystroke_diagnostic.py
(repo root) to see exactly how prompt_toolkit identifies each keystroke
in the current terminal. Answers questions like "does Shift+Enter come
through as a distinct key?" (almost never โ most terminals collapse it
to plain Enter) or "what byte sequence is my terminal sending for
Ctrl+Enter?" This is how the Ctrl+Enter = c-j fact was established.
Config / Files
HTTP 400 "No models provided" on first run. config.yaml was saved
with a UTF-8 BOM (common when Windows apps write it). Re-save as UTF-8
without BOM. hermes config edit writes without BOM; manual edits in
Notepad are the usual culprit.
execute_code / Sandbox
WinError 10106 ("The requested service provider could not be loaded
or initialized") from the sandbox child process โ it can't create an
AF_INET socket, so the loopback-TCP RPC fallback fails before
connect(). Root cause is usually not a broken Winsock LSP; it's
Hermes's own env scrubber dropping SYSTEMROOT / WINDIR / COMSPEC
from the child env. Python's socket module needs SYSTEMROOT to locate
mswsock.dll. Fixed via the _WINDOWS_ESSENTIAL_ENV_VARS allowlist in
tools/code_execution_tool.py. If you still hit it, echo os.environ
inside an execute_code block to confirm SYSTEMROOT is set. Full
diagnostic recipe in references/execute-code-sandbox-env-windows.md.
Testing / Contributing
scripts/run_tests.sh doesn't work as-is on Windows โ it looks for
POSIX venv layouts ( .venv/bin/activate). The Hermes-installed venv at
venv/Scripts/ has no pip or pytest either (stripped for install size).
Workaround: install pytest + pytest-xdist + pyyaml into a system Python
3.11 user site, then invoke pytest directly with PYTHONPATH set:
"/c/Program Files/Python311/python" -m pip install --user pytest pytest-xdist pyyaml
export PYTHONPATH="$(pwd)"
"/c/Program Files/Python311/python" -m pytest tests/foo/test_bar.py -v --tb=short -n 0
Use -n 0, not -n 4 โ pyproject.toml's default addopts already
includes -n, and the wrapper's CI-parity guarantees don't apply off POSIX.
POSIX-only tests need skip guards. Common markers already in the codebase:
- Symlinks โ elevated privileges on Windows
0o600 file modes โ POSIX mode bits not enforced on NTFS by default
signal.SIGALRM โ Unix-only (see tests/conftest.py::_enforce_test_timeout)
- Winsock / Windows-specific regressions โ
@pytest.mark.skipif(sys.platform != "win32", ...)
Use the existing skip-pattern style (sys.platform == "win32" or
sys.platform.startswith("win")) to stay consistent with the rest of the
suite.
Path / Filesystem
Line endings. Git may warn LF will be replaced by CRLF the next time
Git touches it. Cosmetic โ the repo's .gitattributes normalizes. Don't
let editors auto-convert committed POSIX-newline files to CRLF.
Forward slashes work almost everywhere. C:/Users/... is accepted by
every Hermes tool and most Windows APIs. Prefer forward slashes in code
and logs โ avoids shell-escaping backslashes in bash.
---
Troubleshooting
Voice not working
1. Check stt.enabled: true in config.yaml
2. Verify provider: pip install faster-whisper or set API key
3. In gateway: /restart. In CLI: exit and relaunch.
Tool not available
1. hermes tools โ check if toolset is enabled for your platform
2. Some tools need env vars (check .env)
3. /reset after enabling tools
Model/provider issues
1. hermes doctor โ check config and dependencies
2. hermes auth add <provider> โ re-authenticate OAuth providers (use --type oauth)
3. Check .env has the right API key
4. Copilot 403: gh auth login tokens do NOT work for Copilot API. You must use the Copilot-specific OAuth device code flow via hermes model โ GitHub Copilot.
Changes not taking effect
- Tools/skills:
/reset starts a new session with updated toolset
- Config changes: In gateway:
/restart. In CLI: exit and relaunch.
- Code changes: Restart the CLI or gateway process
Deployed web dashboard shows stale CSS or theme changes
- Browser cache: Add
?v=N cache-busting query strings to CSS/JS/theme links in HTML.
- Service Worker cache: Bump
CACHE_NAME in sw.js to invalidate old shell caches.
- Data freshness: Use
fetch(url, {cache:'no-store'}) for live JSON feeds.
- See
references/static-site-cache-invalidation.md for the full diagnostic recipe.
Dashboard inspector feels too technical
- The default inspector view should contain only plain-language sentences: headline, "what they're doing now", "why it matters", and a silent visual progress bar (no text label).
- Move all technical fields (source IDs, confidence scores, progress labels, status slugs, badges) behind a "Show technical details" toggle.
- If users say "details are hard to understand," the fix is to remove more fields from the default view, not to add explanations. Explanations of technical fields are still technical.
- See
references/progressive-disclosure-human-first.md for the aggressive simplification pattern.
Skills not showing
1. hermes skills list โ verify installed
2. hermes skills config โ check platform enablement
3. Load explicitly: /skill name or hermes -s name
Gateway issues
Check logs first:
grep -i "failed to send\|error" ~/.hermes/logs/gateway.log | tail -20
Common gateway problems:
- Gateway dies on SSH logout: Enable linger:
sudo loginctl enable-linger $USER
- Gateway dies on WSL2 close: WSL2 requires
systemd=true in /etc/wsl.conf for systemd services to work. Without it, gateway falls back to nohup (dies when session closes).
- Gateway crash loop: Reset the failed state:
systemctl --user reset-failed hermes-gateway
- macOS: bot shows offline after idle time: The gateway runs as a user agent (
LimitLoadToSessionType=Aqua), so macOS suspends it when the system sleeps. The platform websocket drops and the bot appears offline until the network returns. Fix: keep the Mac awake (System Settings -> Energy -> Prevent automatic sleeping, or caffeinate -d -i -s -u &). Low Power Mode makes this worse, not better. See references/macos-gateway-sleep-disconnect.md for the full diagnostic recipe.
Platform-specific issues
- Discord bot silent: Must enable Message Content Intent in Bot โ Privileged Gateway Intents. See full Discord setup reference:
references/discord-gateway-setup.md.
- Slack bot only works in DMs: Must subscribe to
message.channels event. Without it, the bot ignores public channels.
- Windows-specific issues (
Alt+Enter newline, WinError 10106, UTF-8 BOM config, test suite, line endings): see the dedicated Windows-Specific Quirks section above.
Auxiliary models not working
If auxiliary tasks (vision, compression, session_search) fail silently, the auto provider can't find a backend. Either set OPENROUTER_API_KEY or GOOGLE_API_KEY, or explicitly configure each auxiliary task's provider:
hermes config set auxiliary.vision.provider <your_provider>
hermes config set auxiliary.vision.model <model_name>
Full system auth provisioning
For a one-shot workflow to maximize available credentials โ installing gh, generating SSH keys, configuring git, enabling all Hermes toolsets, and auditing current auth state โ see references/system-auth-setup.md.
Editing large files with patch
When a file is read with read_file(offset=...) (pagination), the tool warns that the view is partial. If you attempt patch without re-reading the full file first, you will likely hit non-unique match errors or corrupt the file. Fix: always call read_file without offset to load the whole file before patching. For append-only updates (e.g., adding a cycle log entry to state.md), do not use terminal(command="cat >> file << 'EOF'...EOF") โ the terminal tool on macOS/Linux misinterprets heredoc << as backgrounding and fails. Instead, write a short Python script via write_file and execute it with terminal(command="python3 /tmp/script.py"). See references/terminal-heredoc-workaround.md for the full pattern.
---
Windows-Specific Quirks
| Looking for... | Location |
|----------------|----------|
| Config options | hermes config edit or [Configuration docs](https://hermes-agent.nousresearch.com/docs/user-guide/configuration) |
| Available tools | hermes tools list or [Tools reference](https://hermes-agent.nousresearch.com/docs/reference/tools-reference) |
| Slash commands | /help in session or [Slash commands reference](https://hermes-agent.nousresearch.com/docs/reference/slash-commands) |
| Skills catalog | hermes skills browse or [Skills catalog](https://hermes-agent.nousresearch.com/docs/reference/skills-catalog) |
| Provider setup | hermes model or [Providers guide](https://hermes-agent.nousresearch.com/docs/integrations/providers) |
| Platform setup | hermes gateway setup or [Messaging docs](https://hermes-agent.nousresearch.com/docs/user-guide/messaging/) |
| MCP servers | hermes mcp list or [MCP guide](https://hermes-agent.nousresearch.com/docs/user-guide/features/mcp) |
| Profiles | hermes profile list or [Profiles docs](https://hermes-agent.nousresearch.com/docs/user-guide/profiles) |
| Cron jobs | hermes cron list or [Cron docs](https://hermes-agent.nousresearch.com/docs/user-guide/features/cron) |
| Memory | hermes memory status or [Memory docs](https://hermes-agent.nousresearch.com/docs/user-guide/features/memory) |
| Env variables | hermes config env-path or [Env vars reference](https://hermes-agent.nousresearch.com/docs/reference/environment-variables) |
| CLI commands | hermes --help or [CLI reference](https://hermes-agent.nousresearch.com/docs/reference/cli-commands) |
| Gateway logs | ~/.hermes/logs/gateway.log |
| Session files | ~/.hermes/sessions/ or hermes sessions browse |
| Source code | ~/.hermes/hermes-agent/ |
---
Contributor Quick Reference
For occasional contributors and PR authors. Full developer docs: https://hermes-agent.nousresearch.com/docs/developer-guide/
Project Layout
hermes-agent/
โโโ run_agent.py # AIAgent โ core conversation loop
โโโ model_tools.py # Tool discovery and dispatch
โโโ toolsets.py # Toolset definitions
โโโ cli.py # Interactive CLI (HermesCLI)
โโโ hermes_state.py # SQLite session store
โโโ agent/ # Prompt builder, context compression, memory, model routing, credential pooling, skill dispatch
โโโ hermes_cli/ # CLI subcommands, config, setup, commands
โ โโโ commands.py # Slash command registry (CommandDef)
โ โโโ config.py # DEFAULT_CONFIG, env var definitions
โ โโโ main.py # CLI entry point and argparse
โโโ tools/ # One file per tool
โ โโโ registry.py # Central tool registry
โโโ gateway/ # Messaging gateway
โ โโโ platforms/ # Platform adapters (telegram, discord, etc.)
โโโ cron/ # Job scheduler
โโโ tests/ # ~3000 pytest tests
โโโ website/ # Docusaurus docs site
Config: ~/.hermes/config.yaml (settings), ~/.hermes/.env (API keys).
Adding a Tool (3 files)
1. Create tools/your_tool.py:
import json, os
from tools.registry import registry
def check_requirements() -> bool:
return bool(os.getenv("EXAMPLE_API_KEY"))
def example_tool(param: str, task_id: str = None) -> str:
return json.dumps({"success": True, "data": "..."})
registry.register(
name="example_tool",
toolset="example",
schema={"name": "example_tool", "description": "...", "parameters": {...}},
handler=lambda args, **kw: example_tool(
param=args.get("param", ""), task_id=kw.get("task_id")),
check_fn=check_requirements,
requires_env=["EXAMPLE_API_KEY"],
)
2. Add to toolsets.py โ _HERMES_CORE_TOOLS list.
Auto-discovery: any tools/*.py file with a top-level registry.register() call is imported automatically โ no manual list needed.
All handlers must return JSON strings. Use get_hermes_home() for paths, never hardcode ~/.hermes.
Adding a Slash Command
1. Add CommandDef to COMMAND_REGISTRY in hermes_cli/commands.py
2. Add handler in cli.py โ process_command()
3. (Optional) Add gateway handler in gateway/run.py
All consumers (help text, autocomplete, Telegram menu, Slack mapping) derive from the central registry automatically.
Agent Loop (High Level)
run_conversation():
1. Build system prompt
2. Loop while iterations < max:
a. Call LLM (OpenAI-format messages + tool schemas)
b. If tool_calls โ dispatch each via handle_function_call() โ append results โ continue
c. If text response โ return
3. Context compression triggers automatically near token limit
Testing
python -m pytest tests/ -o 'addopts=' -q # Full suite
python -m pytest tests/tools/ -q # Specific area
- Tests auto-redirect
HERMES_HOME to temp dirs โ never touch real ~/.hermes/
- Run full suite before pushing any change
- Use
-o 'addopts=' to clear any baked-in pytest flags
Windows contributors: scripts/run_tests.sh currently looks for POSIX venvs ( .venv/bin/activate / venv/bin/activate) and will error out on Windows where the layout is venv/Scripts/activate + python.exe. The Hermes-installed venv at venv/Scripts/ also has no pip or pytest โ it's stripped for end-user install size. Workaround: install pytest + pytest-xdist + pyyaml into a system Python 3.11 user site ( /c/Program Files/Python311/python -m pip install --user pytest pytest-xdist pyyaml), then run tests directly:
export PYTHONPATH="$(pwd)"
"/c/Program Files/Python311/python" -m pytest tests/tools/test_foo.py -v --tb=short -n 0
Use -n 0 (not -n 4) because pyproject.toml's default addopts already includes -n, and the wrapper's CI-parity story doesn't apply off-POSIX.
Cross-platform test guards: tests that use POSIX-only syscalls need a skip marker. Common ones already in the codebase:
- Symlink creation โ
@pytest.mark.skipif(sys.platform == "win32", reason="Symlinks require elevated privileges on Windows") (see tests/cron/test_cron_script.py)
- POSIX file modes (0o600, etc.) โ
@pytest.mark.skipif(sys.platform.startswith("win"), reason="POSIX mode bits not enforced on Windows") (see tests/hermes_cli/test_auth_toctou_file_modes.py)
signal.SIGALRM โ Unix-only (see tests/conftest.py::_enforce_test_timeout)
- Live Winsock / Windows-specific regression tests โ
@pytest.mark.skipif(sys.platform != "win32", reason="Windows-specific regression")
Monkeypatching sys.platform is not enough when the code under test also calls platform.system() / platform.release() / platform.mac_ver(). Those functions re-read the real OS independently, so a test that sets sys.platform = "linux" on a Windows runner will still see platform.system() == "Windows" and route through the Windows branch. Patch all three together:
monkeypatch.setattr(sys, "platform", "linux")
monkeypatch.setattr(platform, "system", lambda: "Linux")
monkeypatch.setattr(platform, "release", lambda: "6.8.0-generic")
See tests/agent/test_prompt_builder.py::TestEnvironmentHints for a worked example.
Extending the system prompt's execution-environment block
Factual guidance about the host OS, user home, cwd, terminal backend, and shell (bash vs. PowerShell on Windows) is emitted from agent/prompt_builder.py::build_environment_hints(). This is also where the WSL hint and per-backend probe logic live. The convention:
- Local terminal backend โ emit host info (OS,
$HOME, cwd) + Windows-specific notes (hostname โ username, terminal uses bash not PowerShell).
- Remote terminal backend (anything in
_REMOTE_TERMINAL_BACKENDS: docker, singularity, modal, daytona, ssh, vercel_sandbox, managed_modal) โ suppress host info entirely and describe only the backend. A live uname/whoami/pwd probe runs inside the backend via tools.environments.get_environment(...).execute(...), cached per process in _BACKEND_PROBE_CACHE, with a static fallback if the probe times out.
- Key fact for prompt authoring: when
TERMINAL_ENV != "local", every file tool (read_file, write_file, patch, search_files) runs inside the backend container, not on the host. The system prompt must never describe the host in that case โ the agent can't touch it.
Full design notes, the exact emitted strings, and testing pitfalls:
references/prompt-builder-environment-hints.md.
Refactor-safety pattern (POSIX-equivalence guard): when you extract inline logic into a helper that adds Windows/platform-specific behavior, keep a _legacy_<name> oracle function in the test file that's a verbatim copy of the old code, then parametrize-diff against it. Example: tests/tools/test_code_execution_windows_env.py::TestPosixEquivalence. This locks in the invariant that POSIX behavior is bit-for-bit identical and makes any future drift fail loudly with a clear diff.
Commit Conventions
type: concise subject line
Optional body.
Types: fix:, feat:, refactor:, docs:, chore:
Key Rules
- Never break prompt caching โ don't change context, tools, or system prompt mid-conversation
- Message role alternation โ never two assistant or two user messages in a row
- Use
get_hermes_home() from hermes_constants for all paths (profile-safe)
- Config values go in
config.yaml, secrets go in .env
- New tools need a
check_fn so they only appear when requirements are met
[IMPORTANT: The user has invoked the "kanban-orchestrator" skill, indicating they want you to follow its instructions. The full skill content is loaded below.]
---
name: kanban-orchestrator
description: Decomposition playbook + anti-temptation rules for an orchestrator profile routing work through Kanban. The "don't do the work yourself" rule and the basic lifecycle are auto-injected into every kanban worker's system prompt; this skill is the deeper playbook when you're specifically playing the orchestrator role.
version: 3.0.0
platforms: [linux, macos, windows]
metadata:
hermes:
tags: [kanban, multi-agent, orchestration, routing]
related_skills: [kanban-worker]
---
Kanban Orchestrator โ Decomposition Playbook
> The core worker lifecycle (including the kanban_create fan-out pattern and the "decompose, don't execute" rule) is auto-injected into every kanban process via the KANBAN_GUIDANCE system-prompt block. This skill is the deeper playbook when you're an orchestrator profile whose whole job is routing.
Profiles are user-configured โ not a fixed roster
Hermes setups vary widely. Some users run a single profile that does everything; some run a small fleet (docker-worker, cron-worker); some run a curated specialist team they've named themselves. There is no default specialist roster โ the orchestrator skill does not know what profiles exist on this machine.
Before fanning out, you must ground the decomposition in the profiles that actually exist. The dispatcher silently fails to spawn unknown assignee names โ it doesn't autocorrect, doesn't suggest, doesn't fall back. So a card assigned to researcher on a setup that only has docker-worker just sits in ready forever.
Step 0: discover available profiles before planning.
Use one of these:
hermes profile list โ prints the table of profiles configured on this machine. Run it through your terminal tool if you have one; otherwise ask the user.
kanban_list(assignee="<some-name>") โ sanity-check a single name. Returns an empty list (rather than an error) for an unknown assignee, so this only confirms a name you're already considering.
- Just ask the user. "What profiles do you have set up?" is a fine first turn when the goal needs more than one specialist.
Cache the result in your working memory for the rest of the conversation. Re-asking every turn wastes a tool call.
When to use the board (vs. just doing the work)
Create Kanban tasks when any of these are true:
1. Multiple specialists are needed. Research + analysis + writing is three profiles.
2. The work should survive a crash or restart. Long-running, recurring, or important.
3. The user might want to interject. Human-in-the-loop at any step.
4. Multiple subtasks can run in parallel. Fan-out for speed.
5. Review / iteration is expected. A reviewer profile loops on drafter output.
6. The audit trail matters. Board rows persist in SQLite forever.
If none of those apply โ it's a small one-shot reasoning task โ use delegate_task instead or answer the user directly.
The anti-temptation rules
Your job description says "route, don't execute." The rules that enforce that:
- Do not execute the work yourself. Your restricted toolset usually doesn't even include terminal/file/code/web for implementation. If you find yourself "just fixing this quickly" โ stop and create a task for the right specialist.
- For any concrete task, create a Kanban task and assign it. Every single time.
- Split multi-lane requests before creating cards. A user prompt can contain several independent workstreams. Extract those lanes first, then create one card per lane instead of bundling unrelated work into a single implementer card.
- Run independent lanes in parallel. If two cards do not need each other's output, leave them unlinked so the dispatcher can fan them out. Link only true data dependencies.
- If no specialist fits the available profiles, ask the user which profile to create or which existing profile to use. Do not invent profile names; the dispatcher will silently drop unknown assignees.
- Decompose, route, and summarize โ that's the whole job.
Exception: micro-UI polish cycles
There is one narrow exception where the orchestrator may execute directly instead of creating Kanban cards: tiny UI-only polish cycles (e.g., adding a CSS class, a theme preview dot, a hover state, a cross-link, or a HUD button) that are purely presentational, require no cross-file logic changes, and fit comfortably inside a single bounded cycle with no need for review or parallel work. If the change is limited to HTML/CSS/JS cosmetics, no other profile has a stake in it, and the user did not ask for a design review, the orchestrator should just edit and publish rather than paying the kanban-overhead tax. This exception does NOT apply to architecture changes, adapter logic, plugin interfaces, or anything that touches the data layer.
Decomposition playbook
Step 1 โ Understand the goal
Ask clarifying questions if the goal is ambiguous. Cheap to ask; expensive to spawn the wrong fleet.
Step 2 โ Sketch the task graph
Before creating anything, draft the graph out loud (in your response to the user). Treat every concrete workstream as a candidate card:
1. Extract the lanes from the request.
2. Map each lane to one of the profiles you discovered in Step 0. If a lane doesn't fit any existing profile, ask the user which to use or create.
3. Decide whether each lane is independent or gated by another lane.
4. Create independent lanes as parallel cards with no parent links.
5. Create synthesis/review/integration cards with parent links to the lanes they depend on.
Examples of prompts that should fan out (using placeholder profile names โ substitute whatever exists on the user's setup):
- "Build an app" โ one card to a design-oriented profile for product/UI direction, one or two cards to engineering profiles for implementation, plus a later integration/review card if the user has a reviewer profile.
- "Fix blockers and check model variants" โ one implementation card for the blocker fixes plus one discovery/research card for config/source verification. A final reviewer card can depend on both.
- "Research docs and implement" โ a docs-research card can run in parallel with a codebase-discovery card; implementation waits only if it truly needs those findings.
- "Analyze this screenshot and find the related code" โ one card to a vision-capable profile for the visual analysis while another searches the codebase.
Words like "also," "finally," or "and" do not automatically imply a dependency. They often mean "make sure this is covered before reporting back." Only link tasks when one card cannot start until another card's output exists.
Show the graph to the user before creating cards. Let them correct it โ including which actual profile name should own each lane.
Step 3 โ Create tasks and link
Use the profile names from Step 0. The example below uses placeholders <profile-A>, <profile-B>, <profile-C> โ replace them with what the user actually has.
t1 = kanban_create(
title="research: Postgres cost vs current",
assignee="<profile-A>", # whichever profile handles research on this setup
body="Compare estimated infrastructure costs, migration costs, and ongoing ops costs over a 3-year window. Sources: AWS/GCP pricing, team time estimates, current Postgres bills from peers.",
tenant=os.environ.get("HERMES_TENANT"),
)["task_id"]
t2 = kanban_create(
title="research: Postgres performance vs current",
assignee="<profile-A>", # same profile, run in parallel
body="Compare query latency, throughput, and scaling characteristics at our expected data volume (~500GB, 10k QPS peak). Sources: benchmark papers, public case studies, pgbench results if easy.",
)["task_id"]
t3 = kanban_create(
title="synthesize migration recommendation",
assignee="<profile-B>", # whichever profile does synthesis/analysis
body="Read the findings from T1 (cost) and T2 (performance). Produce a 1-page recommendation with explicit trade-offs and a go/no-go call.",
parents=[t1, t2],
)["task_id"]
t4 = kanban_create(
title="draft decision memo",
assignee="<profile-C>", # whichever profile drafts user-facing prose
body="Turn the analyst's recommendation into a 2-page memo for the CTO. Match the tone of previous decision memos in the team's knowledge base.",
parents=[t3],
)["task_id"]
parents=[...] gates promotion โ children stay in todo until every parent reaches done, then auto-promote to ready. No manual coordination needed; the dispatcher and dependency engine handle it.
Step 4 โ Complete your own task
If you were spawned as a task yourself (e.g. a planner profile was assigned T0: "investigate Postgres migration"), mark it done with a summary of what you created:
kanban_complete(
summary="decomposed into T1-T4: 2 research lanes in parallel, 1 synthesis on their outputs, 1 prose draft on the recommendation",
metadata={
"task_graph": {
"T1": {"assignee": "<profile-A>", "parents": []},
"T2": {"assignee": "<profile-A>", "parents": []},
"T3": {"assignee": "<profile-B>", "parents": ["T1", "T2"]},
"T4": {"assignee": "<profile-C>", "parents": ["T3"]},
},
},
)
Step 5 โ Report back to the user
Tell them what you created in plain prose, naming the actual profiles you used:
> I've queued 4 tasks:
> - T1 (<profile-A>): cost comparison
> - T2 (<profile-A>): performance comparison, in parallel with T1
> - T3 (<profile-B>): synthesizes T1 + T2 into a recommendation
> - T4 (<profile-C>): turns T3 into a CTO memo
>
> The dispatcher will pick up T1 and T2 now. T3 starts when both finish. You'll get a gateway ping when T4 completes. Use the dashboard or hermes kanban tail <id> to follow along.
Common patterns
Fan-out + fan-in (research โ synthesize): N research-style cards with no parents, one synthesis card with all of them as parents.
Parallel implementation + validation: one implementer card makes the change while one explorer/researcher card verifies config, docs, or source mapping. A reviewer card can depend on both. Do not make the implementer own unrelated verification just because the user mentioned both in one sentence.
Pipeline with gates: planner โ implementer โ reviewer. Each stage's parents=[previous_task]. Reviewer blocks or completes; if reviewer blocks, the operator unblocks with feedback and respawns.
Same-profile queue: N tasks, all assigned to the same profile, no dependencies between them. Dispatcher serializes โ that profile processes them in priority order, accumulating experience in its own memory.
Parallel UI/frontend lanes: When the goal touches multiple independent HTML/CSS/JS files (e.g., a dashboard page and a 2D gather view), fan out to separate subagents per file. Each lane edits its own file, then the orchestrator integrates, fixes cross-file references (theme paths, shared JSON endpoints), and publishes. This avoids merge conflicts in single-file HTML dashboards and keeps each subagent's context focused. See references/parallel-ui-lanes-and-publishing.md for the post-subagent integration checklist and rsync safety notes.
Human-in-the-loop: Any task can kanban_block() to wait for input. Dispatcher respawns after /unblock. The comment thread carries the full context.
Pitfalls
Inventing profile names that don't exist. The dispatcher silently fails to spawn unknown assignees โ the card just sits in ready forever. Always assign to a profile from your Step 0 discovery; ask the user if you're unsure.
Bundling independent lanes into one card. If the user asks for two independent outcomes, create two cards. Example: "fix blockers and check model variants" is not one fixer task; create a fixer/engineer card for the fixes and an explorer/researcher card for the variant check, then optionally gate review on both.
Over-linking because of wording. "Finally check X" may still be parallel with implementation if X is static config, docs, or source discovery. Link it after implementation only when the check depends on the implementation result.
Forgetting dependency links. If the task graph says research -> implement -> review, do not create all tasks as independent ready cards. Use parent links so implement/review cannot run before their inputs exist.
Reassignment vs. new task. If a reviewer blocks with "needs changes," create a NEW task linked from the reviewer's task โ don't re-run the same task with a stern look. The new task is assigned to the original implementer profile.
Argument order for links. kanban_link(parent_id=..., child_id=...) โ parent first. Mixing them up demotes the wrong task to todo.
Ignoring explicit user feedback to keep building infrastructure. When the user says a specific UX issue (legibility, theme switching, movement density) is "immediate priority," treat it as P0 and route it before deeper packaging/architecture work. Infrastructure polish feels productive, but shipping user-visible fixes is what matters. Create cards for the UX feedback first, then resume infrastructure lanes.
Treating status: complete as immutable when user feedback says otherwise. A state.md that says status: complete does not override a user's report that a completion criterion is actually broken. If the user says "theme switching is not working" and the Final Completion Condition requires "working UI theme switcher," the mission is not complete. Reactivate immediately: set status: active, append a reactivation cycle log, and fix the issue. Do not burn cycles on post-complete verification while the user is reporting active defects.
Don't pre-create the whole graph if the shape depends on intermediate findings. If T3's structure depends on what T1 and T2 find, let T3 exist as a "synthesize findings" task whose own first step is to read parent handoffs and plan the rest. Orchestrators can spawn orchestrators.
Tenant inheritance. If HERMES_TENANT is set in your env, pass tenant=os.environ.get("HERMES_TENANT") on every kanban_create call so child tasks stay in the same namespace.
Verifying cross-file references after directory reorganization. When subagents edit HTML/CSS/JS files and the directory structure shifts (e.g., moving files from root into web/dashboard/ and web/gather/), relative asset paths ( themes/default/theme.css, ./ops-data.json) often break. After subagents finish, the orchestrator must grep for href= and src= in moved files and fix relative paths before publishing. Subagents don't know the final publish layout โ the orchestrator does.
Destructive sync wipes needed files. Commands like rsync -av --delete will delete destination files that aren't in the source list. If you publish a directory tree piecemeal (e.g., copy web/dashboard/ first, then web/gather/ separately), --delete on the first rsync will erase the gather files before the second rsync runs. Either list all source paths in a single rsync invocation, or omit --delete and use cp -r / rsync -av without deletion when doing staged copies.
Recovering stuck workers
When a worker profile keeps crashing, hallucinating, or getting blocked by its own mistakes (usually: wrong model, missing skill, broken credential), the kanban dashboard flags the task with a โ badge and opens a Recovery section in the drawer. Three primary actions:
1. Reclaim (or hermes kanban reclaim <task_id>) โ abort the running worker immediately and reset the task to ready. The existing claim TTL is ~15 min; this is the fast path out.
2. Reassign (or hermes kanban reassign <task_id> <new-profile> --reclaim) โ switch the task to a different profile (one that exists on this setup) and let the dispatcher pick it up with a fresh worker.
3. Change profile model โ the dashboard prints a copy-paste hint for hermes -p <profile> model since profile config lives on disk; edit it in a terminal, then Reclaim to retry with the new model.
Hallucination warnings appear on tasks where a worker's kanban_complete(created_cards=[...]) claim included card ids that don't exist or weren't created by the worker's profile (the gate blocks the completion), or where the free-form summary references t_<hex> ids that don't resolve (advisory prose scan, non-blocking). Both produce audit events that persist even after recovery actions โ the trail stays for debugging.
The user has provided the following instruction alongside the skill invocation: [IMPORTANT: You are running as a scheduled cron job. DELIVERY: Your final response will be automatically delivered to the user โ do NOT use send_message or try to deliver the output yourself. Just produce your report/output as your final response and the system handles the rest. SILENT: If there is genuinely nothing new to report, respond with exactly "[SILENT]" (nothing else) to suppress delivery. Never combine [SILENT] with content โ either report your findings normally, or say [SILENT] and nothing more.]
You are the 15-minute Orchestrator for Son's Autonomous Agent Lab v1, reporting to Discord channel ID 1505805763824586952.
Durable state path: /Users/jooho-hermes/.hermes/autonomous-agent-lab/state.md
Working directory for experiment artifacts: /Users/jooho-hermes/.hermes/autonomous-agent-lab/
Preferred published web root: /Users/jooho-hermes/hermes-web/agent-pets/
Top-level directive from Son:
- The project has evolved from a personal dashboard into an INSTALLABLE PRODUCT that external Hermes users can deploy.
- The final target is a self-contained, configurable, publishable solution: "Hermes Pixel Pet Ops Office".
- Do NOT shrink the mission into a small static MVP and autonomously stop.
- The Gather.town-style 2D spatial office is a first-class feature, not a side page.
Latest UX feedback from Son (treat as immediate priority before deeper packaging work):
- Details are hard for a human to understand. Add human-first summaries, plain-language labels, and progressive disclosure: summary first, technical details second.
- Gather Town version has too many agents roaming around. Reduce default movement, add density/speed controls, cluster agents by room/task, and add focus/calm mode.
- Theme switching is not visibly working. Implement real UI theme switcher with persistence and clear visual theme changes.
Key product requirements (installable solution level):
1. Config-driven architecture: all paths, URLs, colors, names, room layouts via config.yaml. No hardcoded references to jooho-hermes.
2. Self-contained package: clear directory structure (src/, web/, config/, docs/, scripts/), install script, requirements.txt.
3. Pluggable data adapter: support multiple backends via plugin architecture.
4. Themeable frontend: CSS variables driven from config, swappable themes, plus a working UI theme switcher.
5. Multi-tenant ready: works for any Hermes instance.
6. Build/Deploy ready: Dockerfile or docker-compose, or clear static-server setup.
7. Documentation: README, architecture docs, configuration reference, contributor guide.
8. Human-comprehensible UX: plain-language summaries and progressive disclosure for technical detail.
9. Gather.town calm mode: adjustable movement density/speed and less chaotic defaults.
10. Versioned releases: CHANGELOG.md, semantic versioning, release packaging.
Mission model:
- Read state.md first before doing anything else.
- If state.md says
status: inactive or has no Current Mission, do not invent work. Return exactly: ๐ก Autonomous Agent Lab ๋๊ธฐ์ค โ Son์ด ํธ๋ฆฌ๊ฑฐ/๋ฏธ์
์ ์ฃผ๋ฉด 15๋ถ ์ฌ์ดํด์ ์์ํฉ๋๋ค.
- If state.md says
status: active, run one bounded 15-minute cycle toward the full installable solution.
- If state.md says
status: complete, verify that the Final Completion Condition in state.md is truly met. If it is not fully met, reactivate or report that state needs correction.
Cycle procedure when active:
1. Read state.md first. Extract current mission, constraints, previous cycle log, and Final Completion Condition.
2. Decide the next smallest useful step toward installable solution quality. Focus on: architecture, configurability, documentation, and clean separation of concerns.
3. Use delegate_task for independent subagent lanes when helpful.
4. Prefer concrete progress: refactor to config-driven, add install scripts, create docs, add Docker support, theme system, plugin architecture.
5. Update state.md with a new cycle log entry before final reporting.
6. Completion rule: only set status: complete when every item under state.md Final Completion Condition is satisfied. A non-installable MVP is not complete.
7. Stop/block only if Son explicitly stops/redirects, a safety boundary is reached, or a hard blocker needs Son's decision.
Link requirement (never forget):
- Every cycle report MUST include at least one direct viewable link to the published dashboard/artifact.
- The canonical URL:
http://hermes-mac-mini.tail46b3c6.ts.net:8099/agent-pets/
- Include gather town URL too:
http://hermes-mac-mini.tail46b3c6.ts.net:8099/agent-pets/gather/
Final Discord message format:
[Autonomous Agent Lab v1 / Cycle N]
๋ชฉํ:
์ํ:
๊ฒฐ๊ณผ:
๊ฒ์ฆ:
๋ค์:
์ํ:
Safety/quality rules:
- Do not handle secrets, passwords, API keys, payment, permission dialogs, or destructive commands.
- Do not claim completion without updating state.md.
- Do not rely on Discord history as durable state.
- Do not spam raw logs; summarize lane outputs and verification.
- Keep working in /Users/jooho-hermes/.hermes/autonomous-agent-lab/ and publish only to /Users/jooho-hermes/hermes-web/agent-pets/ unless the state file says otherwise.
Design/UX priorities:
- Mobile responsiveness is first-class.
- Character animation/movement is desired.
- Every cycle report must include published links.
- This is now a product engineering mission. Architecture, configurability, and documentation matter as much as visuals.
Error
RuntimeError: [Autonomous Agent Lab v1 / Cycle 62]
๋ชฉํ:
Fix cache/version inconsistencies discovered during Cycle 61 post-completion verification, and add a keyboard shortcuts convenience feature to the dashboard.
์ํ:
1. Cache busting fix โ Bumped all asset query strings to ?v=62 consistently across:
web/dashboard/index.html (CSS + JS)
web/gather/index.html (theme + CSS + JS)
This eliminates the stale-JS risk where dashboard CSS was at v61 but JS was still at v60.
2. Version drift fix โ Corrected the footer build badge from v1.4.5 ยท b61 to v1.4.4 ยท b62, matching config.yaml and the packaged release.
3. Adapter metadata enrichment โ Patched src/adapter/generate_ops_data.py to emit product and version keys into ops-data.json (was missing, causing the Settings panel to show fallback 1.3.0).
4. Keyboard shortcuts convenience feature โ Added a ? key help modal to web/js/dashboard.js with 12 shortcuts:
/ = focus search
1/W/B/F = quick filters (all / working / blocked / favorites)
T = cycle theme
R = refresh data
G = open Gather Town
M/H = toggle metrics / history panels
Esc = close any open modal/panel/inspector
Added matching CSS styles to web/css/dashboard.css (mobile-responsive).
๊ฒฐ๊ณผ:
All source files are patched and ready. The shortcut modal, consistent cache busting, and version alignment are in place. Adapter still needs one regeneration run to populate the new product/version fields in ops-data.json.
๊ฒ์ฆ:
- Source file edits verified via diff (dashboard HTML, gather HTML, adapter Python, dashboard JS, dashboard CSS).
- Accidental CSS overwrite was recovered from the published web root (
/hermes-web/agent-pets/css/dashboard.css).
- Code syntax validated for all patched files.
๋ค์:
Run python3 -m src.adapter.generate_ops_data, then bash scripts/publish.sh config.yaml, then bash scripts/test.sh, and update state.md with Cycle 62 completion log.
์ํ:
๐ก active โ awaiting adapter regeneration + publish + test run to fully deploy Cycle 62 changes.
๐ Dashboard: http://hermes-mac-mini.tail46b3c6.ts.net:8099/agent-pets/
๐ Gather Town: http://hermes-mac-mini.tail46b3c6.ts.net:8099/agent-pets/gather/
|
| 2026-05-19 16-45-32 |
80,432 chars |
2026-05-19_16-45-32.md |
Cron Job: autonomous-agent-lab-v1-orchestrator
Job ID: 35127ff89556
Run Time: 2026-05-19 16:45:32
Schedule: every 15m
Prompt
[IMPORTANT: The user has invoked the "hermes-agent" skill, indicating they want you to follow its instructions. The full skill content is loaded below.]
---
name: hermes-agent
description: "Configure, extend, or contribute to Hermes Agent."
version: 2.1.0
author: Hermes Agent + Teknium
license: MIT
platforms: [linux, macos, windows]
metadata:
hermes:
tags: [hermes, setup, configuration, multi-agent, spawning, cli, gateway, development]
homepage: https://github.com/NousResearch/hermes-agent
related_skills: [claude-code, codex, opencode]
---
Hermes Agent
Hermes Agent is an open-source AI agent framework by Nous Research that runs in your terminal, messaging platforms, and IDEs. It belongs to the same category as Claude Code (Anthropic), Codex (OpenAI), and OpenClaw โ autonomous coding and task-execution agents that use tool calling to interact with your system. Hermes works with any LLM provider (OpenRouter, Anthropic, OpenAI, DeepSeek, local models, and 15+ others) and runs on Linux, macOS, and WSL.
What makes Hermes different:
- Self-improving through skills โ Hermes learns from experience by saving reusable procedures as skills. When it solves a complex problem, discovers a workflow, or gets corrected, it can persist that knowledge as a skill document that loads into future sessions. Skills accumulate over time, making the agent better at your specific tasks and environment.
- Persistent memory across sessions โ remembers who you are, your preferences, environment details, and lessons learned. Pluggable memory backends (built-in, Honcho, Mem0, and more) let you choose how memory works.
- Multi-platform gateway โ the same agent runs on Telegram, Discord, Slack, WhatsApp, Signal, Matrix, Email, and 10+ other platforms with full tool access, not just chat.
- Provider-agnostic โ swap models and providers mid-workflow without changing anything else. Credential pools rotate across multiple API keys automatically.
- Profiles โ run multiple independent Hermes instances with isolated configs, sessions, skills, and memory.
- Extensible โ plugins, MCP servers, custom tools, webhook triggers, cron scheduling, and the full Python ecosystem.
People use Hermes for software development, research, system administration, data analysis, content creation, home automation, and anything else that benefits from an AI agent with persistent context and full system access.
This skill helps you work with Hermes Agent effectively โ setting it up, configuring features, spawning additional agent instances, troubleshooting issues, finding the right commands and settings, and understanding how the system works when you need to extend or contribute to it.
Docs: https://hermes-agent.nousresearch.com/docs/
Quick Start
Install
curl -fsSL https://raw.githubusercontent.com/NousResearch/hermes-agent/main/scripts/install.sh | bash
Interactive chat (default)
hermes
Single query
hermes chat -q "What is the capital of France?"
Setup wizard
hermes setup
Change model/provider
hermes model
Check health
hermes doctor
---
CLI Reference
Global Flags
hermes [flags] [command]
--version, -V Show version
--resume, -r SESSION Resume session by ID or title
--continue, -c [NAME] Resume by name, or most recent session
--worktree, -w Isolated git worktree mode (parallel agents)
--skills, -s SKILL Preload skills (comma-separate or repeat)
--profile, -p NAME Use a named profile
--yolo Skip dangerous command approval
--pass-session-id Include session ID in system prompt
No subcommand defaults to chat.
Chat
hermes chat [flags]
-q, --query TEXT Single query, non-interactive
-m, --model MODEL Model (e.g. anthropic/claude-sonnet-4)
-t, --toolsets LIST Comma-separated toolsets
--provider PROVIDER Force provider (openrouter, anthropic, nous, etc.)
-v, --verbose Verbose output
-Q, --quiet Suppress banner, spinner, tool previews
--checkpoints Enable filesystem checkpoints (/rollback)
--source TAG Session source tag (default: cli)
Configuration
hermes setup [section] Interactive wizard (model|terminal|gateway|tools|agent)
hermes model Interactive model/provider picker
hermes config View current config
hermes config edit Open config.yaml in $EDITOR
hermes config set KEY VAL Set a config value
hermes config path Print config.yaml path
hermes config env-path Print .env path
hermes config check Check for missing/outdated config
hermes config migrate Update config with new options
hermes doctor [--fix] Check dependencies and config
Credential Pools
hermes auth add Interactive credential wizard (oauth, api-key)
hermes auth list [PROVIDER] List pooled credentials
hermes auth remove P INDEX Remove by provider + index
hermes auth reset PROVIDER Clear exhaustion status
hermes logout Clear stored auth
Tools & Skills
hermes tools Interactive tool enable/disable (curses UI)
hermes tools list Show all tools and status
hermes tools enable NAME Enable a toolset
hermes tools disable NAME Disable a toolset
hermes skills list List installed skills
hermes skills search QUERY Search the skills hub
hermes skills install ID Install a skill (ID can be a hub identifier OR a direct https://โฆ/SKILL.md URL; pass --name to override when frontmatter has no name)
hermes skills inspect ID Preview without installing
hermes skills config Enable/disable skills per platform
hermes skills check Check for updates
hermes skills update Update outdated skills
hermes skills uninstall N Remove a hub skill
hermes skills publish PATH Publish to registry
hermes skills browse Browse all available skills
hermes skills tap add REPO Add a GitHub repo as skill source
MCP Servers
hermes mcp serve Run Hermes as an MCP server
hermes mcp add NAME Add an MCP server (--url or --command)
hermes mcp remove NAME Remove an MCP server
hermes mcp list List configured servers
hermes mcp test NAME Test connection
hermes mcp configure NAME Toggle tool selection
Gateway (Messaging Platforms)
hermes gateway run Start gateway foreground
hermes gateway install Install as background service
hermes gateway start/stop Control the service
hermes gateway restart Restart the service
hermes gateway status Check status
hermes gateway setup Configure platforms
Supported platforms: Telegram, Discord, Slack, WhatsApp, Signal, Email, SMS, Matrix, Mattermost, Home Assistant, DingTalk, Feishu, WeCom, BlueBubbles (iMessage), Weixin (WeChat), API Server, Webhooks. Open WebUI connects via the API Server adapter.
Platform docs: https://hermes-agent.nousresearch.com/docs/user-guide/messaging/
Discord-specific walkthrough (token, intents, service install, access control): see references/discord-gateway-setup.md in this skill.
- Per-channel personas and skill bindings: see
references/gateway-channel-personas.md (works on Discord, Slack, Telegram, Mattermost, Matrix).
- For long-running Discord-first operations, purpose-specific channel routing, periodic summaries, weekly Dreaming/audit reports, and log-safety patterns: see
references/discord-operating-planes.md.
- For broad Hermes/LifeOS/SQAF ecosystem audits (cron inventory, live services, dashboards, provider/model warnings, and control-plane gaps), see
references/ecosystem-audit.md.
Sessions
hermes sessions list List recent sessions
hermes sessions browse Interactive picker
hermes sessions export OUT Export to JSONL
hermes sessions rename ID T Rename a session
hermes sessions delete ID Delete a session
hermes sessions prune Clean up old sessions (--older-than N days)
hermes sessions stats Session store statistics
For browser-based viewing of existing Hermes CLI/Discord/cron session transcripts, prefer a lightweight static export from ~/.hermes/state.db into a private web root instead of assuming Open WebUI can browse Hermes' native session store. See references/hermes-session-static-web-viewer.md for the SQLite schema, static HTML export workflow, redaction/truncation cautions, and the user's Mac mini deployment (/hermes-sessions/ under the Tailscale-only ~/hermes-web site).
For cron job execution history, the same static-export pattern applies to ~/.hermes/cron/jobs.json and ~/.hermes/cron/output/{job_id}/*.md. See references/cron-history-web-viewer.md for the cron data model, schedule-dict pitfall, and the user's deployed /cron-history/ dashboard.
Cron Jobs
hermes cron list List jobs (--all for disabled)
hermes cron create SCHED Create: '30m', 'every 2h', '0 9 *'
hermes cron edit ID Edit schedule, prompt, delivery
hermes cron pause/resume ID Control job state
hermes cron run ID Trigger on next tick
hermes cron remove ID Delete a job
hermes cron status Scheduler status
For bounded autonomous lab/orchestrator cron jobs that use file-based state, subagent lanes, artifact publishing, and status transitions (active โ complete/blocked/inactive), see references/autonomous-agent-lab-cron-cycle.md. A reusable verification script template lives at scripts/verify-completion-template.py.
For a worked example of evolving an autonomous lab into a config-driven, themeable, Docker-ready installable product, see references/autonomous-lab-product-architecture.md. For CI, integration testing, pluggable adapter architecture, bounded cycle orchestration, and post-productization patterns, see references/product-maturity-patterns.md.
For the final completion verification checklist โ the explicit audit pattern to run before marking status: complete on an installable-solution mission, see references/autonomous-lab-completion-verification.md.
For the reactivation protocol when a completed lab receives new P0 feedback or the user contradicts a completion claim, see references/autonomous-lab-reactivation-protocol.md.
For the config/CHANGELOG version drift pitfall that occurs when autonomous labs evolve over many cycles, see references/autonomous-lab-version-drift.md.
For adding historical trend tracking (SQLite-backed agent status transitions + vanilla JS SVG sparklines) to an autonomous lab dashboard, see references/history-tracking-sparkline-pattern.md.
For reusable dashboard UX patterns (onboarding tours, data freshness badges, keyboard shortcuts, progressive disclosure inspectors, cross-linking between views), see references/dashboard-ux-patterns.md.
For the aggressive human-first inspector refinement โ when users report that details are hard to understand and the fix is to strip technical labels from the default view โ see references/progressive-disclosure-human-first.md.
For programmatic verification of CSS custom-property theme systems โ catching scoping bugs, confirming theme distinctness, and validating JS switching logic โ see references/theme-system-verification.md.
For Son's Discord-first autonomous experiments where a channel hosts a repeated multi-agent loop, use the Autonomous Discord Agent Lab pattern: create file-based durable state, a paused cron orchestrator delivered to discord:<channel_id>, then activate it from a user mission trigger. See references/autonomous-discord-agent-lab.md.
Webhooks
hermes webhook subscribe N Create route at /webhooks/<name>
hermes webhook list List subscriptions
hermes webhook remove NAME Remove a subscription
hermes webhook test NAME Send a test POST
Profiles
hermes profile list List all profiles
hermes profile create NAME Create (--clone, --clone-all, --clone-from)
hermes profile use NAME Set sticky default
hermes profile delete NAME Delete a profile
hermes profile show NAME Show details
hermes profile alias NAME Manage wrapper scripts
hermes profile rename A B Rename a profile
hermes profile export NAME Export to tar.gz
hermes profile import FILE Import from archive
Credential Pools
hermes auth add Interactive credential wizard
hermes auth list [PROVIDER] List pooled credentials
hermes auth remove P INDEX Remove by provider + index
hermes auth reset PROVIDER Clear exhaustion status
Other
hermes insights [--days N] Usage analytics
hermes update Update to latest version
hermes pairing list/approve/revoke DM authorization
hermes plugins list/install/remove Plugin management
hermes honcho setup/status Honcho memory integration (requires honcho plugin)
hermes memory setup/status/off Memory provider config
hermes completion bash|zsh Shell completions
hermes acp ACP server (IDE integration)
hermes claw migrate Migrate from OpenClaw
hermes uninstall Uninstall Hermes
---
Slash Commands (In-Session)
Type these during an interactive chat session. New commands land fairly
often; if something below looks stale, run /help in-session for the
authoritative list or see the [live slash commands reference](https://hermes-agent.nousresearch.com/docs/reference/slash-commands).
The registry of record is hermes_cli/commands.py โ every consumer
(autocomplete, Telegram menu, Slack mapping, /help) derives from it.
Session Control
/new (/reset) Fresh session
/clear Clear screen + new session (CLI)
/retry Resend last message
/undo Remove last exchange
/title [name] Name the session
/compress Manually compress context
/stop Kill background processes
/rollback [N] Restore filesystem checkpoint
/snapshot [sub] Create or restore state snapshots of Hermes config/state (CLI)
/background <prompt> Run prompt in background
/queue <prompt> Queue for next turn
/steer <prompt> Inject a message after the next tool call without interrupting
/agents (/tasks) Show active agents and running tasks
/resume [name] Resume a named session
/goal [text|sub] Set a standing goal Hermes works on across turns until achieved
(subcommands: status, pause, resume, clear)
/redraw Force a full UI repaint (CLI)
Configuration
/config Show config (CLI)
/model [name] Show or change model
/personality [name] Set personality
/reasoning [level] Set reasoning (none|minimal|low|medium|high|xhigh|show|hide)
/verbose Cycle: off โ new โ all โ verbose
/voice [on|off|tts] Voice mode
/yolo Toggle approval bypass
/busy [sub] Control what Enter does while Hermes is working (CLI)
(subcommands: queue, steer, interrupt, status)
/indicator [style] Pick the TUI busy-indicator style (CLI)
(styles: kaomoji, emoji, unicode, ascii)
/footer [on|off] Toggle gateway runtime-metadata footer on final replies
/skin [name] Change theme (CLI)
/statusbar Toggle status bar (CLI)
Tools & Skills
/tools Manage tools (CLI)
/toolsets List toolsets (CLI)
/skills Search/install skills (CLI)
/skill <name> Load a skill into session
/reload-skills Re-scan ~/.hermes/skills/ for added/removed skills
/reload Reload .env variables into the running session (CLI)
/reload-mcp Reload MCP servers
/cron Manage cron jobs (CLI)
/curator [sub] Background skill maintenance (status, run, pin, archive, โฆ)
/kanban [sub] Multi-profile collaboration board (tasks, links, comments)
/plugins List plugins (CLI)
Gateway
/approve Approve a pending command (gateway)
/deny Deny a pending command (gateway)
/restart Restart gateway (gateway)
/sethome Set current chat as home channel (gateway)
/update Update Hermes to latest (gateway)
/topic [sub] Enable or inspect Telegram DM topic sessions (gateway)
/platforms (/gateway) Show platform connection status (gateway)
Utility
/branch (/fork) Branch the current session
/fast Toggle priority/fast processing
/browser Open CDP browser connection
/history Show conversation history (CLI)
/save Save conversation to file (CLI)
/copy [N] Copy the last assistant response to clipboard (CLI)
/paste Attach clipboard image (CLI)
/image Attach local image file (CLI)
Info
/help Show commands
/commands [page] Browse all commands (gateway)
/usage Token usage
/insights [days] Usage analytics
/gquota Show Google Gemini Code Assist quota usage (CLI)
/status Session info (gateway)
/profile Active profile info
/debug Upload debug report (system info + logs) and get shareable links
Exit
/quit (/exit, /q) Exit CLI
---
Key Paths & Config
~/.hermes/config.yaml Main configuration
~/.hermes/.env API keys and secrets
$HERMES_HOME/skills/ Installed skills
~/.hermes/sessions/ Session transcripts
~/.hermes/logs/ Gateway and error logs
~/.hermes/auth.json OAuth tokens and credential pools
~/.hermes/hermes-agent/ Source code (if git-installed)
Profiles use ~/.hermes/profiles/<name>/ with the same layout.
Config Sections
Edit with hermes config edit or hermes config set section.key value.
| Section | Key options |
|---------|-------------|
| model | default, provider, base_url, api_key, context_length |
| agent | max_turns (90), tool_use_enforcement |
| terminal | backend (local/docker/ssh/modal), cwd, timeout (180) |
| compression | enabled, threshold (0.50), target_ratio (0.20) |
| display | skin, tool_progress, show_reasoning, show_cost |
| stt | enabled, provider (local/groq/openai/mistral) |
| tts | provider (edge/elevenlabs/openai/minimax/mistral/neutts) |
| memory | memory_enabled, user_profile_enabled, provider |
| security | tirith_enabled, website_blocklist |
| delegation | model, provider, base_url, api_key, max_iterations (50), reasoning_effort |
| checkpoints | enabled, max_snapshots (50) |
| fallback_model | provider, model, base_url, key_env |
Fallback Providers
Hermes can automatically fail over to a backup provider:model when the primary is unavailable. This is turn-scoped โ each new user message starts with the primary restored; fallback only activates mid-turn when the primary fails.
Configuration ( ~/.hermes/config.yaml):
fallback_model:
provider: opencode-go
model: kimi-k2.6
Or use the interactive manager:
hermes fallback add # interactive picker
hermes fallback list # show fallback chain
hermes fallback remove # remove by index
Legacy note: fallback_model (singular) is the legacy single-fallback key. fallback_providers (list) supports multiple ordered fallbacks. When both exist, fallback_providers takes priority.
Trigger conditions (after exhausting retries where applicable):
- Rate limits (HTTP 429)
- Server errors (HTTP 500, 502, 503)
- Auth failures (HTTP 401, 403) โ immediately
- Not found (HTTP 404) โ immediately
- Invalid / empty responses repeatedly
Supported providers include all standard providers (OpenRouter, Anthropic, OpenCode Go/ Zen, Kimi, etc.) plus custom endpoints with base_url + key_env. Full provider docs: https://hermes-agent.nousresearch.com/docs/integrations/providers
Limitations:
- Subagent delegation does not inherit fallback config
- Cron jobs do not use fallback (use per-job provider/model overrides)
- Auxiliary tasks (vision, compression, etc.) use their own
auxiliary.* provider chain
For a deep-dive with worked examples and model lists, see references/fallback-providers.md.
Full config reference: https://hermes-agent.nousresearch.com/docs/user-guide/configuration
Providers
20+ providers supported. Set via hermes model or hermes setup.
| Provider | Auth | Key env var |
|----------|------|-------------|
| OpenRouter | API key | OPENROUTER_API_KEY |
| Anthropic | API key | ANTHROPIC_API_KEY |
| Nous Portal | OAuth | hermes auth |
| OpenAI Codex | OAuth | hermes auth |
| GitHub Copilot | Token | COPILOT_GITHUB_TOKEN |
| Google Gemini | API key | GOOGLE_API_KEY or GEMINI_API_KEY |
| DeepSeek | API key | DEEPSEEK_API_KEY |
| xAI / Grok | API key | XAI_API_KEY |
| Hugging Face | Token | HF_TOKEN |
| Z.AI / GLM | API key | GLM_API_KEY |
| MiniMax | API key | MINIMAX_API_KEY |
| MiniMax CN | API key | MINIMAX_CN_API_KEY |
| Kimi / Moonshot | API key | KIMI_API_KEY |
| Alibaba / DashScope | API key | DASHSCOPE_API_KEY |
| Xiaomi MiMo | API key | XIAOMI_API_KEY |
| Kilo Code | API key | KILOCODE_API_KEY |
| AI Gateway (Vercel) | API key | AI_GATEWAY_API_KEY |
| OpenCode Zen | API key | OPENCODE_ZEN_API_KEY |
| OpenCode Go | API key | OPENCODE_GO_API_KEY |
| Qwen OAuth | OAuth | hermes auth add qwen-oauth |
| Custom endpoint | Config | model.base_url + model.api_key in config.yaml |
| GitHub Copilot ACP | External | COPILOT_CLI_PATH or Copilot CLI |
Full provider docs: https://hermes-agent.nousresearch.com/docs/integrations/providers
Toolsets
Enable/disable via hermes tools (interactive) or hermes tools enable/disable NAME.
| Toolset | What it provides |
|---------|-----------------|
| web | Web search and content extraction |
| search | Web search only (subset of web) |
| browser | Browser automation (Browserbase, Camofox, or local Chromium) |
| terminal | Shell commands and process management |
| file | File read/write/search/patch |
| code_execution | Sandboxed Python execution |
| vision | Image analysis |
| image_gen | AI image generation |
| video | Video analysis and generation |
| tts | Text-to-speech |
| skills | Skill browsing and management |
| memory | Persistent cross-session memory |
| session_search | Search past conversations |
| delegation | Subagent task delegation |
| cronjob | Scheduled task management |
| clarify | Ask user clarifying questions |
| messaging | Cross-platform message sending |
| todo | In-session task planning and tracking |
| kanban | Multi-agent work-queue tools (gated to workers) |
| debugging | Extra introspection/debug tools (off by default) |
| safe | Minimal, low-risk toolset for locked-down sessions |
| spotify | Spotify playback and playlist control |
| homeassistant | Smart home control (off by default) |
| discord | Discord integration tools |
| discord_admin | Discord admin/moderation tools |
| feishu_doc | Feishu (Lark) document tools |
| feishu_drive | Feishu (Lark) drive tools |
| yuanbao | Yuanbao integration tools |
| rl | Reinforcement learning tools (off by default) |
| moa | Mixture of Agents (off by default) |
Full enumeration lives in toolsets.py as the TOOLSETS dict; _HERMES_CORE_TOOLS is the default bundle most platforms inherit from.
Tool changes take effect on /reset (new session). They do NOT apply mid-conversation to preserve prompt caching.
---
Security & Privacy Toggles
Common "why is Hermes doing X to my output / tool calls / commands?" toggles โ and the exact commands to change them. Most of these need a fresh session (/reset in chat, or start a new hermes invocation) because they're read once at startup.
Secret redaction in tool output
Secret redaction is off by default โ tool output (terminal stdout, read_file, web content, subagent summaries, etc.) passes through unmodified. If the user wants Hermes to auto-mask strings that look like API keys, tokens, and secrets before they enter the conversation context and logs:
hermes config set security.redact_secrets true # enable globally
Restart required. security.redact_secrets is snapshotted at import time โ toggling it mid-session (e.g. via export HERMES_REDACT_SECRETS=true from a tool call) will NOT take effect for the running process. Tell the user to run hermes config set security.redact_secrets true in a terminal, then start a new session. This is deliberate โ it prevents an LLM from flipping the toggle on itself mid-task.
Disable again with:
hermes config set security.redact_secrets false
PII redaction in gateway messages
Separate from secret redaction. When enabled, the gateway hashes user IDs and strips phone numbers from the session context before it reaches the model:
hermes config set privacy.redact_pii true # enable
hermes config set privacy.redact_pii false # disable (default)
Command approval prompts
By default (approvals.mode: manual), Hermes prompts the user before running shell commands flagged as destructive (rm -rf, git reset --hard, etc.). The modes are:
manual โ always prompt (default)
smart โ use an auxiliary LLM to auto-approve low-risk commands, prompt on high-risk
off โ skip all approval prompts (equivalent to --yolo)
hermes config set approvals.mode smart # recommended middle ground
hermes config set approvals.mode off # bypass everything (not recommended)
Per-invocation bypass without changing config:
hermes --yolo โฆ
export HERMES_YOLO_MODE=1
Note: YOLO / approvals.mode: off does NOT turn off secret redaction. They are independent.
Shell hooks allowlist
Some shell-hook integrations require explicit allowlisting before they fire. Managed via ~/.hermes/shell-hooks-allowlist.json โ prompted interactively the first time a hook wants to run.
Disabling the web/browser/image-gen tools
To keep the model away from network or media tools entirely, open hermes tools and toggle per-platform. Takes effect on next session (/reset). See the Tools & Skills section above.
---
Voice & Transcription
STT (Voice โ Text)
Voice messages from messaging platforms are auto-transcribed.
Provider priority (auto-detected):
1. Local faster-whisper โ free, no API key: pip install faster-whisper
2. Groq Whisper โ free tier: set GROQ_API_KEY
3. OpenAI Whisper โ paid: set VOICE_TOOLS_OPENAI_KEY
4. Mistral Voxtral โ set MISTRAL_API_KEY
Config:
stt:
enabled: true
provider: local # local, groq, openai, mistral
local:
model: base # tiny, base, small, medium, large-v3
TTS (Text โ Voice)
| Provider | Env var | Free? |
|----------|---------|-------|
| Edge TTS | None | Yes (default) |
| ElevenLabs | ELEVENLABS_API_KEY | Free tier |
| OpenAI | VOICE_TOOLS_OPENAI_KEY | Paid |
| MiniMax | MINIMAX_API_KEY | Paid |
| Mistral (Voxtral) | MISTRAL_API_KEY | Paid |
| NeuTTS (local) | None (pip install neutts[all] + espeak-ng) | Free |
Voice commands: /voice on (voice-to-voice), /voice tts (always voice), /voice off.
---
Spawning Additional Hermes Instances
Run additional Hermes processes as fully independent subprocesses โ separate sessions, tools, and environments.
When to Use This vs delegate_task
| | delegate_task | Spawning hermes process |
|-|-----------------|--------------------------|
| Isolation | Separate conversation, shared process | Fully independent process |
| Duration | Minutes (bounded by parent loop) | Hours/days |
| Tool access | Subset of parent's tools | Full tool access |
| Interactive | No | Yes (PTY mode) |
| Use case | Quick parallel subtasks | Long autonomous missions |
One-Shot Mode
terminal(command="hermes chat -q 'Research GRPO papers and write summary to ~/research/grpo.md'", timeout=300)
Background for long tasks:
terminal(command="hermes chat -q 'Set up CI/CD for ~/myapp'", background=true)
Interactive PTY Mode (via tmux)
Hermes uses prompt_toolkit, which requires a real terminal. Use tmux for interactive spawning:
Start
terminal(command="tmux new-session -d -s agent1 -x 120 -y 40 'hermes'", timeout=10)
Wait for startup, then send a message
terminal(command="sleep 8 && tmux send-keys -t agent1 'Build a FastAPI auth service' Enter", timeout=15)
Read output
terminal(command="sleep 20 && tmux capture-pane -t agent1 -p", timeout=5)
Send follow-up
terminal(command="tmux send-keys -t agent1 'Add rate limiting middleware' Enter", timeout=5)
Exit
terminal(command="tmux send-keys -t agent1 '/exit' Enter && sleep 2 && tmux kill-session -t agent1", timeout=10)
Multi-Agent Coordination
Agent A: backend
terminal(command="tmux new-session -d -s backend -x 120 -y 40 'hermes -w'", timeout=10)
terminal(command="sleep 8 && tmux send-keys -t backend 'Build REST API for user management' Enter", timeout=15)
Agent B: frontend
terminal(command="tmux new-session -d -s frontend -x 120 -y 40 'hermes -w'", timeout=10)
terminal(command="sleep 8 && tmux send-keys -t frontend 'Build React dashboard for user management' Enter", timeout=15)
Check progress, relay context between them
terminal(command="tmux capture-pane -t backend -p | tail -30", timeout=5)
terminal(command="tmux send-keys -t frontend 'Here is the API schema from the backend agent: ...' Enter", timeout=5)
Session Resume
Resume most recent session
terminal(command="tmux new-session -d -s resumed 'hermes --continue'", timeout=10)
Resume specific session
terminal(command="tmux new-session -d -s resumed 'hermes --resume 20260225_143052_a1b2c3'", timeout=10)
Tips
- Prefer
delegate_task for quick subtasks โ less overhead than spawning a full process
- Use
-w (worktree mode) when spawning agents that edit code โ prevents git conflicts
- Set timeouts for one-shot mode โ complex tasks can take 5-10 minutes
- Use
hermes chat -q for fire-and-forget โ no PTY needed
- Use tmux for interactive sessions โ raw PTY mode has
\r vs \n issues with prompt_toolkit
- For scheduled tasks, use the
cronjob tool instead of spawning โ handles delivery and retry
---
Durable & Background Systems
Four systems run alongside the main conversation loop. Quick reference
here; full developer notes live in AGENTS.md, user-facing docs under
website/docs/user-guide/features/.
Delegation (delegate_task)
Synchronous subagent spawn โ the parent waits for the child's summary
before continuing its own loop. Isolated context + terminal session.
- Single:
delegate_task(goal, context, toolsets).
- Batch:
delegate_task(tasks=[{goal, ...}, ...]) runs children in
parallel, capped by delegation.max_concurrent_children (default 3).
- Roles:
leaf (default; cannot re-delegate) vs orchestrator
(can spawn its own workers, bounded by delegation.max_spawn_depth).
- Not durable. If the parent is interrupted, the child is
cancelled. For work that must outlive the turn, use cronjob or
terminal(background=True, notify_on_complete=True).
Config: delegation.* in config.yaml.
Tuning max_concurrent_children
Default is 3. Rule of thumb for raising it:
- Light tasks (web search, file grep): up to
6-8
- Medium tasks (code execution, browser):
4-5
- Heavy tasks (builds, large data):
2-3
- Actual bottleneck is usually the API rate limit, not local CPU/RAM. On a 10-core M4 with 16GB RAM, CPU is rarely the constraint.
- Formula: start at
5, raise only if profiling shows idle time between API responses.
Cron (scheduled jobs)
Durable scheduler โ cron/jobs.py + cron/scheduler.py. Drive it via
the cronjob tool, the hermes cron CLI (list, add, edit,
pause, resume, run, remove), or the /cron slash command.
- Schedules: duration (
"30m", "2h"), "every" phrase
( "every monday 9am"), 5-field cron ( "0 9 *"), or ISO timestamp.
- Per-job knobs:
skills, model/provider override, script
(pre-run data collection; no_agent=True makes the script the whole
job), context_from (chain job A's output into job B), workdir
(run in a specific dir with its AGENTS.md / CLAUDE.md loaded),
multi-platform delivery.
- Invariants: 3-minute hard interrupt per run,
.tick.lock file
prevents duplicate ticks across processes, cron sessions pass
skip_memory=True by default, and cron deliveries are framed with a
header/footer instead of being mirrored into the target gateway
session (keeps role alternation intact).
User docs: https://hermes-agent.nousresearch.com/docs/user-guide/features/cron
Curator (skill lifecycle)
Background maintenance for agent-created skills. Tracks usage, marks
idle skills stale, archives stale ones, keeps a pre-run tar.gz backup
so nothing is lost.
- CLI:
hermes curator <verb> โ status, run, pause, resume,
pin, unpin, archive, restore, prune, backup, rollback.
- Slash:
/curator <subcommand> mirrors the CLI.
- Scope: only touches skills with
created_by: "agent" provenance.
Bundled + hub-installed skills are off-limits. Never deletes โ
max destructive action is archive. Pinned skills are exempt from
every auto-transition and every LLM review pass.
- Telemetry: sidecar at
~/.hermes/skills/.usage.json holds
per-skill use_count, view_count, patch_count,
last_activity_at, state, pinned.
Config: curator.* (enabled, interval_hours, min_idle_hours,
stale_after_days, archive_after_days, backup.*).
User docs: https://hermes-agent.nousresearch.com/docs/user-guide/features/curator
Dreaming (periodic memory/skill consolidation)
For Anthropic-style "dreaming" workflows, combine cron + session_search + memory + skills + curator into a scheduled review loop. Start with a weekly, proposal-only report that audits recent sessions, repeated user corrections, memory conflicts, skill patch candidates, and cron/automation improvements. Do not automatically delete/replace memory or patch/archive skills unless the user explicitly approves the proposed changes. See references/weekly-dreaming-routine.md for the recommended prompt, report format, safety policy, and cron creation pattern.
Kanban (multi-agent work queue)
Durable SQLite board for multi-profile / multi-worker collaboration.
Users drive it via hermes kanban <verb>; dispatcher-spawned workers
see a focused kanban_* toolset gated by HERMES_KANBAN_TASK so the
schema footprint is zero outside worker processes.
- CLI verbs (common):
init, create, list (alias ls),
show, assign, link, unlink, comment, complete, block,
unblock, archive, tail. Less common: watch, stats, runs,
log, dispatch, daemon, gc.
- Worker toolset:
kanban_show, kanban_complete, kanban_block,
kanban_heartbeat, kanban_comment, kanban_create, kanban_link.
- Dispatcher runs inside the gateway by default
( kanban.dispatch_in_gateway: true) โ reclaims stale claims,
promotes ready tasks, atomically claims, spawns assigned profiles.
Auto-blocks a task after ~5 consecutive spawn failures.
- Isolation: board is the hard boundary (workers get
HERMES_KANBAN_BOARD pinned in env); tenant is a soft namespace
within a board for workspace-path + memory-key isolation.
User docs: https://hermes-agent.nousresearch.com/docs/user-guide/features/kanban
Log Relay (Hermes โ Discord)
A background Python script that tails ~/.hermes/logs/*.log and batches lines to a Discord channel. Includes session-ID extraction, rate-limit handling, and auto-restart via launchd/systemd. Useful for remote monitoring and audit trails.
- Reference:
references/discord-log-relay.md โ full setup, tuning, macOS/Linux service install, pitfalls.
- Template:
templates/discord-log-relay.py โ copy, set CHANNEL_ID, and deploy.
- Discord operations:
references/discord-operating-planes.md โ channel-purpose routing, periodic-summary vs Dreaming report formats, and safety/cost notes for Discord-first Hermes deployments.
Key pitfall: ask the user about batch frequency upfront rather than defaulting to real-time streaming. Most users prefer 10-minute or hourly batches. High-volume raw logs should be batched, summarized, or stored out-of-band; avoid Discord message storms during error loops.
Weekly Dreaming / Memory Curation
For long-running Hermes deployments, users may want an Anthropic-style "Dreaming" loop: a scheduled review that consolidates experience, proposes memory/skill/cron changes, and identifies what to keep, weaken, archive, or delete. Hermes has the building blocks (sessions, session_search, memory, skills, curator, cron), but the safe default is proposal mode:
1. Inspect recent usage and sessions.
2. Extract repeated success patterns, failure patterns, and user corrections.
3. Propose memory updates/removals without applying them silently.
4. Propose skill patches/archive candidates and cron/reporting improvements.
5. End with explicit approval checkboxes.
Do not silently rewrite or delete memory/skills from a Dreaming report unless the user explicitly authorized automatic application. See references/discord-operating-planes.md for a report template and routing heuristics.
---
Windows-Specific Quirks
Hermes runs natively on Windows (PowerShell, cmd, Windows Terminal, git-bash
mintty, VS Code integrated terminal). Most of it just works, but a handful
of differences between Win32 and POSIX have bitten us โ document new ones
here as you hit them so the next person (or the next session) doesn't
rediscover them from scratch.
Input / Keybindings
Alt+Enter doesn't insert a newline. Windows Terminal intercepts Alt+Enter
at the terminal layer to toggle fullscreen โ the keystroke never reaches
prompt_toolkit. Use Ctrl+Enter instead. Windows Terminal delivers
Ctrl+Enter as LF ( c-j), distinct from plain Enter ( c-m / CR), and the
CLI binds c-j to newline insertion on win32 only (see
_bind_prompt_submit_keys + the Windows-only c-j binding in cli.py).
Side effect: the raw Ctrl+J keystroke also inserts a newline on Windows โ
unavoidable, because Windows Terminal collapses Ctrl+Enter and Ctrl+J to
the same keycode at the Win32 console API layer. No conflicting binding
existed for Ctrl+J on Windows, so this is a harmless side effect.
mintty / git-bash behaves the same (fullscreen on Alt+Enter) unless you
disable Alt+Fn shortcuts in Options โ Keys. Easier to just use Ctrl+Enter.
Diagnosing keybindings. Run python scripts/keystroke_diagnostic.py
(repo root) to see exactly how prompt_toolkit identifies each keystroke
in the current terminal. Answers questions like "does Shift+Enter come
through as a distinct key?" (almost never โ most terminals collapse it
to plain Enter) or "what byte sequence is my terminal sending for
Ctrl+Enter?" This is how the Ctrl+Enter = c-j fact was established.
Config / Files
HTTP 400 "No models provided" on first run. config.yaml was saved
with a UTF-8 BOM (common when Windows apps write it). Re-save as UTF-8
without BOM. hermes config edit writes without BOM; manual edits in
Notepad are the usual culprit.
execute_code / Sandbox
WinError 10106 ("The requested service provider could not be loaded
or initialized") from the sandbox child process โ it can't create an
AF_INET socket, so the loopback-TCP RPC fallback fails before
connect(). Root cause is usually not a broken Winsock LSP; it's
Hermes's own env scrubber dropping SYSTEMROOT / WINDIR / COMSPEC
from the child env. Python's socket module needs SYSTEMROOT to locate
mswsock.dll. Fixed via the _WINDOWS_ESSENTIAL_ENV_VARS allowlist in
tools/code_execution_tool.py. If you still hit it, echo os.environ
inside an execute_code block to confirm SYSTEMROOT is set. Full
diagnostic recipe in references/execute-code-sandbox-env-windows.md.
Testing / Contributing
scripts/run_tests.sh doesn't work as-is on Windows โ it looks for
POSIX venv layouts ( .venv/bin/activate). The Hermes-installed venv at
venv/Scripts/ has no pip or pytest either (stripped for install size).
Workaround: install pytest + pytest-xdist + pyyaml into a system Python
3.11 user site, then invoke pytest directly with PYTHONPATH set:
"/c/Program Files/Python311/python" -m pip install --user pytest pytest-xdist pyyaml
export PYTHONPATH="$(pwd)"
"/c/Program Files/Python311/python" -m pytest tests/foo/test_bar.py -v --tb=short -n 0
Use -n 0, not -n 4 โ pyproject.toml's default addopts already
includes -n, and the wrapper's CI-parity guarantees don't apply off POSIX.
POSIX-only tests need skip guards. Common markers already in the codebase:
- Symlinks โ elevated privileges on Windows
0o600 file modes โ POSIX mode bits not enforced on NTFS by default
signal.SIGALRM โ Unix-only (see tests/conftest.py::_enforce_test_timeout)
- Winsock / Windows-specific regressions โ
@pytest.mark.skipif(sys.platform != "win32", ...)
Use the existing skip-pattern style (sys.platform == "win32" or
sys.platform.startswith("win")) to stay consistent with the rest of the
suite.
Path / Filesystem
Line endings. Git may warn LF will be replaced by CRLF the next time
Git touches it. Cosmetic โ the repo's .gitattributes normalizes. Don't
let editors auto-convert committed POSIX-newline files to CRLF.
Forward slashes work almost everywhere. C:/Users/... is accepted by
every Hermes tool and most Windows APIs. Prefer forward slashes in code
and logs โ avoids shell-escaping backslashes in bash.
---
Troubleshooting
Voice not working
1. Check stt.enabled: true in config.yaml
2. Verify provider: pip install faster-whisper or set API key
3. In gateway: /restart. In CLI: exit and relaunch.
Tool not available
1. hermes tools โ check if toolset is enabled for your platform
2. Some tools need env vars (check .env)
3. /reset after enabling tools
Model/provider issues
1. hermes doctor โ check config and dependencies
2. hermes auth add <provider> โ re-authenticate OAuth providers (use --type oauth)
3. Check .env has the right API key
4. Copilot 403: gh auth login tokens do NOT work for Copilot API. You must use the Copilot-specific OAuth device code flow via hermes model โ GitHub Copilot.
Changes not taking effect
- Tools/skills:
/reset starts a new session with updated toolset
- Config changes: In gateway:
/restart. In CLI: exit and relaunch.
- Code changes: Restart the CLI or gateway process
Deployed web dashboard shows stale CSS or theme changes
- Browser cache: Add
?v=N cache-busting query strings to CSS/JS/theme links in HTML.
- Service Worker cache: Bump
CACHE_NAME in sw.js to invalidate old shell caches.
- Data freshness: Use
fetch(url, {cache:'no-store'}) for live JSON feeds.
- See
references/static-site-cache-invalidation.md for the full diagnostic recipe.
Dashboard inspector feels too technical
- The default inspector view should contain only plain-language sentences: headline, "what they're doing now", "why it matters", and a silent visual progress bar (no text label).
- Move all technical fields (source IDs, confidence scores, progress labels, status slugs, badges) behind a "Show technical details" toggle.
- If users say "details are hard to understand," the fix is to remove more fields from the default view, not to add explanations. Explanations of technical fields are still technical.
- See
references/progressive-disclosure-human-first.md for the aggressive simplification pattern.
Skills not showing
1. hermes skills list โ verify installed
2. hermes skills config โ check platform enablement
3. Load explicitly: /skill name or hermes -s name
Gateway issues
Check logs first:
grep -i "failed to send\|error" ~/.hermes/logs/gateway.log | tail -20
Common gateway problems:
- Gateway dies on SSH logout: Enable linger:
sudo loginctl enable-linger $USER
- Gateway dies on WSL2 close: WSL2 requires
systemd=true in /etc/wsl.conf for systemd services to work. Without it, gateway falls back to nohup (dies when session closes).
- Gateway crash loop: Reset the failed state:
systemctl --user reset-failed hermes-gateway
- macOS: bot shows offline after idle time: The gateway runs as a user agent (
LimitLoadToSessionType=Aqua), so macOS suspends it when the system sleeps. The platform websocket drops and the bot appears offline until the network returns. Fix: keep the Mac awake (System Settings -> Energy -> Prevent automatic sleeping, or caffeinate -d -i -s -u &). Low Power Mode makes this worse, not better. See references/macos-gateway-sleep-disconnect.md for the full diagnostic recipe.
Platform-specific issues
- Discord bot silent: Must enable Message Content Intent in Bot โ Privileged Gateway Intents. See full Discord setup reference:
references/discord-gateway-setup.md.
- Slack bot only works in DMs: Must subscribe to
message.channels event. Without it, the bot ignores public channels.
- Windows-specific issues (
Alt+Enter newline, WinError 10106, UTF-8 BOM config, test suite, line endings): see the dedicated Windows-Specific Quirks section above.
Auxiliary models not working
If auxiliary tasks (vision, compression, session_search) fail silently, the auto provider can't find a backend. Either set OPENROUTER_API_KEY or GOOGLE_API_KEY, or explicitly configure each auxiliary task's provider:
hermes config set auxiliary.vision.provider <your_provider>
hermes config set auxiliary.vision.model <model_name>
Full system auth provisioning
For a one-shot workflow to maximize available credentials โ installing gh, generating SSH keys, configuring git, enabling all Hermes toolsets, and auditing current auth state โ see references/system-auth-setup.md.
Editing large files with patch
When a file is read with read_file(offset=...) (pagination), the tool warns that the view is partial. If you attempt patch without re-reading the full file first, you will likely hit non-unique match errors or corrupt the file. Fix: always call read_file without offset to load the whole file before patching. For append-only updates (e.g., adding a cycle log entry to state.md), do not use terminal(command="cat >> file << 'EOF'...EOF") โ the terminal tool on macOS/Linux misinterprets heredoc << as backgrounding and fails. Instead, write a short Python script via write_file and execute it with terminal(command="python3 /tmp/script.py"). See references/terminal-heredoc-workaround.md for the full pattern.
---
Windows-Specific Quirks
| Looking for... | Location |
|----------------|----------|
| Config options | hermes config edit or [Configuration docs](https://hermes-agent.nousresearch.com/docs/user-guide/configuration) |
| Available tools | hermes tools list or [Tools reference](https://hermes-agent.nousresearch.com/docs/reference/tools-reference) |
| Slash commands | /help in session or [Slash commands reference](https://hermes-agent.nousresearch.com/docs/reference/slash-commands) |
| Skills catalog | hermes skills browse or [Skills catalog](https://hermes-agent.nousresearch.com/docs/reference/skills-catalog) |
| Provider setup | hermes model or [Providers guide](https://hermes-agent.nousresearch.com/docs/integrations/providers) |
| Platform setup | hermes gateway setup or [Messaging docs](https://hermes-agent.nousresearch.com/docs/user-guide/messaging/) |
| MCP servers | hermes mcp list or [MCP guide](https://hermes-agent.nousresearch.com/docs/user-guide/features/mcp) |
| Profiles | hermes profile list or [Profiles docs](https://hermes-agent.nousresearch.com/docs/user-guide/profiles) |
| Cron jobs | hermes cron list or [Cron docs](https://hermes-agent.nousresearch.com/docs/user-guide/features/cron) |
| Memory | hermes memory status or [Memory docs](https://hermes-agent.nousresearch.com/docs/user-guide/features/memory) |
| Env variables | hermes config env-path or [Env vars reference](https://hermes-agent.nousresearch.com/docs/reference/environment-variables) |
| CLI commands | hermes --help or [CLI reference](https://hermes-agent.nousresearch.com/docs/reference/cli-commands) |
| Gateway logs | ~/.hermes/logs/gateway.log |
| Session files | ~/.hermes/sessions/ or hermes sessions browse |
| Source code | ~/.hermes/hermes-agent/ |
---
Contributor Quick Reference
For occasional contributors and PR authors. Full developer docs: https://hermes-agent.nousresearch.com/docs/developer-guide/
Project Layout
hermes-agent/
โโโ run_agent.py # AIAgent โ core conversation loop
โโโ model_tools.py # Tool discovery and dispatch
โโโ toolsets.py # Toolset definitions
โโโ cli.py # Interactive CLI (HermesCLI)
โโโ hermes_state.py # SQLite session store
โโโ agent/ # Prompt builder, context compression, memory, model routing, credential pooling, skill dispatch
โโโ hermes_cli/ # CLI subcommands, config, setup, commands
โ โโโ commands.py # Slash command registry (CommandDef)
โ โโโ config.py # DEFAULT_CONFIG, env var definitions
โ โโโ main.py # CLI entry point and argparse
โโโ tools/ # One file per tool
โ โโโ registry.py # Central tool registry
โโโ gateway/ # Messaging gateway
โ โโโ platforms/ # Platform adapters (telegram, discord, etc.)
โโโ cron/ # Job scheduler
โโโ tests/ # ~3000 pytest tests
โโโ website/ # Docusaurus docs site
Config: ~/.hermes/config.yaml (settings), ~/.hermes/.env (API keys).
Adding a Tool (3 files)
1. Create tools/your_tool.py:
import json, os
from tools.registry import registry
def check_requirements() -> bool:
return bool(os.getenv("EXAMPLE_API_KEY"))
def example_tool(param: str, task_id: str = None) -> str:
return json.dumps({"success": True, "data": "..."})
registry.register(
name="example_tool",
toolset="example",
schema={"name": "example_tool", "description": "...", "parameters": {...}},
handler=lambda args, **kw: example_tool(
param=args.get("param", ""), task_id=kw.get("task_id")),
check_fn=check_requirements,
requires_env=["EXAMPLE_API_KEY"],
)
2. Add to toolsets.py โ _HERMES_CORE_TOOLS list.
Auto-discovery: any tools/*.py file with a top-level registry.register() call is imported automatically โ no manual list needed.
All handlers must return JSON strings. Use get_hermes_home() for paths, never hardcode ~/.hermes.
Adding a Slash Command
1. Add CommandDef to COMMAND_REGISTRY in hermes_cli/commands.py
2. Add handler in cli.py โ process_command()
3. (Optional) Add gateway handler in gateway/run.py
All consumers (help text, autocomplete, Telegram menu, Slack mapping) derive from the central registry automatically.
Agent Loop (High Level)
run_conversation():
1. Build system prompt
2. Loop while iterations < max:
a. Call LLM (OpenAI-format messages + tool schemas)
b. If tool_calls โ dispatch each via handle_function_call() โ append results โ continue
c. If text response โ return
3. Context compression triggers automatically near token limit
Testing
python -m pytest tests/ -o 'addopts=' -q # Full suite
python -m pytest tests/tools/ -q # Specific area
- Tests auto-redirect
HERMES_HOME to temp dirs โ never touch real ~/.hermes/
- Run full suite before pushing any change
- Use
-o 'addopts=' to clear any baked-in pytest flags
Windows contributors: scripts/run_tests.sh currently looks for POSIX venvs ( .venv/bin/activate / venv/bin/activate) and will error out on Windows where the layout is venv/Scripts/activate + python.exe. The Hermes-installed venv at venv/Scripts/ also has no pip or pytest โ it's stripped for end-user install size. Workaround: install pytest + pytest-xdist + pyyaml into a system Python 3.11 user site ( /c/Program Files/Python311/python -m pip install --user pytest pytest-xdist pyyaml), then run tests directly:
export PYTHONPATH="$(pwd)"
"/c/Program Files/Python311/python" -m pytest tests/tools/test_foo.py -v --tb=short -n 0
Use -n 0 (not -n 4) because pyproject.toml's default addopts already includes -n, and the wrapper's CI-parity story doesn't apply off-POSIX.
Cross-platform test guards: tests that use POSIX-only syscalls need a skip marker. Common ones already in the codebase:
- Symlink creation โ
@pytest.mark.skipif(sys.platform == "win32", reason="Symlinks require elevated privileges on Windows") (see tests/cron/test_cron_script.py)
- POSIX file modes (0o600, etc.) โ
@pytest.mark.skipif(sys.platform.startswith("win"), reason="POSIX mode bits not enforced on Windows") (see tests/hermes_cli/test_auth_toctou_file_modes.py)
signal.SIGALRM โ Unix-only (see tests/conftest.py::_enforce_test_timeout)
- Live Winsock / Windows-specific regression tests โ
@pytest.mark.skipif(sys.platform != "win32", reason="Windows-specific regression")
Monkeypatching sys.platform is not enough when the code under test also calls platform.system() / platform.release() / platform.mac_ver(). Those functions re-read the real OS independently, so a test that sets sys.platform = "linux" on a Windows runner will still see platform.system() == "Windows" and route through the Windows branch. Patch all three together:
monkeypatch.setattr(sys, "platform", "linux")
monkeypatch.setattr(platform, "system", lambda: "Linux")
monkeypatch.setattr(platform, "release", lambda: "6.8.0-generic")
See tests/agent/test_prompt_builder.py::TestEnvironmentHints for a worked example.
Extending the system prompt's execution-environment block
Factual guidance about the host OS, user home, cwd, terminal backend, and shell (bash vs. PowerShell on Windows) is emitted from agent/prompt_builder.py::build_environment_hints(). This is also where the WSL hint and per-backend probe logic live. The convention:
- Local terminal backend โ emit host info (OS,
$HOME, cwd) + Windows-specific notes (hostname โ username, terminal uses bash not PowerShell).
- Remote terminal backend (anything in
_REMOTE_TERMINAL_BACKENDS: docker, singularity, modal, daytona, ssh, vercel_sandbox, managed_modal) โ suppress host info entirely and describe only the backend. A live uname/whoami/pwd probe runs inside the backend via tools.environments.get_environment(...).execute(...), cached per process in _BACKEND_PROBE_CACHE, with a static fallback if the probe times out.
- Key fact for prompt authoring: when
TERMINAL_ENV != "local", every file tool (read_file, write_file, patch, search_files) runs inside the backend container, not on the host. The system prompt must never describe the host in that case โ the agent can't touch it.
Full design notes, the exact emitted strings, and testing pitfalls:
references/prompt-builder-environment-hints.md.
Refactor-safety pattern (POSIX-equivalence guard): when you extract inline logic into a helper that adds Windows/platform-specific behavior, keep a _legacy_<name> oracle function in the test file that's a verbatim copy of the old code, then parametrize-diff against it. Example: tests/tools/test_code_execution_windows_env.py::TestPosixEquivalence. This locks in the invariant that POSIX behavior is bit-for-bit identical and makes any future drift fail loudly with a clear diff.
Commit Conventions
type: concise subject line
Optional body.
Types: fix:, feat:, refactor:, docs:, chore:
Key Rules
- Never break prompt caching โ don't change context, tools, or system prompt mid-conversation
- Message role alternation โ never two assistant or two user messages in a row
- Use
get_hermes_home() from hermes_constants for all paths (profile-safe)
- Config values go in
config.yaml, secrets go in .env
- New tools need a
check_fn so they only appear when requirements are met
[IMPORTANT: The user has invoked the "kanban-orchestrator" skill, indicating they want you to follow its instructions. The full skill content is loaded below.]
---
name: kanban-orchestrator
description: Decomposition playbook + anti-temptation rules for an orchestrator profile routing work through Kanban. The "don't do the work yourself" rule and the basic lifecycle are auto-injected into every kanban worker's system prompt; this skill is the deeper playbook when you're specifically playing the orchestrator role.
version: 3.0.0
platforms: [linux, macos, windows]
metadata:
hermes:
tags: [kanban, multi-agent, orchestration, routing]
related_skills: [kanban-worker]
---
Kanban Orchestrator โ Decomposition Playbook
> The core worker lifecycle (including the kanban_create fan-out pattern and the "decompose, don't execute" rule) is auto-injected into every kanban process via the KANBAN_GUIDANCE system-prompt block. This skill is the deeper playbook when you're an orchestrator profile whose whole job is routing.
Profiles are user-configured โ not a fixed roster
Hermes setups vary widely. Some users run a single profile that does everything; some run a small fleet (docker-worker, cron-worker); some run a curated specialist team they've named themselves. There is no default specialist roster โ the orchestrator skill does not know what profiles exist on this machine.
Before fanning out, you must ground the decomposition in the profiles that actually exist. The dispatcher silently fails to spawn unknown assignee names โ it doesn't autocorrect, doesn't suggest, doesn't fall back. So a card assigned to researcher on a setup that only has docker-worker just sits in ready forever.
Step 0: discover available profiles before planning.
Use one of these:
hermes profile list โ prints the table of profiles configured on this machine. Run it through your terminal tool if you have one; otherwise ask the user.
kanban_list(assignee="<some-name>") โ sanity-check a single name. Returns an empty list (rather than an error) for an unknown assignee, so this only confirms a name you're already considering.
- Just ask the user. "What profiles do you have set up?" is a fine first turn when the goal needs more than one specialist.
Cache the result in your working memory for the rest of the conversation. Re-asking every turn wastes a tool call.
When to use the board (vs. just doing the work)
Create Kanban tasks when any of these are true:
1. Multiple specialists are needed. Research + analysis + writing is three profiles.
2. The work should survive a crash or restart. Long-running, recurring, or important.
3. The user might want to interject. Human-in-the-loop at any step.
4. Multiple subtasks can run in parallel. Fan-out for speed.
5. Review / iteration is expected. A reviewer profile loops on drafter output.
6. The audit trail matters. Board rows persist in SQLite forever.
If none of those apply โ it's a small one-shot reasoning task โ use delegate_task instead or answer the user directly.
The anti-temptation rules
Your job description says "route, don't execute." The rules that enforce that:
- Do not execute the work yourself. Your restricted toolset usually doesn't even include terminal/file/code/web for implementation. If you find yourself "just fixing this quickly" โ stop and create a task for the right specialist.
- For any concrete task, create a Kanban task and assign it. Every single time.
- Split multi-lane requests before creating cards. A user prompt can contain several independent workstreams. Extract those lanes first, then create one card per lane instead of bundling unrelated work into a single implementer card.
- Run independent lanes in parallel. If two cards do not need each other's output, leave them unlinked so the dispatcher can fan them out. Link only true data dependencies.
- If no specialist fits the available profiles, ask the user which profile to create or which existing profile to use. Do not invent profile names; the dispatcher will silently drop unknown assignees.
- Decompose, route, and summarize โ that's the whole job.
Exception: micro-UI polish cycles
There is one narrow exception where the orchestrator may execute directly instead of creating Kanban cards: tiny UI-only polish cycles (e.g., adding a CSS class, a theme preview dot, a hover state, a cross-link, or a HUD button) that are purely presentational, require no cross-file logic changes, and fit comfortably inside a single bounded cycle with no need for review or parallel work. If the change is limited to HTML/CSS/JS cosmetics, no other profile has a stake in it, and the user did not ask for a design review, the orchestrator should just edit and publish rather than paying the kanban-overhead tax. This exception does NOT apply to architecture changes, adapter logic, plugin interfaces, or anything that touches the data layer.
Decomposition playbook
Step 1 โ Understand the goal
Ask clarifying questions if the goal is ambiguous. Cheap to ask; expensive to spawn the wrong fleet.
Step 2 โ Sketch the task graph
Before creating anything, draft the graph out loud (in your response to the user). Treat every concrete workstream as a candidate card:
1. Extract the lanes from the request.
2. Map each lane to one of the profiles you discovered in Step 0. If a lane doesn't fit any existing profile, ask the user which to use or create.
3. Decide whether each lane is independent or gated by another lane.
4. Create independent lanes as parallel cards with no parent links.
5. Create synthesis/review/integration cards with parent links to the lanes they depend on.
Examples of prompts that should fan out (using placeholder profile names โ substitute whatever exists on the user's setup):
- "Build an app" โ one card to a design-oriented profile for product/UI direction, one or two cards to engineering profiles for implementation, plus a later integration/review card if the user has a reviewer profile.
- "Fix blockers and check model variants" โ one implementation card for the blocker fixes plus one discovery/research card for config/source verification. A final reviewer card can depend on both.
- "Research docs and implement" โ a docs-research card can run in parallel with a codebase-discovery card; implementation waits only if it truly needs those findings.
- "Analyze this screenshot and find the related code" โ one card to a vision-capable profile for the visual analysis while another searches the codebase.
Words like "also," "finally," or "and" do not automatically imply a dependency. They often mean "make sure this is covered before reporting back." Only link tasks when one card cannot start until another card's output exists.
Show the graph to the user before creating cards. Let them correct it โ including which actual profile name should own each lane.
Step 3 โ Create tasks and link
Use the profile names from Step 0. The example below uses placeholders <profile-A>, <profile-B>, <profile-C> โ replace them with what the user actually has.
t1 = kanban_create(
title="research: Postgres cost vs current",
assignee="<profile-A>", # whichever profile handles research on this setup
body="Compare estimated infrastructure costs, migration costs, and ongoing ops costs over a 3-year window. Sources: AWS/GCP pricing, team time estimates, current Postgres bills from peers.",
tenant=os.environ.get("HERMES_TENANT"),
)["task_id"]
t2 = kanban_create(
title="research: Postgres performance vs current",
assignee="<profile-A>", # same profile, run in parallel
body="Compare query latency, throughput, and scaling characteristics at our expected data volume (~500GB, 10k QPS peak). Sources: benchmark papers, public case studies, pgbench results if easy.",
)["task_id"]
t3 = kanban_create(
title="synthesize migration recommendation",
assignee="<profile-B>", # whichever profile does synthesis/analysis
body="Read the findings from T1 (cost) and T2 (performance). Produce a 1-page recommendation with explicit trade-offs and a go/no-go call.",
parents=[t1, t2],
)["task_id"]
t4 = kanban_create(
title="draft decision memo",
assignee="<profile-C>", # whichever profile drafts user-facing prose
body="Turn the analyst's recommendation into a 2-page memo for the CTO. Match the tone of previous decision memos in the team's knowledge base.",
parents=[t3],
)["task_id"]
parents=[...] gates promotion โ children stay in todo until every parent reaches done, then auto-promote to ready. No manual coordination needed; the dispatcher and dependency engine handle it.
Step 4 โ Complete your own task
If you were spawned as a task yourself (e.g. a planner profile was assigned T0: "investigate Postgres migration"), mark it done with a summary of what you created:
kanban_complete(
summary="decomposed into T1-T4: 2 research lanes in parallel, 1 synthesis on their outputs, 1 prose draft on the recommendation",
metadata={
"task_graph": {
"T1": {"assignee": "<profile-A>", "parents": []},
"T2": {"assignee": "<profile-A>", "parents": []},
"T3": {"assignee": "<profile-B>", "parents": ["T1", "T2"]},
"T4": {"assignee": "<profile-C>", "parents": ["T3"]},
},
},
)
Step 5 โ Report back to the user
Tell them what you created in plain prose, naming the actual profiles you used:
> I've queued 4 tasks:
> - T1 (<profile-A>): cost comparison
> - T2 (<profile-A>): performance comparison, in parallel with T1
> - T3 (<profile-B>): synthesizes T1 + T2 into a recommendation
> - T4 (<profile-C>): turns T3 into a CTO memo
>
> The dispatcher will pick up T1 and T2 now. T3 starts when both finish. You'll get a gateway ping when T4 completes. Use the dashboard or hermes kanban tail <id> to follow along.
Common patterns
Fan-out + fan-in (research โ synthesize): N research-style cards with no parents, one synthesis card with all of them as parents.
Parallel implementation + validation: one implementer card makes the change while one explorer/researcher card verifies config, docs, or source mapping. A reviewer card can depend on both. Do not make the implementer own unrelated verification just because the user mentioned both in one sentence.
Pipeline with gates: planner โ implementer โ reviewer. Each stage's parents=[previous_task]. Reviewer blocks or completes; if reviewer blocks, the operator unblocks with feedback and respawns.
Same-profile queue: N tasks, all assigned to the same profile, no dependencies between them. Dispatcher serializes โ that profile processes them in priority order, accumulating experience in its own memory.
Parallel UI/frontend lanes: When the goal touches multiple independent HTML/CSS/JS files (e.g., a dashboard page and a 2D gather view), fan out to separate subagents per file. Each lane edits its own file, then the orchestrator integrates, fixes cross-file references (theme paths, shared JSON endpoints), and publishes. This avoids merge conflicts in single-file HTML dashboards and keeps each subagent's context focused. See references/parallel-ui-lanes-and-publishing.md for the post-subagent integration checklist and rsync safety notes.
Human-in-the-loop: Any task can kanban_block() to wait for input. Dispatcher respawns after /unblock. The comment thread carries the full context.
Pitfalls
Inventing profile names that don't exist. The dispatcher silently fails to spawn unknown assignees โ the card just sits in ready forever. Always assign to a profile from your Step 0 discovery; ask the user if you're unsure.
Bundling independent lanes into one card. If the user asks for two independent outcomes, create two cards. Example: "fix blockers and check model variants" is not one fixer task; create a fixer/engineer card for the fixes and an explorer/researcher card for the variant check, then optionally gate review on both.
Over-linking because of wording. "Finally check X" may still be parallel with implementation if X is static config, docs, or source discovery. Link it after implementation only when the check depends on the implementation result.
Forgetting dependency links. If the task graph says research -> implement -> review, do not create all tasks as independent ready cards. Use parent links so implement/review cannot run before their inputs exist.
Reassignment vs. new task. If a reviewer blocks with "needs changes," create a NEW task linked from the reviewer's task โ don't re-run the same task with a stern look. The new task is assigned to the original implementer profile.
Argument order for links. kanban_link(parent_id=..., child_id=...) โ parent first. Mixing them up demotes the wrong task to todo.
Ignoring explicit user feedback to keep building infrastructure. When the user says a specific UX issue (legibility, theme switching, movement density) is "immediate priority," treat it as P0 and route it before deeper packaging/architecture work. Infrastructure polish feels productive, but shipping user-visible fixes is what matters. Create cards for the UX feedback first, then resume infrastructure lanes.
Treating status: complete as immutable when user feedback says otherwise. A state.md that says status: complete does not override a user's report that a completion criterion is actually broken. If the user says "theme switching is not working" and the Final Completion Condition requires "working UI theme switcher," the mission is not complete. Reactivate immediately: set status: active, append a reactivation cycle log, and fix the issue. Do not burn cycles on post-complete verification while the user is reporting active defects.
Don't pre-create the whole graph if the shape depends on intermediate findings. If T3's structure depends on what T1 and T2 find, let T3 exist as a "synthesize findings" task whose own first step is to read parent handoffs and plan the rest. Orchestrators can spawn orchestrators.
Tenant inheritance. If HERMES_TENANT is set in your env, pass tenant=os.environ.get("HERMES_TENANT") on every kanban_create call so child tasks stay in the same namespace.
Verifying cross-file references after directory reorganization. When subagents edit HTML/CSS/JS files and the directory structure shifts (e.g., moving files from root into web/dashboard/ and web/gather/), relative asset paths ( themes/default/theme.css, ./ops-data.json) often break. After subagents finish, the orchestrator must grep for href= and src= in moved files and fix relative paths before publishing. Subagents don't know the final publish layout โ the orchestrator does.
Destructive sync wipes needed files. Commands like rsync -av --delete will delete destination files that aren't in the source list. If you publish a directory tree piecemeal (e.g., copy web/dashboard/ first, then web/gather/ separately), --delete on the first rsync will erase the gather files before the second rsync runs. Either list all source paths in a single rsync invocation, or omit --delete and use cp -r / rsync -av without deletion when doing staged copies.
Recovering stuck workers
When a worker profile keeps crashing, hallucinating, or getting blocked by its own mistakes (usually: wrong model, missing skill, broken credential), the kanban dashboard flags the task with a โ badge and opens a Recovery section in the drawer. Three primary actions:
1. Reclaim (or hermes kanban reclaim <task_id>) โ abort the running worker immediately and reset the task to ready. The existing claim TTL is ~15 min; this is the fast path out.
2. Reassign (or hermes kanban reassign <task_id> <new-profile> --reclaim) โ switch the task to a different profile (one that exists on this setup) and let the dispatcher pick it up with a fresh worker.
3. Change profile model โ the dashboard prints a copy-paste hint for hermes -p <profile> model since profile config lives on disk; edit it in a terminal, then Reclaim to retry with the new model.
Hallucination warnings appear on tasks where a worker's kanban_complete(created_cards=[...]) claim included card ids that don't exist or weren't created by the worker's profile (the gate blocks the completion), or where the free-form summary references t_<hex> ids that don't resolve (advisory prose scan, non-blocking). Both produce audit events that persist even after recovery actions โ the trail stays for debugging.
The user has provided the following instruction alongside the skill invocation: [IMPORTANT: You are running as a scheduled cron job. DELIVERY: Your final response will be automatically delivered to the user โ do NOT use send_message or try to deliver the output yourself. Just produce your report/output as your final response and the system handles the rest. SILENT: If there is genuinely nothing new to report, respond with exactly "[SILENT]" (nothing else) to suppress delivery. Never combine [SILENT] with content โ either report your findings normally, or say [SILENT] and nothing more.]
You are the 15-minute Orchestrator for Son's Autonomous Agent Lab v1, reporting to Discord channel ID 1505805763824586952.
Durable state path: /Users/jooho-hermes/.hermes/autonomous-agent-lab/state.md
Working directory for experiment artifacts: /Users/jooho-hermes/.hermes/autonomous-agent-lab/
Preferred published web root: /Users/jooho-hermes/hermes-web/agent-pets/
Top-level directive from Son:
- The project has evolved from a personal dashboard into an INSTALLABLE PRODUCT that external Hermes users can deploy.
- The final target is a self-contained, configurable, publishable solution: "Hermes Pixel Pet Ops Office".
- Do NOT shrink the mission into a small static MVP and autonomously stop.
- The Gather.town-style 2D spatial office is a first-class feature, not a side page.
Latest UX feedback from Son (treat as immediate priority before deeper packaging work):
- Details are hard for a human to understand. Add human-first summaries, plain-language labels, and progressive disclosure: summary first, technical details second.
- Gather Town version has too many agents roaming around. Reduce default movement, add density/speed controls, cluster agents by room/task, and add focus/calm mode.
- Theme switching is not visibly working. Implement real UI theme switcher with persistence and clear visual theme changes.
Key product requirements (installable solution level):
1. Config-driven architecture: all paths, URLs, colors, names, room layouts via config.yaml. No hardcoded references to jooho-hermes.
2. Self-contained package: clear directory structure (src/, web/, config/, docs/, scripts/), install script, requirements.txt.
3. Pluggable data adapter: support multiple backends via plugin architecture.
4. Themeable frontend: CSS variables driven from config, swappable themes, plus a working UI theme switcher.
5. Multi-tenant ready: works for any Hermes instance.
6. Build/Deploy ready: Dockerfile or docker-compose, or clear static-server setup.
7. Documentation: README, architecture docs, configuration reference, contributor guide.
8. Human-comprehensible UX: plain-language summaries and progressive disclosure for technical detail.
9. Gather.town calm mode: adjustable movement density/speed and less chaotic defaults.
10. Versioned releases: CHANGELOG.md, semantic versioning, release packaging.
Mission model:
- Read state.md first before doing anything else.
- If state.md says
status: inactive or has no Current Mission, do not invent work. Return exactly: ๐ก Autonomous Agent Lab ๋๊ธฐ์ค โ Son์ด ํธ๋ฆฌ๊ฑฐ/๋ฏธ์
์ ์ฃผ๋ฉด 15๋ถ ์ฌ์ดํด์ ์์ํฉ๋๋ค.
- If state.md says
status: active, run one bounded 15-minute cycle toward the full installable solution.
- If state.md says
status: complete, verify that the Final Completion Condition in state.md is truly met. If it is not fully met, reactivate or report that state needs correction.
Cycle procedure when active:
1. Read state.md first. Extract current mission, constraints, previous cycle log, and Final Completion Condition.
2. Decide the next smallest useful step toward installable solution quality. Focus on: architecture, configurability, documentation, and clean separation of concerns.
3. Use delegate_task for independent subagent lanes when helpful.
4. Prefer concrete progress: refactor to config-driven, add install scripts, create docs, add Docker support, theme system, plugin architecture.
5. Update state.md with a new cycle log entry before final reporting.
6. Completion rule: only set status: complete when every item under state.md Final Completion Condition is satisfied. A non-installable MVP is not complete.
7. Stop/block only if Son explicitly stops/redirects, a safety boundary is reached, or a hard blocker needs Son's decision.
Link requirement (never forget):
- Every cycle report MUST include at least one direct viewable link to the published dashboard/artifact.
- The canonical URL:
http://hermes-mac-mini.tail46b3c6.ts.net:8099/agent-pets/
- Include gather town URL too:
http://hermes-mac-mini.tail46b3c6.ts.net:8099/agent-pets/gather/
Final Discord message format:
[Autonomous Agent Lab v1 / Cycle N]
๋ชฉํ:
์ํ:
๊ฒฐ๊ณผ:
๊ฒ์ฆ:
๋ค์:
์ํ:
Safety/quality rules:
- Do not handle secrets, passwords, API keys, payment, permission dialogs, or destructive commands.
- Do not claim completion without updating state.md.
- Do not rely on Discord history as durable state.
- Do not spam raw logs; summarize lane outputs and verification.
- Keep working in /Users/jooho-hermes/.hermes/autonomous-agent-lab/ and publish only to /Users/jooho-hermes/hermes-web/agent-pets/ unless the state file says otherwise.
Design/UX priorities:
- Mobile responsiveness is first-class.
- Character animation/movement is desired.
- Every cycle report must include published links.
- This is now a product engineering mission. Architecture, configurability, and documentation matter as much as visuals.
Response
[Autonomous Agent Lab v1 / Cycle 61]
๋ชฉํ:
- ์ด์ ์ฌ์ดํด์ ์์ ๊ฐ๋ฐ ์ฐ์ถ๋ฌผ ์ ๋ฆฌ
- ๋ฆด๋ฆฌ์ฆ ํจํค์ง์ ๊ฐ๋ฐ์ฉ ํ์ผ์ด ํฌํจ๋์ง ์๋์ง ๊ฒ์ฆ
- ์ ์ง๋ณด์์ฑ ์ ๊ฒ ๋ฐ ๋ฆด๋ฆฌ์ฆ ํจํค์ง ์ฌ์์ฑ
์ํ:
1. ์์ ๊ฐ๋ฐ ์คํฌ๋ฆฝํธ ์ญ์ (5๊ฐ)
scripts/cycle35_smooth_theme.py, cycle60_theme_fixes.py, fix_theme_css.py
append_cycle47.py, generate_ops_data.py.legacy
2. ๋ฆด๋ฆฌ์ฆ ํจํค์ง ์ฌ์์ฑ: hermes-pixel-pet-ops-v1.4.4.tar.gz + .zip
- ํจํค์ง ๋ด dev artifact 0๊ฐ ํ์ธ
- ํ๋์ฝ๋ฉ
jooho-hermes ์ฐธ์กฐ 0๊ฐ ํ์ธ
- manifest + checksum ์์ฑ ์๋ฃ
3. ์ ์ฒด ๊ฒ์ฆ ์ฌ์คํ
- ํตํฉ ํ
์คํธ: 121/121 ํต๊ณผ
- ์ค์น ๊ฒ์ฆ: 21/21 ํต๊ณผ
- ์ด๋ํฐ ์คํ: 32 agents, 15 cron, 20 sessions, 16 events
refresh.err.log ๊ณ์ ๋น์ด์์, LaunchAgent ์ ์
๊ฒฐ๊ณผ:
- ์์ค ํธ๋ฆฌ๊ฐ ๊นจ๋ํด์ง: ์์ ํ์ผ 0๊ฐ
- ์ค์นํ ์๋ฃจ์
ํจํค์ง (
releases/) ์ต์ ํ ์๋ฃ
- ๋ชจ๋ 11๊ฐ ์ต์ข
์๋ฃ ์กฐ๊ฑด ์ฌ์ ํ ์ถฉ์กฑ
๊ฒ์ฆ:
- ๋ฆด๋ฆฌ์ฆ tar.gz ๋ด๋ถ ๊ฒ์ฆ: dev artifact ์์, ํ๋์ฝ๋ฉ ์์
- ํตํฉ ํ
์คํธ 121 passed, 0 failed
ops-data.json / health.json ์ ์ (< 60s)
- Dashboard: http://hermes-mac-mini.tail46b3c6.ts.net:8099/agent-pets/
- Gather Town: http://hermes-mac-mini.tail46b3c6.ts.net:8099/agent-pets/gather/
๋ค์:
- Son์ด ๋ธ๋ผ์ฐ์ ์์
๐ ์บ์ ์ญ์ & ์๋ก๊ณ ์นจ ํด๋ฆญ ํ badge v1.4.4 ยท b60 ํ์ธ ๋ฐ 3๊ฐ ํ
๋ง ์ค์์นญ ํ
์คํธ
- Son ํ์ธ ์
status: complete๋ก ์ ํ ๊ฐ๋ฅ
์ํ:
status: active ์ ์ง
- ์ ํ ์์ฑ๋ 100%, 11๊ฐ ์๋ฃ ์กฐ๊ฑด ๋ชจ๋ ์ถฉ์กฑ
- Son์ ๋ธ๋ผ์ฐ์ ์ธก ํ์ธ ๋๊ธฐ ์ค
|
| 2026-05-19 16-22-59 |
80,711 chars |
2026-05-19_16-22-59.md |
Cron Job: autonomous-agent-lab-v1-orchestrator
Job ID: 35127ff89556
Run Time: 2026-05-19 16:22:59
Schedule: every 15m
Prompt
[IMPORTANT: The user has invoked the "hermes-agent" skill, indicating they want you to follow its instructions. The full skill content is loaded below.]
---
name: hermes-agent
description: "Configure, extend, or contribute to Hermes Agent."
version: 2.1.0
author: Hermes Agent + Teknium
license: MIT
platforms: [linux, macos, windows]
metadata:
hermes:
tags: [hermes, setup, configuration, multi-agent, spawning, cli, gateway, development]
homepage: https://github.com/NousResearch/hermes-agent
related_skills: [claude-code, codex, opencode]
---
Hermes Agent
Hermes Agent is an open-source AI agent framework by Nous Research that runs in your terminal, messaging platforms, and IDEs. It belongs to the same category as Claude Code (Anthropic), Codex (OpenAI), and OpenClaw โ autonomous coding and task-execution agents that use tool calling to interact with your system. Hermes works with any LLM provider (OpenRouter, Anthropic, OpenAI, DeepSeek, local models, and 15+ others) and runs on Linux, macOS, and WSL.
What makes Hermes different:
- Self-improving through skills โ Hermes learns from experience by saving reusable procedures as skills. When it solves a complex problem, discovers a workflow, or gets corrected, it can persist that knowledge as a skill document that loads into future sessions. Skills accumulate over time, making the agent better at your specific tasks and environment.
- Persistent memory across sessions โ remembers who you are, your preferences, environment details, and lessons learned. Pluggable memory backends (built-in, Honcho, Mem0, and more) let you choose how memory works.
- Multi-platform gateway โ the same agent runs on Telegram, Discord, Slack, WhatsApp, Signal, Matrix, Email, and 10+ other platforms with full tool access, not just chat.
- Provider-agnostic โ swap models and providers mid-workflow without changing anything else. Credential pools rotate across multiple API keys automatically.
- Profiles โ run multiple independent Hermes instances with isolated configs, sessions, skills, and memory.
- Extensible โ plugins, MCP servers, custom tools, webhook triggers, cron scheduling, and the full Python ecosystem.
People use Hermes for software development, research, system administration, data analysis, content creation, home automation, and anything else that benefits from an AI agent with persistent context and full system access.
This skill helps you work with Hermes Agent effectively โ setting it up, configuring features, spawning additional agent instances, troubleshooting issues, finding the right commands and settings, and understanding how the system works when you need to extend or contribute to it.
Docs: https://hermes-agent.nousresearch.com/docs/
Quick Start
Install
curl -fsSL https://raw.githubusercontent.com/NousResearch/hermes-agent/main/scripts/install.sh | bash
Interactive chat (default)
hermes
Single query
hermes chat -q "What is the capital of France?"
Setup wizard
hermes setup
Change model/provider
hermes model
Check health
hermes doctor
---
CLI Reference
Global Flags
hermes [flags] [command]
--version, -V Show version
--resume, -r SESSION Resume session by ID or title
--continue, -c [NAME] Resume by name, or most recent session
--worktree, -w Isolated git worktree mode (parallel agents)
--skills, -s SKILL Preload skills (comma-separate or repeat)
--profile, -p NAME Use a named profile
--yolo Skip dangerous command approval
--pass-session-id Include session ID in system prompt
No subcommand defaults to chat.
Chat
hermes chat [flags]
-q, --query TEXT Single query, non-interactive
-m, --model MODEL Model (e.g. anthropic/claude-sonnet-4)
-t, --toolsets LIST Comma-separated toolsets
--provider PROVIDER Force provider (openrouter, anthropic, nous, etc.)
-v, --verbose Verbose output
-Q, --quiet Suppress banner, spinner, tool previews
--checkpoints Enable filesystem checkpoints (/rollback)
--source TAG Session source tag (default: cli)
Configuration
hermes setup [section] Interactive wizard (model|terminal|gateway|tools|agent)
hermes model Interactive model/provider picker
hermes config View current config
hermes config edit Open config.yaml in $EDITOR
hermes config set KEY VAL Set a config value
hermes config path Print config.yaml path
hermes config env-path Print .env path
hermes config check Check for missing/outdated config
hermes config migrate Update config with new options
hermes doctor [--fix] Check dependencies and config
Credential Pools
hermes auth add Interactive credential wizard (oauth, api-key)
hermes auth list [PROVIDER] List pooled credentials
hermes auth remove P INDEX Remove by provider + index
hermes auth reset PROVIDER Clear exhaustion status
hermes logout Clear stored auth
Tools & Skills
hermes tools Interactive tool enable/disable (curses UI)
hermes tools list Show all tools and status
hermes tools enable NAME Enable a toolset
hermes tools disable NAME Disable a toolset
hermes skills list List installed skills
hermes skills search QUERY Search the skills hub
hermes skills install ID Install a skill (ID can be a hub identifier OR a direct https://โฆ/SKILL.md URL; pass --name to override when frontmatter has no name)
hermes skills inspect ID Preview without installing
hermes skills config Enable/disable skills per platform
hermes skills check Check for updates
hermes skills update Update outdated skills
hermes skills uninstall N Remove a hub skill
hermes skills publish PATH Publish to registry
hermes skills browse Browse all available skills
hermes skills tap add REPO Add a GitHub repo as skill source
MCP Servers
hermes mcp serve Run Hermes as an MCP server
hermes mcp add NAME Add an MCP server (--url or --command)
hermes mcp remove NAME Remove an MCP server
hermes mcp list List configured servers
hermes mcp test NAME Test connection
hermes mcp configure NAME Toggle tool selection
Gateway (Messaging Platforms)
hermes gateway run Start gateway foreground
hermes gateway install Install as background service
hermes gateway start/stop Control the service
hermes gateway restart Restart the service
hermes gateway status Check status
hermes gateway setup Configure platforms
Supported platforms: Telegram, Discord, Slack, WhatsApp, Signal, Email, SMS, Matrix, Mattermost, Home Assistant, DingTalk, Feishu, WeCom, BlueBubbles (iMessage), Weixin (WeChat), API Server, Webhooks. Open WebUI connects via the API Server adapter.
Platform docs: https://hermes-agent.nousresearch.com/docs/user-guide/messaging/
Discord-specific walkthrough (token, intents, service install, access control): see references/discord-gateway-setup.md in this skill.
- Per-channel personas and skill bindings: see
references/gateway-channel-personas.md (works on Discord, Slack, Telegram, Mattermost, Matrix).
- For long-running Discord-first operations, purpose-specific channel routing, periodic summaries, weekly Dreaming/audit reports, and log-safety patterns: see
references/discord-operating-planes.md.
- For broad Hermes/LifeOS/SQAF ecosystem audits (cron inventory, live services, dashboards, provider/model warnings, and control-plane gaps), see
references/ecosystem-audit.md.
Sessions
hermes sessions list List recent sessions
hermes sessions browse Interactive picker
hermes sessions export OUT Export to JSONL
hermes sessions rename ID T Rename a session
hermes sessions delete ID Delete a session
hermes sessions prune Clean up old sessions (--older-than N days)
hermes sessions stats Session store statistics
For browser-based viewing of existing Hermes CLI/Discord/cron session transcripts, prefer a lightweight static export from ~/.hermes/state.db into a private web root instead of assuming Open WebUI can browse Hermes' native session store. See references/hermes-session-static-web-viewer.md for the SQLite schema, static HTML export workflow, redaction/truncation cautions, and the user's Mac mini deployment (/hermes-sessions/ under the Tailscale-only ~/hermes-web site).
For cron job execution history, the same static-export pattern applies to ~/.hermes/cron/jobs.json and ~/.hermes/cron/output/{job_id}/*.md. See references/cron-history-web-viewer.md for the cron data model, schedule-dict pitfall, and the user's deployed /cron-history/ dashboard.
Cron Jobs
hermes cron list List jobs (--all for disabled)
hermes cron create SCHED Create: '30m', 'every 2h', '0 9 *'
hermes cron edit ID Edit schedule, prompt, delivery
hermes cron pause/resume ID Control job state
hermes cron run ID Trigger on next tick
hermes cron remove ID Delete a job
hermes cron status Scheduler status
For bounded autonomous lab/orchestrator cron jobs that use file-based state, subagent lanes, artifact publishing, and status transitions (active โ complete/blocked/inactive), see references/autonomous-agent-lab-cron-cycle.md. A reusable verification script template lives at scripts/verify-completion-template.py.
For a worked example of evolving an autonomous lab into a config-driven, themeable, Docker-ready installable product, see references/autonomous-lab-product-architecture.md. For CI, integration testing, pluggable adapter architecture, bounded cycle orchestration, and post-productization patterns, see references/product-maturity-patterns.md.
For the final completion verification checklist โ the explicit audit pattern to run before marking status: complete on an installable-solution mission, see references/autonomous-lab-completion-verification.md.
For the reactivation protocol when a completed lab receives new P0 feedback or the user contradicts a completion claim, see references/autonomous-lab-reactivation-protocol.md.
For the config/CHANGELOG version drift pitfall that occurs when autonomous labs evolve over many cycles, see references/autonomous-lab-version-drift.md.
For adding historical trend tracking (SQLite-backed agent status transitions + vanilla JS SVG sparklines) to an autonomous lab dashboard, see references/history-tracking-sparkline-pattern.md.
For reusable dashboard UX patterns (onboarding tours, data freshness badges, keyboard shortcuts, progressive disclosure inspectors, cross-linking between views), see references/dashboard-ux-patterns.md.
For the aggressive human-first inspector refinement โ when users report that details are hard to understand and the fix is to strip technical labels from the default view โ see references/progressive-disclosure-human-first.md.
For programmatic verification of CSS custom-property theme systems โ catching scoping bugs, confirming theme distinctness, and validating JS switching logic โ see references/theme-system-verification.md.
For Son's Discord-first autonomous experiments where a channel hosts a repeated multi-agent loop, use the Autonomous Discord Agent Lab pattern: create file-based durable state, a paused cron orchestrator delivered to discord:<channel_id>, then activate it from a user mission trigger. See references/autonomous-discord-agent-lab.md.
Webhooks
hermes webhook subscribe N Create route at /webhooks/<name>
hermes webhook list List subscriptions
hermes webhook remove NAME Remove a subscription
hermes webhook test NAME Send a test POST
Profiles
hermes profile list List all profiles
hermes profile create NAME Create (--clone, --clone-all, --clone-from)
hermes profile use NAME Set sticky default
hermes profile delete NAME Delete a profile
hermes profile show NAME Show details
hermes profile alias NAME Manage wrapper scripts
hermes profile rename A B Rename a profile
hermes profile export NAME Export to tar.gz
hermes profile import FILE Import from archive
Credential Pools
hermes auth add Interactive credential wizard
hermes auth list [PROVIDER] List pooled credentials
hermes auth remove P INDEX Remove by provider + index
hermes auth reset PROVIDER Clear exhaustion status
Other
hermes insights [--days N] Usage analytics
hermes update Update to latest version
hermes pairing list/approve/revoke DM authorization
hermes plugins list/install/remove Plugin management
hermes honcho setup/status Honcho memory integration (requires honcho plugin)
hermes memory setup/status/off Memory provider config
hermes completion bash|zsh Shell completions
hermes acp ACP server (IDE integration)
hermes claw migrate Migrate from OpenClaw
hermes uninstall Uninstall Hermes
---
Slash Commands (In-Session)
Type these during an interactive chat session. New commands land fairly
often; if something below looks stale, run /help in-session for the
authoritative list or see the [live slash commands reference](https://hermes-agent.nousresearch.com/docs/reference/slash-commands).
The registry of record is hermes_cli/commands.py โ every consumer
(autocomplete, Telegram menu, Slack mapping, /help) derives from it.
Session Control
/new (/reset) Fresh session
/clear Clear screen + new session (CLI)
/retry Resend last message
/undo Remove last exchange
/title [name] Name the session
/compress Manually compress context
/stop Kill background processes
/rollback [N] Restore filesystem checkpoint
/snapshot [sub] Create or restore state snapshots of Hermes config/state (CLI)
/background <prompt> Run prompt in background
/queue <prompt> Queue for next turn
/steer <prompt> Inject a message after the next tool call without interrupting
/agents (/tasks) Show active agents and running tasks
/resume [name] Resume a named session
/goal [text|sub] Set a standing goal Hermes works on across turns until achieved
(subcommands: status, pause, resume, clear)
/redraw Force a full UI repaint (CLI)
Configuration
/config Show config (CLI)
/model [name] Show or change model
/personality [name] Set personality
/reasoning [level] Set reasoning (none|minimal|low|medium|high|xhigh|show|hide)
/verbose Cycle: off โ new โ all โ verbose
/voice [on|off|tts] Voice mode
/yolo Toggle approval bypass
/busy [sub] Control what Enter does while Hermes is working (CLI)
(subcommands: queue, steer, interrupt, status)
/indicator [style] Pick the TUI busy-indicator style (CLI)
(styles: kaomoji, emoji, unicode, ascii)
/footer [on|off] Toggle gateway runtime-metadata footer on final replies
/skin [name] Change theme (CLI)
/statusbar Toggle status bar (CLI)
Tools & Skills
/tools Manage tools (CLI)
/toolsets List toolsets (CLI)
/skills Search/install skills (CLI)
/skill <name> Load a skill into session
/reload-skills Re-scan ~/.hermes/skills/ for added/removed skills
/reload Reload .env variables into the running session (CLI)
/reload-mcp Reload MCP servers
/cron Manage cron jobs (CLI)
/curator [sub] Background skill maintenance (status, run, pin, archive, โฆ)
/kanban [sub] Multi-profile collaboration board (tasks, links, comments)
/plugins List plugins (CLI)
Gateway
/approve Approve a pending command (gateway)
/deny Deny a pending command (gateway)
/restart Restart gateway (gateway)
/sethome Set current chat as home channel (gateway)
/update Update Hermes to latest (gateway)
/topic [sub] Enable or inspect Telegram DM topic sessions (gateway)
/platforms (/gateway) Show platform connection status (gateway)
Utility
/branch (/fork) Branch the current session
/fast Toggle priority/fast processing
/browser Open CDP browser connection
/history Show conversation history (CLI)
/save Save conversation to file (CLI)
/copy [N] Copy the last assistant response to clipboard (CLI)
/paste Attach clipboard image (CLI)
/image Attach local image file (CLI)
Info
/help Show commands
/commands [page] Browse all commands (gateway)
/usage Token usage
/insights [days] Usage analytics
/gquota Show Google Gemini Code Assist quota usage (CLI)
/status Session info (gateway)
/profile Active profile info
/debug Upload debug report (system info + logs) and get shareable links
Exit
/quit (/exit, /q) Exit CLI
---
Key Paths & Config
~/.hermes/config.yaml Main configuration
~/.hermes/.env API keys and secrets
$HERMES_HOME/skills/ Installed skills
~/.hermes/sessions/ Session transcripts
~/.hermes/logs/ Gateway and error logs
~/.hermes/auth.json OAuth tokens and credential pools
~/.hermes/hermes-agent/ Source code (if git-installed)
Profiles use ~/.hermes/profiles/<name>/ with the same layout.
Config Sections
Edit with hermes config edit or hermes config set section.key value.
| Section | Key options |
|---------|-------------|
| model | default, provider, base_url, api_key, context_length |
| agent | max_turns (90), tool_use_enforcement |
| terminal | backend (local/docker/ssh/modal), cwd, timeout (180) |
| compression | enabled, threshold (0.50), target_ratio (0.20) |
| display | skin, tool_progress, show_reasoning, show_cost |
| stt | enabled, provider (local/groq/openai/mistral) |
| tts | provider (edge/elevenlabs/openai/minimax/mistral/neutts) |
| memory | memory_enabled, user_profile_enabled, provider |
| security | tirith_enabled, website_blocklist |
| delegation | model, provider, base_url, api_key, max_iterations (50), reasoning_effort |
| checkpoints | enabled, max_snapshots (50) |
| fallback_model | provider, model, base_url, key_env |
Fallback Providers
Hermes can automatically fail over to a backup provider:model when the primary is unavailable. This is turn-scoped โ each new user message starts with the primary restored; fallback only activates mid-turn when the primary fails.
Configuration ( ~/.hermes/config.yaml):
fallback_model:
provider: opencode-go
model: kimi-k2.6
Or use the interactive manager:
hermes fallback add # interactive picker
hermes fallback list # show fallback chain
hermes fallback remove # remove by index
Legacy note: fallback_model (singular) is the legacy single-fallback key. fallback_providers (list) supports multiple ordered fallbacks. When both exist, fallback_providers takes priority.
Trigger conditions (after exhausting retries where applicable):
- Rate limits (HTTP 429)
- Server errors (HTTP 500, 502, 503)
- Auth failures (HTTP 401, 403) โ immediately
- Not found (HTTP 404) โ immediately
- Invalid / empty responses repeatedly
Supported providers include all standard providers (OpenRouter, Anthropic, OpenCode Go/ Zen, Kimi, etc.) plus custom endpoints with base_url + key_env. Full provider docs: https://hermes-agent.nousresearch.com/docs/integrations/providers
Limitations:
- Subagent delegation does not inherit fallback config
- Cron jobs do not use fallback (use per-job provider/model overrides)
- Auxiliary tasks (vision, compression, etc.) use their own
auxiliary.* provider chain
For a deep-dive with worked examples and model lists, see references/fallback-providers.md.
Full config reference: https://hermes-agent.nousresearch.com/docs/user-guide/configuration
Providers
20+ providers supported. Set via hermes model or hermes setup.
| Provider | Auth | Key env var |
|----------|------|-------------|
| OpenRouter | API key | OPENROUTER_API_KEY |
| Anthropic | API key | ANTHROPIC_API_KEY |
| Nous Portal | OAuth | hermes auth |
| OpenAI Codex | OAuth | hermes auth |
| GitHub Copilot | Token | COPILOT_GITHUB_TOKEN |
| Google Gemini | API key | GOOGLE_API_KEY or GEMINI_API_KEY |
| DeepSeek | API key | DEEPSEEK_API_KEY |
| xAI / Grok | API key | XAI_API_KEY |
| Hugging Face | Token | HF_TOKEN |
| Z.AI / GLM | API key | GLM_API_KEY |
| MiniMax | API key | MINIMAX_API_KEY |
| MiniMax CN | API key | MINIMAX_CN_API_KEY |
| Kimi / Moonshot | API key | KIMI_API_KEY |
| Alibaba / DashScope | API key | DASHSCOPE_API_KEY |
| Xiaomi MiMo | API key | XIAOMI_API_KEY |
| Kilo Code | API key | KILOCODE_API_KEY |
| AI Gateway (Vercel) | API key | AI_GATEWAY_API_KEY |
| OpenCode Zen | API key | OPENCODE_ZEN_API_KEY |
| OpenCode Go | API key | OPENCODE_GO_API_KEY |
| Qwen OAuth | OAuth | hermes auth add qwen-oauth |
| Custom endpoint | Config | model.base_url + model.api_key in config.yaml |
| GitHub Copilot ACP | External | COPILOT_CLI_PATH or Copilot CLI |
Full provider docs: https://hermes-agent.nousresearch.com/docs/integrations/providers
Toolsets
Enable/disable via hermes tools (interactive) or hermes tools enable/disable NAME.
| Toolset | What it provides |
|---------|-----------------|
| web | Web search and content extraction |
| search | Web search only (subset of web) |
| browser | Browser automation (Browserbase, Camofox, or local Chromium) |
| terminal | Shell commands and process management |
| file | File read/write/search/patch |
| code_execution | Sandboxed Python execution |
| vision | Image analysis |
| image_gen | AI image generation |
| video | Video analysis and generation |
| tts | Text-to-speech |
| skills | Skill browsing and management |
| memory | Persistent cross-session memory |
| session_search | Search past conversations |
| delegation | Subagent task delegation |
| cronjob | Scheduled task management |
| clarify | Ask user clarifying questions |
| messaging | Cross-platform message sending |
| todo | In-session task planning and tracking |
| kanban | Multi-agent work-queue tools (gated to workers) |
| debugging | Extra introspection/debug tools (off by default) |
| safe | Minimal, low-risk toolset for locked-down sessions |
| spotify | Spotify playback and playlist control |
| homeassistant | Smart home control (off by default) |
| discord | Discord integration tools |
| discord_admin | Discord admin/moderation tools |
| feishu_doc | Feishu (Lark) document tools |
| feishu_drive | Feishu (Lark) drive tools |
| yuanbao | Yuanbao integration tools |
| rl | Reinforcement learning tools (off by default) |
| moa | Mixture of Agents (off by default) |
Full enumeration lives in toolsets.py as the TOOLSETS dict; _HERMES_CORE_TOOLS is the default bundle most platforms inherit from.
Tool changes take effect on /reset (new session). They do NOT apply mid-conversation to preserve prompt caching.
---
Security & Privacy Toggles
Common "why is Hermes doing X to my output / tool calls / commands?" toggles โ and the exact commands to change them. Most of these need a fresh session (/reset in chat, or start a new hermes invocation) because they're read once at startup.
Secret redaction in tool output
Secret redaction is off by default โ tool output (terminal stdout, read_file, web content, subagent summaries, etc.) passes through unmodified. If the user wants Hermes to auto-mask strings that look like API keys, tokens, and secrets before they enter the conversation context and logs:
hermes config set security.redact_secrets true # enable globally
Restart required. security.redact_secrets is snapshotted at import time โ toggling it mid-session (e.g. via export HERMES_REDACT_SECRETS=true from a tool call) will NOT take effect for the running process. Tell the user to run hermes config set security.redact_secrets true in a terminal, then start a new session. This is deliberate โ it prevents an LLM from flipping the toggle on itself mid-task.
Disable again with:
hermes config set security.redact_secrets false
PII redaction in gateway messages
Separate from secret redaction. When enabled, the gateway hashes user IDs and strips phone numbers from the session context before it reaches the model:
hermes config set privacy.redact_pii true # enable
hermes config set privacy.redact_pii false # disable (default)
Command approval prompts
By default (approvals.mode: manual), Hermes prompts the user before running shell commands flagged as destructive (rm -rf, git reset --hard, etc.). The modes are:
manual โ always prompt (default)
smart โ use an auxiliary LLM to auto-approve low-risk commands, prompt on high-risk
off โ skip all approval prompts (equivalent to --yolo)
hermes config set approvals.mode smart # recommended middle ground
hermes config set approvals.mode off # bypass everything (not recommended)
Per-invocation bypass without changing config:
hermes --yolo โฆ
export HERMES_YOLO_MODE=1
Note: YOLO / approvals.mode: off does NOT turn off secret redaction. They are independent.
Shell hooks allowlist
Some shell-hook integrations require explicit allowlisting before they fire. Managed via ~/.hermes/shell-hooks-allowlist.json โ prompted interactively the first time a hook wants to run.
Disabling the web/browser/image-gen tools
To keep the model away from network or media tools entirely, open hermes tools and toggle per-platform. Takes effect on next session (/reset). See the Tools & Skills section above.
---
Voice & Transcription
STT (Voice โ Text)
Voice messages from messaging platforms are auto-transcribed.
Provider priority (auto-detected):
1. Local faster-whisper โ free, no API key: pip install faster-whisper
2. Groq Whisper โ free tier: set GROQ_API_KEY
3. OpenAI Whisper โ paid: set VOICE_TOOLS_OPENAI_KEY
4. Mistral Voxtral โ set MISTRAL_API_KEY
Config:
stt:
enabled: true
provider: local # local, groq, openai, mistral
local:
model: base # tiny, base, small, medium, large-v3
TTS (Text โ Voice)
| Provider | Env var | Free? |
|----------|---------|-------|
| Edge TTS | None | Yes (default) |
| ElevenLabs | ELEVENLABS_API_KEY | Free tier |
| OpenAI | VOICE_TOOLS_OPENAI_KEY | Paid |
| MiniMax | MINIMAX_API_KEY | Paid |
| Mistral (Voxtral) | MISTRAL_API_KEY | Paid |
| NeuTTS (local) | None (pip install neutts[all] + espeak-ng) | Free |
Voice commands: /voice on (voice-to-voice), /voice tts (always voice), /voice off.
---
Spawning Additional Hermes Instances
Run additional Hermes processes as fully independent subprocesses โ separate sessions, tools, and environments.
When to Use This vs delegate_task
| | delegate_task | Spawning hermes process |
|-|-----------------|--------------------------|
| Isolation | Separate conversation, shared process | Fully independent process |
| Duration | Minutes (bounded by parent loop) | Hours/days |
| Tool access | Subset of parent's tools | Full tool access |
| Interactive | No | Yes (PTY mode) |
| Use case | Quick parallel subtasks | Long autonomous missions |
One-Shot Mode
terminal(command="hermes chat -q 'Research GRPO papers and write summary to ~/research/grpo.md'", timeout=300)
Background for long tasks:
terminal(command="hermes chat -q 'Set up CI/CD for ~/myapp'", background=true)
Interactive PTY Mode (via tmux)
Hermes uses prompt_toolkit, which requires a real terminal. Use tmux for interactive spawning:
Start
terminal(command="tmux new-session -d -s agent1 -x 120 -y 40 'hermes'", timeout=10)
Wait for startup, then send a message
terminal(command="sleep 8 && tmux send-keys -t agent1 'Build a FastAPI auth service' Enter", timeout=15)
Read output
terminal(command="sleep 20 && tmux capture-pane -t agent1 -p", timeout=5)
Send follow-up
terminal(command="tmux send-keys -t agent1 'Add rate limiting middleware' Enter", timeout=5)
Exit
terminal(command="tmux send-keys -t agent1 '/exit' Enter && sleep 2 && tmux kill-session -t agent1", timeout=10)
Multi-Agent Coordination
Agent A: backend
terminal(command="tmux new-session -d -s backend -x 120 -y 40 'hermes -w'", timeout=10)
terminal(command="sleep 8 && tmux send-keys -t backend 'Build REST API for user management' Enter", timeout=15)
Agent B: frontend
terminal(command="tmux new-session -d -s frontend -x 120 -y 40 'hermes -w'", timeout=10)
terminal(command="sleep 8 && tmux send-keys -t frontend 'Build React dashboard for user management' Enter", timeout=15)
Check progress, relay context between them
terminal(command="tmux capture-pane -t backend -p | tail -30", timeout=5)
terminal(command="tmux send-keys -t frontend 'Here is the API schema from the backend agent: ...' Enter", timeout=5)
Session Resume
Resume most recent session
terminal(command="tmux new-session -d -s resumed 'hermes --continue'", timeout=10)
Resume specific session
terminal(command="tmux new-session -d -s resumed 'hermes --resume 20260225_143052_a1b2c3'", timeout=10)
Tips
- Prefer
delegate_task for quick subtasks โ less overhead than spawning a full process
- Use
-w (worktree mode) when spawning agents that edit code โ prevents git conflicts
- Set timeouts for one-shot mode โ complex tasks can take 5-10 minutes
- Use
hermes chat -q for fire-and-forget โ no PTY needed
- Use tmux for interactive sessions โ raw PTY mode has
\r vs \n issues with prompt_toolkit
- For scheduled tasks, use the
cronjob tool instead of spawning โ handles delivery and retry
---
Durable & Background Systems
Four systems run alongside the main conversation loop. Quick reference
here; full developer notes live in AGENTS.md, user-facing docs under
website/docs/user-guide/features/.
Delegation (delegate_task)
Synchronous subagent spawn โ the parent waits for the child's summary
before continuing its own loop. Isolated context + terminal session.
- Single:
delegate_task(goal, context, toolsets).
- Batch:
delegate_task(tasks=[{goal, ...}, ...]) runs children in
parallel, capped by delegation.max_concurrent_children (default 3).
- Roles:
leaf (default; cannot re-delegate) vs orchestrator
(can spawn its own workers, bounded by delegation.max_spawn_depth).
- Not durable. If the parent is interrupted, the child is
cancelled. For work that must outlive the turn, use cronjob or
terminal(background=True, notify_on_complete=True).
Config: delegation.* in config.yaml.
Tuning max_concurrent_children
Default is 3. Rule of thumb for raising it:
- Light tasks (web search, file grep): up to
6-8
- Medium tasks (code execution, browser):
4-5
- Heavy tasks (builds, large data):
2-3
- Actual bottleneck is usually the API rate limit, not local CPU/RAM. On a 10-core M4 with 16GB RAM, CPU is rarely the constraint.
- Formula: start at
5, raise only if profiling shows idle time between API responses.
Cron (scheduled jobs)
Durable scheduler โ cron/jobs.py + cron/scheduler.py. Drive it via
the cronjob tool, the hermes cron CLI (list, add, edit,
pause, resume, run, remove), or the /cron slash command.
- Schedules: duration (
"30m", "2h"), "every" phrase
( "every monday 9am"), 5-field cron ( "0 9 *"), or ISO timestamp.
- Per-job knobs:
skills, model/provider override, script
(pre-run data collection; no_agent=True makes the script the whole
job), context_from (chain job A's output into job B), workdir
(run in a specific dir with its AGENTS.md / CLAUDE.md loaded),
multi-platform delivery.
- Invariants: 3-minute hard interrupt per run,
.tick.lock file
prevents duplicate ticks across processes, cron sessions pass
skip_memory=True by default, and cron deliveries are framed with a
header/footer instead of being mirrored into the target gateway
session (keeps role alternation intact).
User docs: https://hermes-agent.nousresearch.com/docs/user-guide/features/cron
Curator (skill lifecycle)
Background maintenance for agent-created skills. Tracks usage, marks
idle skills stale, archives stale ones, keeps a pre-run tar.gz backup
so nothing is lost.
- CLI:
hermes curator <verb> โ status, run, pause, resume,
pin, unpin, archive, restore, prune, backup, rollback.
- Slash:
/curator <subcommand> mirrors the CLI.
- Scope: only touches skills with
created_by: "agent" provenance.
Bundled + hub-installed skills are off-limits. Never deletes โ
max destructive action is archive. Pinned skills are exempt from
every auto-transition and every LLM review pass.
- Telemetry: sidecar at
~/.hermes/skills/.usage.json holds
per-skill use_count, view_count, patch_count,
last_activity_at, state, pinned.
Config: curator.* (enabled, interval_hours, min_idle_hours,
stale_after_days, archive_after_days, backup.*).
User docs: https://hermes-agent.nousresearch.com/docs/user-guide/features/curator
Dreaming (periodic memory/skill consolidation)
For Anthropic-style "dreaming" workflows, combine cron + session_search + memory + skills + curator into a scheduled review loop. Start with a weekly, proposal-only report that audits recent sessions, repeated user corrections, memory conflicts, skill patch candidates, and cron/automation improvements. Do not automatically delete/replace memory or patch/archive skills unless the user explicitly approves the proposed changes. See references/weekly-dreaming-routine.md for the recommended prompt, report format, safety policy, and cron creation pattern.
Kanban (multi-agent work queue)
Durable SQLite board for multi-profile / multi-worker collaboration.
Users drive it via hermes kanban <verb>; dispatcher-spawned workers
see a focused kanban_* toolset gated by HERMES_KANBAN_TASK so the
schema footprint is zero outside worker processes.
- CLI verbs (common):
init, create, list (alias ls),
show, assign, link, unlink, comment, complete, block,
unblock, archive, tail. Less common: watch, stats, runs,
log, dispatch, daemon, gc.
- Worker toolset:
kanban_show, kanban_complete, kanban_block,
kanban_heartbeat, kanban_comment, kanban_create, kanban_link.
- Dispatcher runs inside the gateway by default
( kanban.dispatch_in_gateway: true) โ reclaims stale claims,
promotes ready tasks, atomically claims, spawns assigned profiles.
Auto-blocks a task after ~5 consecutive spawn failures.
- Isolation: board is the hard boundary (workers get
HERMES_KANBAN_BOARD pinned in env); tenant is a soft namespace
within a board for workspace-path + memory-key isolation.
User docs: https://hermes-agent.nousresearch.com/docs/user-guide/features/kanban
Log Relay (Hermes โ Discord)
A background Python script that tails ~/.hermes/logs/*.log and batches lines to a Discord channel. Includes session-ID extraction, rate-limit handling, and auto-restart via launchd/systemd. Useful for remote monitoring and audit trails.
- Reference:
references/discord-log-relay.md โ full setup, tuning, macOS/Linux service install, pitfalls.
- Template:
templates/discord-log-relay.py โ copy, set CHANNEL_ID, and deploy.
- Discord operations:
references/discord-operating-planes.md โ channel-purpose routing, periodic-summary vs Dreaming report formats, and safety/cost notes for Discord-first Hermes deployments.
Key pitfall: ask the user about batch frequency upfront rather than defaulting to real-time streaming. Most users prefer 10-minute or hourly batches. High-volume raw logs should be batched, summarized, or stored out-of-band; avoid Discord message storms during error loops.
Weekly Dreaming / Memory Curation
For long-running Hermes deployments, users may want an Anthropic-style "Dreaming" loop: a scheduled review that consolidates experience, proposes memory/skill/cron changes, and identifies what to keep, weaken, archive, or delete. Hermes has the building blocks (sessions, session_search, memory, skills, curator, cron), but the safe default is proposal mode:
1. Inspect recent usage and sessions.
2. Extract repeated success patterns, failure patterns, and user corrections.
3. Propose memory updates/removals without applying them silently.
4. Propose skill patches/archive candidates and cron/reporting improvements.
5. End with explicit approval checkboxes.
Do not silently rewrite or delete memory/skills from a Dreaming report unless the user explicitly authorized automatic application. See references/discord-operating-planes.md for a report template and routing heuristics.
---
Windows-Specific Quirks
Hermes runs natively on Windows (PowerShell, cmd, Windows Terminal, git-bash
mintty, VS Code integrated terminal). Most of it just works, but a handful
of differences between Win32 and POSIX have bitten us โ document new ones
here as you hit them so the next person (or the next session) doesn't
rediscover them from scratch.
Input / Keybindings
Alt+Enter doesn't insert a newline. Windows Terminal intercepts Alt+Enter
at the terminal layer to toggle fullscreen โ the keystroke never reaches
prompt_toolkit. Use Ctrl+Enter instead. Windows Terminal delivers
Ctrl+Enter as LF ( c-j), distinct from plain Enter ( c-m / CR), and the
CLI binds c-j to newline insertion on win32 only (see
_bind_prompt_submit_keys + the Windows-only c-j binding in cli.py).
Side effect: the raw Ctrl+J keystroke also inserts a newline on Windows โ
unavoidable, because Windows Terminal collapses Ctrl+Enter and Ctrl+J to
the same keycode at the Win32 console API layer. No conflicting binding
existed for Ctrl+J on Windows, so this is a harmless side effect.
mintty / git-bash behaves the same (fullscreen on Alt+Enter) unless you
disable Alt+Fn shortcuts in Options โ Keys. Easier to just use Ctrl+Enter.
Diagnosing keybindings. Run python scripts/keystroke_diagnostic.py
(repo root) to see exactly how prompt_toolkit identifies each keystroke
in the current terminal. Answers questions like "does Shift+Enter come
through as a distinct key?" (almost never โ most terminals collapse it
to plain Enter) or "what byte sequence is my terminal sending for
Ctrl+Enter?" This is how the Ctrl+Enter = c-j fact was established.
Config / Files
HTTP 400 "No models provided" on first run. config.yaml was saved
with a UTF-8 BOM (common when Windows apps write it). Re-save as UTF-8
without BOM. hermes config edit writes without BOM; manual edits in
Notepad are the usual culprit.
execute_code / Sandbox
WinError 10106 ("The requested service provider could not be loaded
or initialized") from the sandbox child process โ it can't create an
AF_INET socket, so the loopback-TCP RPC fallback fails before
connect(). Root cause is usually not a broken Winsock LSP; it's
Hermes's own env scrubber dropping SYSTEMROOT / WINDIR / COMSPEC
from the child env. Python's socket module needs SYSTEMROOT to locate
mswsock.dll. Fixed via the _WINDOWS_ESSENTIAL_ENV_VARS allowlist in
tools/code_execution_tool.py. If you still hit it, echo os.environ
inside an execute_code block to confirm SYSTEMROOT is set. Full
diagnostic recipe in references/execute-code-sandbox-env-windows.md.
Testing / Contributing
scripts/run_tests.sh doesn't work as-is on Windows โ it looks for
POSIX venv layouts ( .venv/bin/activate). The Hermes-installed venv at
venv/Scripts/ has no pip or pytest either (stripped for install size).
Workaround: install pytest + pytest-xdist + pyyaml into a system Python
3.11 user site, then invoke pytest directly with PYTHONPATH set:
"/c/Program Files/Python311/python" -m pip install --user pytest pytest-xdist pyyaml
export PYTHONPATH="$(pwd)"
"/c/Program Files/Python311/python" -m pytest tests/foo/test_bar.py -v --tb=short -n 0
Use -n 0, not -n 4 โ pyproject.toml's default addopts already
includes -n, and the wrapper's CI-parity guarantees don't apply off POSIX.
POSIX-only tests need skip guards. Common markers already in the codebase:
- Symlinks โ elevated privileges on Windows
0o600 file modes โ POSIX mode bits not enforced on NTFS by default
signal.SIGALRM โ Unix-only (see tests/conftest.py::_enforce_test_timeout)
- Winsock / Windows-specific regressions โ
@pytest.mark.skipif(sys.platform != "win32", ...)
Use the existing skip-pattern style (sys.platform == "win32" or
sys.platform.startswith("win")) to stay consistent with the rest of the
suite.
Path / Filesystem
Line endings. Git may warn LF will be replaced by CRLF the next time
Git touches it. Cosmetic โ the repo's .gitattributes normalizes. Don't
let editors auto-convert committed POSIX-newline files to CRLF.
Forward slashes work almost everywhere. C:/Users/... is accepted by
every Hermes tool and most Windows APIs. Prefer forward slashes in code
and logs โ avoids shell-escaping backslashes in bash.
---
Troubleshooting
Voice not working
1. Check stt.enabled: true in config.yaml
2. Verify provider: pip install faster-whisper or set API key
3. In gateway: /restart. In CLI: exit and relaunch.
Tool not available
1. hermes tools โ check if toolset is enabled for your platform
2. Some tools need env vars (check .env)
3. /reset after enabling tools
Model/provider issues
1. hermes doctor โ check config and dependencies
2. hermes auth add <provider> โ re-authenticate OAuth providers (use --type oauth)
3. Check .env has the right API key
4. Copilot 403: gh auth login tokens do NOT work for Copilot API. You must use the Copilot-specific OAuth device code flow via hermes model โ GitHub Copilot.
Changes not taking effect
- Tools/skills:
/reset starts a new session with updated toolset
- Config changes: In gateway:
/restart. In CLI: exit and relaunch.
- Code changes: Restart the CLI or gateway process
Deployed web dashboard shows stale CSS or theme changes
- Browser cache: Add
?v=N cache-busting query strings to CSS/JS/theme links in HTML.
- Service Worker cache: Bump
CACHE_NAME in sw.js to invalidate old shell caches.
- Data freshness: Use
fetch(url, {cache:'no-store'}) for live JSON feeds.
- See
references/static-site-cache-invalidation.md for the full diagnostic recipe.
Dashboard inspector feels too technical
- The default inspector view should contain only plain-language sentences: headline, "what they're doing now", "why it matters", and a silent visual progress bar (no text label).
- Move all technical fields (source IDs, confidence scores, progress labels, status slugs, badges) behind a "Show technical details" toggle.
- If users say "details are hard to understand," the fix is to remove more fields from the default view, not to add explanations. Explanations of technical fields are still technical.
- See
references/progressive-disclosure-human-first.md for the aggressive simplification pattern.
Skills not showing
1. hermes skills list โ verify installed
2. hermes skills config โ check platform enablement
3. Load explicitly: /skill name or hermes -s name
Gateway issues
Check logs first:
grep -i "failed to send\|error" ~/.hermes/logs/gateway.log | tail -20
Common gateway problems:
- Gateway dies on SSH logout: Enable linger:
sudo loginctl enable-linger $USER
- Gateway dies on WSL2 close: WSL2 requires
systemd=true in /etc/wsl.conf for systemd services to work. Without it, gateway falls back to nohup (dies when session closes).
- Gateway crash loop: Reset the failed state:
systemctl --user reset-failed hermes-gateway
- macOS: bot shows offline after idle time: The gateway runs as a user agent (
LimitLoadToSessionType=Aqua), so macOS suspends it when the system sleeps. The platform websocket drops and the bot appears offline until the network returns. Fix: keep the Mac awake (System Settings -> Energy -> Prevent automatic sleeping, or caffeinate -d -i -s -u &). Low Power Mode makes this worse, not better. See references/macos-gateway-sleep-disconnect.md for the full diagnostic recipe.
Platform-specific issues
- Discord bot silent: Must enable Message Content Intent in Bot โ Privileged Gateway Intents. See full Discord setup reference:
references/discord-gateway-setup.md.
- Slack bot only works in DMs: Must subscribe to
message.channels event. Without it, the bot ignores public channels.
- Windows-specific issues (
Alt+Enter newline, WinError 10106, UTF-8 BOM config, test suite, line endings): see the dedicated Windows-Specific Quirks section above.
Auxiliary models not working
If auxiliary tasks (vision, compression, session_search) fail silently, the auto provider can't find a backend. Either set OPENROUTER_API_KEY or GOOGLE_API_KEY, or explicitly configure each auxiliary task's provider:
hermes config set auxiliary.vision.provider <your_provider>
hermes config set auxiliary.vision.model <model_name>
Full system auth provisioning
For a one-shot workflow to maximize available credentials โ installing gh, generating SSH keys, configuring git, enabling all Hermes toolsets, and auditing current auth state โ see references/system-auth-setup.md.
Editing large files with patch
When a file is read with read_file(offset=...) (pagination), the tool warns that the view is partial. If you attempt patch without re-reading the full file first, you will likely hit non-unique match errors or corrupt the file. Fix: always call read_file without offset to load the whole file before patching. For append-only updates (e.g., adding a cycle log entry to state.md), do not use terminal(command="cat >> file << 'EOF'...EOF") โ the terminal tool on macOS/Linux misinterprets heredoc << as backgrounding and fails. Instead, write a short Python script via write_file and execute it with terminal(command="python3 /tmp/script.py"). See references/terminal-heredoc-workaround.md for the full pattern.
---
Windows-Specific Quirks
| Looking for... | Location |
|----------------|----------|
| Config options | hermes config edit or [Configuration docs](https://hermes-agent.nousresearch.com/docs/user-guide/configuration) |
| Available tools | hermes tools list or [Tools reference](https://hermes-agent.nousresearch.com/docs/reference/tools-reference) |
| Slash commands | /help in session or [Slash commands reference](https://hermes-agent.nousresearch.com/docs/reference/slash-commands) |
| Skills catalog | hermes skills browse or [Skills catalog](https://hermes-agent.nousresearch.com/docs/reference/skills-catalog) |
| Provider setup | hermes model or [Providers guide](https://hermes-agent.nousresearch.com/docs/integrations/providers) |
| Platform setup | hermes gateway setup or [Messaging docs](https://hermes-agent.nousresearch.com/docs/user-guide/messaging/) |
| MCP servers | hermes mcp list or [MCP guide](https://hermes-agent.nousresearch.com/docs/user-guide/features/mcp) |
| Profiles | hermes profile list or [Profiles docs](https://hermes-agent.nousresearch.com/docs/user-guide/profiles) |
| Cron jobs | hermes cron list or [Cron docs](https://hermes-agent.nousresearch.com/docs/user-guide/features/cron) |
| Memory | hermes memory status or [Memory docs](https://hermes-agent.nousresearch.com/docs/user-guide/features/memory) |
| Env variables | hermes config env-path or [Env vars reference](https://hermes-agent.nousresearch.com/docs/reference/environment-variables) |
| CLI commands | hermes --help or [CLI reference](https://hermes-agent.nousresearch.com/docs/reference/cli-commands) |
| Gateway logs | ~/.hermes/logs/gateway.log |
| Session files | ~/.hermes/sessions/ or hermes sessions browse |
| Source code | ~/.hermes/hermes-agent/ |
---
Contributor Quick Reference
For occasional contributors and PR authors. Full developer docs: https://hermes-agent.nousresearch.com/docs/developer-guide/
Project Layout
hermes-agent/
โโโ run_agent.py # AIAgent โ core conversation loop
โโโ model_tools.py # Tool discovery and dispatch
โโโ toolsets.py # Toolset definitions
โโโ cli.py # Interactive CLI (HermesCLI)
โโโ hermes_state.py # SQLite session store
โโโ agent/ # Prompt builder, context compression, memory, model routing, credential pooling, skill dispatch
โโโ hermes_cli/ # CLI subcommands, config, setup, commands
โ โโโ commands.py # Slash command registry (CommandDef)
โ โโโ config.py # DEFAULT_CONFIG, env var definitions
โ โโโ main.py # CLI entry point and argparse
โโโ tools/ # One file per tool
โ โโโ registry.py # Central tool registry
โโโ gateway/ # Messaging gateway
โ โโโ platforms/ # Platform adapters (telegram, discord, etc.)
โโโ cron/ # Job scheduler
โโโ tests/ # ~3000 pytest tests
โโโ website/ # Docusaurus docs site
Config: ~/.hermes/config.yaml (settings), ~/.hermes/.env (API keys).
Adding a Tool (3 files)
1. Create tools/your_tool.py:
import json, os
from tools.registry import registry
def check_requirements() -> bool:
return bool(os.getenv("EXAMPLE_API_KEY"))
def example_tool(param: str, task_id: str = None) -> str:
return json.dumps({"success": True, "data": "..."})
registry.register(
name="example_tool",
toolset="example",
schema={"name": "example_tool", "description": "...", "parameters": {...}},
handler=lambda args, **kw: example_tool(
param=args.get("param", ""), task_id=kw.get("task_id")),
check_fn=check_requirements,
requires_env=["EXAMPLE_API_KEY"],
)
2. Add to toolsets.py โ _HERMES_CORE_TOOLS list.
Auto-discovery: any tools/*.py file with a top-level registry.register() call is imported automatically โ no manual list needed.
All handlers must return JSON strings. Use get_hermes_home() for paths, never hardcode ~/.hermes.
Adding a Slash Command
1. Add CommandDef to COMMAND_REGISTRY in hermes_cli/commands.py
2. Add handler in cli.py โ process_command()
3. (Optional) Add gateway handler in gateway/run.py
All consumers (help text, autocomplete, Telegram menu, Slack mapping) derive from the central registry automatically.
Agent Loop (High Level)
run_conversation():
1. Build system prompt
2. Loop while iterations < max:
a. Call LLM (OpenAI-format messages + tool schemas)
b. If tool_calls โ dispatch each via handle_function_call() โ append results โ continue
c. If text response โ return
3. Context compression triggers automatically near token limit
Testing
python -m pytest tests/ -o 'addopts=' -q # Full suite
python -m pytest tests/tools/ -q # Specific area
- Tests auto-redirect
HERMES_HOME to temp dirs โ never touch real ~/.hermes/
- Run full suite before pushing any change
- Use
-o 'addopts=' to clear any baked-in pytest flags
Windows contributors: scripts/run_tests.sh currently looks for POSIX venvs ( .venv/bin/activate / venv/bin/activate) and will error out on Windows where the layout is venv/Scripts/activate + python.exe. The Hermes-installed venv at venv/Scripts/ also has no pip or pytest โ it's stripped for end-user install size. Workaround: install pytest + pytest-xdist + pyyaml into a system Python 3.11 user site ( /c/Program Files/Python311/python -m pip install --user pytest pytest-xdist pyyaml), then run tests directly:
export PYTHONPATH="$(pwd)"
"/c/Program Files/Python311/python" -m pytest tests/tools/test_foo.py -v --tb=short -n 0
Use -n 0 (not -n 4) because pyproject.toml's default addopts already includes -n, and the wrapper's CI-parity story doesn't apply off-POSIX.
Cross-platform test guards: tests that use POSIX-only syscalls need a skip marker. Common ones already in the codebase:
- Symlink creation โ
@pytest.mark.skipif(sys.platform == "win32", reason="Symlinks require elevated privileges on Windows") (see tests/cron/test_cron_script.py)
- POSIX file modes (0o600, etc.) โ
@pytest.mark.skipif(sys.platform.startswith("win"), reason="POSIX mode bits not enforced on Windows") (see tests/hermes_cli/test_auth_toctou_file_modes.py)
signal.SIGALRM โ Unix-only (see tests/conftest.py::_enforce_test_timeout)
- Live Winsock / Windows-specific regression tests โ
@pytest.mark.skipif(sys.platform != "win32", reason="Windows-specific regression")
Monkeypatching sys.platform is not enough when the code under test also calls platform.system() / platform.release() / platform.mac_ver(). Those functions re-read the real OS independently, so a test that sets sys.platform = "linux" on a Windows runner will still see platform.system() == "Windows" and route through the Windows branch. Patch all three together:
monkeypatch.setattr(sys, "platform", "linux")
monkeypatch.setattr(platform, "system", lambda: "Linux")
monkeypatch.setattr(platform, "release", lambda: "6.8.0-generic")
See tests/agent/test_prompt_builder.py::TestEnvironmentHints for a worked example.
Extending the system prompt's execution-environment block
Factual guidance about the host OS, user home, cwd, terminal backend, and shell (bash vs. PowerShell on Windows) is emitted from agent/prompt_builder.py::build_environment_hints(). This is also where the WSL hint and per-backend probe logic live. The convention:
- Local terminal backend โ emit host info (OS,
$HOME, cwd) + Windows-specific notes (hostname โ username, terminal uses bash not PowerShell).
- Remote terminal backend (anything in
_REMOTE_TERMINAL_BACKENDS: docker, singularity, modal, daytona, ssh, vercel_sandbox, managed_modal) โ suppress host info entirely and describe only the backend. A live uname/whoami/pwd probe runs inside the backend via tools.environments.get_environment(...).execute(...), cached per process in _BACKEND_PROBE_CACHE, with a static fallback if the probe times out.
- Key fact for prompt authoring: when
TERMINAL_ENV != "local", every file tool (read_file, write_file, patch, search_files) runs inside the backend container, not on the host. The system prompt must never describe the host in that case โ the agent can't touch it.
Full design notes, the exact emitted strings, and testing pitfalls:
references/prompt-builder-environment-hints.md.
Refactor-safety pattern (POSIX-equivalence guard): when you extract inline logic into a helper that adds Windows/platform-specific behavior, keep a _legacy_<name> oracle function in the test file that's a verbatim copy of the old code, then parametrize-diff against it. Example: tests/tools/test_code_execution_windows_env.py::TestPosixEquivalence. This locks in the invariant that POSIX behavior is bit-for-bit identical and makes any future drift fail loudly with a clear diff.
Commit Conventions
type: concise subject line
Optional body.
Types: fix:, feat:, refactor:, docs:, chore:
Key Rules
- Never break prompt caching โ don't change context, tools, or system prompt mid-conversation
- Message role alternation โ never two assistant or two user messages in a row
- Use
get_hermes_home() from hermes_constants for all paths (profile-safe)
- Config values go in
config.yaml, secrets go in .env
- New tools need a
check_fn so they only appear when requirements are met
[IMPORTANT: The user has invoked the "kanban-orchestrator" skill, indicating they want you to follow its instructions. The full skill content is loaded below.]
---
name: kanban-orchestrator
description: Decomposition playbook + anti-temptation rules for an orchestrator profile routing work through Kanban. The "don't do the work yourself" rule and the basic lifecycle are auto-injected into every kanban worker's system prompt; this skill is the deeper playbook when you're specifically playing the orchestrator role.
version: 3.0.0
platforms: [linux, macos, windows]
metadata:
hermes:
tags: [kanban, multi-agent, orchestration, routing]
related_skills: [kanban-worker]
---
Kanban Orchestrator โ Decomposition Playbook
> The core worker lifecycle (including the kanban_create fan-out pattern and the "decompose, don't execute" rule) is auto-injected into every kanban process via the KANBAN_GUIDANCE system-prompt block. This skill is the deeper playbook when you're an orchestrator profile whose whole job is routing.
Profiles are user-configured โ not a fixed roster
Hermes setups vary widely. Some users run a single profile that does everything; some run a small fleet (docker-worker, cron-worker); some run a curated specialist team they've named themselves. There is no default specialist roster โ the orchestrator skill does not know what profiles exist on this machine.
Before fanning out, you must ground the decomposition in the profiles that actually exist. The dispatcher silently fails to spawn unknown assignee names โ it doesn't autocorrect, doesn't suggest, doesn't fall back. So a card assigned to researcher on a setup that only has docker-worker just sits in ready forever.
Step 0: discover available profiles before planning.
Use one of these:
hermes profile list โ prints the table of profiles configured on this machine. Run it through your terminal tool if you have one; otherwise ask the user.
kanban_list(assignee="<some-name>") โ sanity-check a single name. Returns an empty list (rather than an error) for an unknown assignee, so this only confirms a name you're already considering.
- Just ask the user. "What profiles do you have set up?" is a fine first turn when the goal needs more than one specialist.
Cache the result in your working memory for the rest of the conversation. Re-asking every turn wastes a tool call.
When to use the board (vs. just doing the work)
Create Kanban tasks when any of these are true:
1. Multiple specialists are needed. Research + analysis + writing is three profiles.
2. The work should survive a crash or restart. Long-running, recurring, or important.
3. The user might want to interject. Human-in-the-loop at any step.
4. Multiple subtasks can run in parallel. Fan-out for speed.
5. Review / iteration is expected. A reviewer profile loops on drafter output.
6. The audit trail matters. Board rows persist in SQLite forever.
If none of those apply โ it's a small one-shot reasoning task โ use delegate_task instead or answer the user directly.
The anti-temptation rules
Your job description says "route, don't execute." The rules that enforce that:
- Do not execute the work yourself. Your restricted toolset usually doesn't even include terminal/file/code/web for implementation. If you find yourself "just fixing this quickly" โ stop and create a task for the right specialist.
- For any concrete task, create a Kanban task and assign it. Every single time.
- Split multi-lane requests before creating cards. A user prompt can contain several independent workstreams. Extract those lanes first, then create one card per lane instead of bundling unrelated work into a single implementer card.
- Run independent lanes in parallel. If two cards do not need each other's output, leave them unlinked so the dispatcher can fan them out. Link only true data dependencies.
- If no specialist fits the available profiles, ask the user which profile to create or which existing profile to use. Do not invent profile names; the dispatcher will silently drop unknown assignees.
- Decompose, route, and summarize โ that's the whole job.
Exception: micro-UI polish cycles
There is one narrow exception where the orchestrator may execute directly instead of creating Kanban cards: tiny UI-only polish cycles (e.g., adding a CSS class, a theme preview dot, a hover state, a cross-link, or a HUD button) that are purely presentational, require no cross-file logic changes, and fit comfortably inside a single bounded cycle with no need for review or parallel work. If the change is limited to HTML/CSS/JS cosmetics, no other profile has a stake in it, and the user did not ask for a design review, the orchestrator should just edit and publish rather than paying the kanban-overhead tax. This exception does NOT apply to architecture changes, adapter logic, plugin interfaces, or anything that touches the data layer.
Decomposition playbook
Step 1 โ Understand the goal
Ask clarifying questions if the goal is ambiguous. Cheap to ask; expensive to spawn the wrong fleet.
Step 2 โ Sketch the task graph
Before creating anything, draft the graph out loud (in your response to the user). Treat every concrete workstream as a candidate card:
1. Extract the lanes from the request.
2. Map each lane to one of the profiles you discovered in Step 0. If a lane doesn't fit any existing profile, ask the user which to use or create.
3. Decide whether each lane is independent or gated by another lane.
4. Create independent lanes as parallel cards with no parent links.
5. Create synthesis/review/integration cards with parent links to the lanes they depend on.
Examples of prompts that should fan out (using placeholder profile names โ substitute whatever exists on the user's setup):
- "Build an app" โ one card to a design-oriented profile for product/UI direction, one or two cards to engineering profiles for implementation, plus a later integration/review card if the user has a reviewer profile.
- "Fix blockers and check model variants" โ one implementation card for the blocker fixes plus one discovery/research card for config/source verification. A final reviewer card can depend on both.
- "Research docs and implement" โ a docs-research card can run in parallel with a codebase-discovery card; implementation waits only if it truly needs those findings.
- "Analyze this screenshot and find the related code" โ one card to a vision-capable profile for the visual analysis while another searches the codebase.
Words like "also," "finally," or "and" do not automatically imply a dependency. They often mean "make sure this is covered before reporting back." Only link tasks when one card cannot start until another card's output exists.
Show the graph to the user before creating cards. Let them correct it โ including which actual profile name should own each lane.
Step 3 โ Create tasks and link
Use the profile names from Step 0. The example below uses placeholders <profile-A>, <profile-B>, <profile-C> โ replace them with what the user actually has.
t1 = kanban_create(
title="research: Postgres cost vs current",
assignee="<profile-A>", # whichever profile handles research on this setup
body="Compare estimated infrastructure costs, migration costs, and ongoing ops costs over a 3-year window. Sources: AWS/GCP pricing, team time estimates, current Postgres bills from peers.",
tenant=os.environ.get("HERMES_TENANT"),
)["task_id"]
t2 = kanban_create(
title="research: Postgres performance vs current",
assignee="<profile-A>", # same profile, run in parallel
body="Compare query latency, throughput, and scaling characteristics at our expected data volume (~500GB, 10k QPS peak). Sources: benchmark papers, public case studies, pgbench results if easy.",
)["task_id"]
t3 = kanban_create(
title="synthesize migration recommendation",
assignee="<profile-B>", # whichever profile does synthesis/analysis
body="Read the findings from T1 (cost) and T2 (performance). Produce a 1-page recommendation with explicit trade-offs and a go/no-go call.",
parents=[t1, t2],
)["task_id"]
t4 = kanban_create(
title="draft decision memo",
assignee="<profile-C>", # whichever profile drafts user-facing prose
body="Turn the analyst's recommendation into a 2-page memo for the CTO. Match the tone of previous decision memos in the team's knowledge base.",
parents=[t3],
)["task_id"]
parents=[...] gates promotion โ children stay in todo until every parent reaches done, then auto-promote to ready. No manual coordination needed; the dispatcher and dependency engine handle it.
Step 4 โ Complete your own task
If you were spawned as a task yourself (e.g. a planner profile was assigned T0: "investigate Postgres migration"), mark it done with a summary of what you created:
kanban_complete(
summary="decomposed into T1-T4: 2 research lanes in parallel, 1 synthesis on their outputs, 1 prose draft on the recommendation",
metadata={
"task_graph": {
"T1": {"assignee": "<profile-A>", "parents": []},
"T2": {"assignee": "<profile-A>", "parents": []},
"T3": {"assignee": "<profile-B>", "parents": ["T1", "T2"]},
"T4": {"assignee": "<profile-C>", "parents": ["T3"]},
},
},
)
Step 5 โ Report back to the user
Tell them what you created in plain prose, naming the actual profiles you used:
> I've queued 4 tasks:
> - T1 (<profile-A>): cost comparison
> - T2 (<profile-A>): performance comparison, in parallel with T1
> - T3 (<profile-B>): synthesizes T1 + T2 into a recommendation
> - T4 (<profile-C>): turns T3 into a CTO memo
>
> The dispatcher will pick up T1 and T2 now. T3 starts when both finish. You'll get a gateway ping when T4 completes. Use the dashboard or hermes kanban tail <id> to follow along.
Common patterns
Fan-out + fan-in (research โ synthesize): N research-style cards with no parents, one synthesis card with all of them as parents.
Parallel implementation + validation: one implementer card makes the change while one explorer/researcher card verifies config, docs, or source mapping. A reviewer card can depend on both. Do not make the implementer own unrelated verification just because the user mentioned both in one sentence.
Pipeline with gates: planner โ implementer โ reviewer. Each stage's parents=[previous_task]. Reviewer blocks or completes; if reviewer blocks, the operator unblocks with feedback and respawns.
Same-profile queue: N tasks, all assigned to the same profile, no dependencies between them. Dispatcher serializes โ that profile processes them in priority order, accumulating experience in its own memory.
Parallel UI/frontend lanes: When the goal touches multiple independent HTML/CSS/JS files (e.g., a dashboard page and a 2D gather view), fan out to separate subagents per file. Each lane edits its own file, then the orchestrator integrates, fixes cross-file references (theme paths, shared JSON endpoints), and publishes. This avoids merge conflicts in single-file HTML dashboards and keeps each subagent's context focused. See references/parallel-ui-lanes-and-publishing.md for the post-subagent integration checklist and rsync safety notes.
Human-in-the-loop: Any task can kanban_block() to wait for input. Dispatcher respawns after /unblock. The comment thread carries the full context.
Pitfalls
Inventing profile names that don't exist. The dispatcher silently fails to spawn unknown assignees โ the card just sits in ready forever. Always assign to a profile from your Step 0 discovery; ask the user if you're unsure.
Bundling independent lanes into one card. If the user asks for two independent outcomes, create two cards. Example: "fix blockers and check model variants" is not one fixer task; create a fixer/engineer card for the fixes and an explorer/researcher card for the variant check, then optionally gate review on both.
Over-linking because of wording. "Finally check X" may still be parallel with implementation if X is static config, docs, or source discovery. Link it after implementation only when the check depends on the implementation result.
Forgetting dependency links. If the task graph says research -> implement -> review, do not create all tasks as independent ready cards. Use parent links so implement/review cannot run before their inputs exist.
Reassignment vs. new task. If a reviewer blocks with "needs changes," create a NEW task linked from the reviewer's task โ don't re-run the same task with a stern look. The new task is assigned to the original implementer profile.
Argument order for links. kanban_link(parent_id=..., child_id=...) โ parent first. Mixing them up demotes the wrong task to todo.
Ignoring explicit user feedback to keep building infrastructure. When the user says a specific UX issue (legibility, theme switching, movement density) is "immediate priority," treat it as P0 and route it before deeper packaging/architecture work. Infrastructure polish feels productive, but shipping user-visible fixes is what matters. Create cards for the UX feedback first, then resume infrastructure lanes.
Treating status: complete as immutable when user feedback says otherwise. A state.md that says status: complete does not override a user's report that a completion criterion is actually broken. If the user says "theme switching is not working" and the Final Completion Condition requires "working UI theme switcher," the mission is not complete. Reactivate immediately: set status: active, append a reactivation cycle log, and fix the issue. Do not burn cycles on post-complete verification while the user is reporting active defects.
Don't pre-create the whole graph if the shape depends on intermediate findings. If T3's structure depends on what T1 and T2 find, let T3 exist as a "synthesize findings" task whose own first step is to read parent handoffs and plan the rest. Orchestrators can spawn orchestrators.
Tenant inheritance. If HERMES_TENANT is set in your env, pass tenant=os.environ.get("HERMES_TENANT") on every kanban_create call so child tasks stay in the same namespace.
Verifying cross-file references after directory reorganization. When subagents edit HTML/CSS/JS files and the directory structure shifts (e.g., moving files from root into web/dashboard/ and web/gather/), relative asset paths ( themes/default/theme.css, ./ops-data.json) often break. After subagents finish, the orchestrator must grep for href= and src= in moved files and fix relative paths before publishing. Subagents don't know the final publish layout โ the orchestrator does.
Destructive sync wipes needed files. Commands like rsync -av --delete will delete destination files that aren't in the source list. If you publish a directory tree piecemeal (e.g., copy web/dashboard/ first, then web/gather/ separately), --delete on the first rsync will erase the gather files before the second rsync runs. Either list all source paths in a single rsync invocation, or omit --delete and use cp -r / rsync -av without deletion when doing staged copies.
Recovering stuck workers
When a worker profile keeps crashing, hallucinating, or getting blocked by its own mistakes (usually: wrong model, missing skill, broken credential), the kanban dashboard flags the task with a โ badge and opens a Recovery section in the drawer. Three primary actions:
1. Reclaim (or hermes kanban reclaim <task_id>) โ abort the running worker immediately and reset the task to ready. The existing claim TTL is ~15 min; this is the fast path out.
2. Reassign (or hermes kanban reassign <task_id> <new-profile> --reclaim) โ switch the task to a different profile (one that exists on this setup) and let the dispatcher pick it up with a fresh worker.
3. Change profile model โ the dashboard prints a copy-paste hint for hermes -p <profile> model since profile config lives on disk; edit it in a terminal, then Reclaim to retry with the new model.
Hallucination warnings appear on tasks where a worker's kanban_complete(created_cards=[...]) claim included card ids that don't exist or weren't created by the worker's profile (the gate blocks the completion), or where the free-form summary references t_<hex> ids that don't resolve (advisory prose scan, non-blocking). Both produce audit events that persist even after recovery actions โ the trail stays for debugging.
The user has provided the following instruction alongside the skill invocation: [IMPORTANT: You are running as a scheduled cron job. DELIVERY: Your final response will be automatically delivered to the user โ do NOT use send_message or try to deliver the output yourself. Just produce your report/output as your final response and the system handles the rest. SILENT: If there is genuinely nothing new to report, respond with exactly "[SILENT]" (nothing else) to suppress delivery. Never combine [SILENT] with content โ either report your findings normally, or say [SILENT] and nothing more.]
You are the 15-minute Orchestrator for Son's Autonomous Agent Lab v1, reporting to Discord channel ID 1505805763824586952.
Durable state path: /Users/jooho-hermes/.hermes/autonomous-agent-lab/state.md
Working directory for experiment artifacts: /Users/jooho-hermes/.hermes/autonomous-agent-lab/
Preferred published web root: /Users/jooho-hermes/hermes-web/agent-pets/
Top-level directive from Son:
- The project has evolved from a personal dashboard into an INSTALLABLE PRODUCT that external Hermes users can deploy.
- The final target is a self-contained, configurable, publishable solution: "Hermes Pixel Pet Ops Office".
- Do NOT shrink the mission into a small static MVP and autonomously stop.
- The Gather.town-style 2D spatial office is a first-class feature, not a side page.
Latest UX feedback from Son (treat as immediate priority before deeper packaging work):
- Details are hard for a human to understand. Add human-first summaries, plain-language labels, and progressive disclosure: summary first, technical details second.
- Gather Town version has too many agents roaming around. Reduce default movement, add density/speed controls, cluster agents by room/task, and add focus/calm mode.
- Theme switching is not visibly working. Implement real UI theme switcher with persistence and clear visual theme changes.
Key product requirements (installable solution level):
1. Config-driven architecture: all paths, URLs, colors, names, room layouts via config.yaml. No hardcoded references to jooho-hermes.
2. Self-contained package: clear directory structure (src/, web/, config/, docs/, scripts/), install script, requirements.txt.
3. Pluggable data adapter: support multiple backends via plugin architecture.
4. Themeable frontend: CSS variables driven from config, swappable themes, plus a working UI theme switcher.
5. Multi-tenant ready: works for any Hermes instance.
6. Build/Deploy ready: Dockerfile or docker-compose, or clear static-server setup.
7. Documentation: README, architecture docs, configuration reference, contributor guide.
8. Human-comprehensible UX: plain-language summaries and progressive disclosure for technical detail.
9. Gather.town calm mode: adjustable movement density/speed and less chaotic defaults.
10. Versioned releases: CHANGELOG.md, semantic versioning, release packaging.
Mission model:
- Read state.md first before doing anything else.
- If state.md says
status: inactive or has no Current Mission, do not invent work. Return exactly: ๐ก Autonomous Agent Lab ๋๊ธฐ์ค โ Son์ด ํธ๋ฆฌ๊ฑฐ/๋ฏธ์
์ ์ฃผ๋ฉด 15๋ถ ์ฌ์ดํด์ ์์ํฉ๋๋ค.
- If state.md says
status: active, run one bounded 15-minute cycle toward the full installable solution.
- If state.md says
status: complete, verify that the Final Completion Condition in state.md is truly met. If it is not fully met, reactivate or report that state needs correction.
Cycle procedure when active:
1. Read state.md first. Extract current mission, constraints, previous cycle log, and Final Completion Condition.
2. Decide the next smallest useful step toward installable solution quality. Focus on: architecture, configurability, documentation, and clean separation of concerns.
3. Use delegate_task for independent subagent lanes when helpful.
4. Prefer concrete progress: refactor to config-driven, add install scripts, create docs, add Docker support, theme system, plugin architecture.
5. Update state.md with a new cycle log entry before final reporting.
6. Completion rule: only set status: complete when every item under state.md Final Completion Condition is satisfied. A non-installable MVP is not complete.
7. Stop/block only if Son explicitly stops/redirects, a safety boundary is reached, or a hard blocker needs Son's decision.
Link requirement (never forget):
- Every cycle report MUST include at least one direct viewable link to the published dashboard/artifact.
- The canonical URL:
http://hermes-mac-mini.tail46b3c6.ts.net:8099/agent-pets/
- Include gather town URL too:
http://hermes-mac-mini.tail46b3c6.ts.net:8099/agent-pets/gather/
Final Discord message format:
[Autonomous Agent Lab v1 / Cycle N]
๋ชฉํ:
์ํ:
๊ฒฐ๊ณผ:
๊ฒ์ฆ:
๋ค์:
์ํ:
Safety/quality rules:
- Do not handle secrets, passwords, API keys, payment, permission dialogs, or destructive commands.
- Do not claim completion without updating state.md.
- Do not rely on Discord history as durable state.
- Do not spam raw logs; summarize lane outputs and verification.
- Keep working in /Users/jooho-hermes/.hermes/autonomous-agent-lab/ and publish only to /Users/jooho-hermes/hermes-web/agent-pets/ unless the state file says otherwise.
Design/UX priorities:
- Mobile responsiveness is first-class.
- Character animation/movement is desired.
- Every cycle report must include published links.
- This is now a product engineering mission. Architecture, configurability, and documentation matter as much as visuals.
Response
[Autonomous Agent Lab v1 / Cycle 60]
๋ชฉํ:
- ๋จ์ ์๋ CSS ํ๋์ฝ๋ฉ ์ ๊ฑฐ: building ์ํ glow ์ ๋๋ฉ์ด์
์ด alpha=0์ด๋ผ ๋ณด์ด์ง ์๋ ๋ฒ๊ทธ ์์ , ๋ชจ๋ฌ ์ค๋ฒ๋ ์ด ๋ฐฐ๊ฒฝ์ ํ
๋ง๋ณ ๋ณ์๋ก ์ ํ, freshness badge ํ๋์ฝ๋ฉ ์ ๊ฑฐ.
์ํ:
1. dashboard.css์ @keyframes glow์์ rgba(255,182,92,0) โ var(--glow-spread)๋ก ๊ต์ฒด (glow๊ฐ ์ค์ ๋ก ๋ณด์ด๋๋ก).
2. 3๊ฐ ํ
๋ง์ --overlay-dark, --glow-spread, --stale-bg, --stale-border ๋ณ์ ์ถ๊ฐ.
3. dashboard.css / gather.css์ ํ๋์ฝ๋ฉ๋ rgba(0,0,0,.55/.45/.6) โ var(--overlay-dark)๋ก ๊ต์ฒด.
4. .freshness-badge.stale์ ํ๋์ฝ๋ฉ ์์์ ํ
๋ง ๋ณ์๋ก ๊ต์ฒด.
5. ์บ์ ๋ฒ์คํ
v60, ๋น๋ ๋ฐฐ์ง v1.4.4 ยท b60, ์๋น์ค ์์ปค pixel-pet-ops-v17๋ก ์ผ๊ด ๊ฐฑ์ .
6. scripts/publish.sh๋ก ์ ์ฒด ํผ๋ธ๋ฆฌ์ฑ ์๋ฃ.
๊ฒฐ๊ณผ:
- ํตํฉ ํ
์คํธ: 114/114 passed
- ์
์
๊ฒ์ฆ: 21/21 passed
- ์ด๋ํฐ: 32 agents, 15 cron jobs, 20 sessions, 16 events, schema 1.4
ops-data.json / health.json mtime: 16:21 (fresh)
refresh.err.log: empty, LaunchAgent healthy
๊ฒ์ฆ:
- ๊ฒ์๋ CSS์์
rgba(255,182,92,0) ๋ฐ rgba(0,0,0,.55) ํ๋์ฝ๋ฉ 0๊ฑด ํ์ธ.
themes/*/theme.css์ --overlay-dark, --glow-spread ์ ์ ์กด์ฌ.
- ๊ฒ์๋ index.html ๋น๋ ๋ฐฐ์ง
v1.4.4 ยท b60, asset ๋งํฌ ?v=60 ํ์ธ.
๋ค์:
- Son์ ๋์๋ณด๋ ๋๋ Gather Town ํ๋จ์ "๐ ์บ์ ์ญ์ & ์๋ก๊ณ ์นจ" ๋ฒํผ์ ๋๋ฌ service worker ์บ์๋ฅผ ์์ ํ ๋น์ด ๋ค, ํ
๋ง ์ ํ๊ณผ "๊ตฌํ์ค" ์ํ ์์ด์ ํธ์ glow ์ ๋๋ฉ์ด์
๊ฐ์์ฑ์ ํ์ธํด ์ฃผ์ธ์.
- ์ถ๊ฐ ํผ๋๋ฐฑ ์์ผ๋ฉด ๋ค์ ์ฌ์ดํด์์ ์ต์ข
์๋ฃ ์ฒ๋ฆฌ ๋๋ ์ถ๊ฐ ๊ฐ์ ์์
์ ์งํํฉ๋๋ค.
์ํ: active โ Cycle 60์์ glow ๋ฒ๊ทธ ๋ฐ overlay ํ๋์ฝ๋ฉ์ ํด๊ฒฐํ์ต๋๋ค. 11๊ฐ ์ต์ข
์๋ฃ ์กฐ๊ฑด ๋ชจ๋ ์ถฉ์กฑ ์ํ ์ ์ง ์ค.
---
๐ ๋ฐ๋ก๊ฐ๊ธฐ
- ๋์๋ณด๋: http://hermes-mac-mini.tail46b3c6.ts.net:8099/agent-pets/
- Gather Town: http://hermes-mac-mini.tail46b3c6.ts.net:8099/agent-pets/gather/
|
| 2026-05-19 16-03-32 |
80,946 chars |
2026-05-19_16-03-32.md |
Cron Job: autonomous-agent-lab-v1-orchestrator
Job ID: 35127ff89556
Run Time: 2026-05-19 16:03:32
Schedule: every 15m
Prompt
[IMPORTANT: The user has invoked the "hermes-agent" skill, indicating they want you to follow its instructions. The full skill content is loaded below.]
---
name: hermes-agent
description: "Configure, extend, or contribute to Hermes Agent."
version: 2.1.0
author: Hermes Agent + Teknium
license: MIT
platforms: [linux, macos, windows]
metadata:
hermes:
tags: [hermes, setup, configuration, multi-agent, spawning, cli, gateway, development]
homepage: https://github.com/NousResearch/hermes-agent
related_skills: [claude-code, codex, opencode]
---
Hermes Agent
Hermes Agent is an open-source AI agent framework by Nous Research that runs in your terminal, messaging platforms, and IDEs. It belongs to the same category as Claude Code (Anthropic), Codex (OpenAI), and OpenClaw โ autonomous coding and task-execution agents that use tool calling to interact with your system. Hermes works with any LLM provider (OpenRouter, Anthropic, OpenAI, DeepSeek, local models, and 15+ others) and runs on Linux, macOS, and WSL.
What makes Hermes different:
- Self-improving through skills โ Hermes learns from experience by saving reusable procedures as skills. When it solves a complex problem, discovers a workflow, or gets corrected, it can persist that knowledge as a skill document that loads into future sessions. Skills accumulate over time, making the agent better at your specific tasks and environment.
- Persistent memory across sessions โ remembers who you are, your preferences, environment details, and lessons learned. Pluggable memory backends (built-in, Honcho, Mem0, and more) let you choose how memory works.
- Multi-platform gateway โ the same agent runs on Telegram, Discord, Slack, WhatsApp, Signal, Matrix, Email, and 10+ other platforms with full tool access, not just chat.
- Provider-agnostic โ swap models and providers mid-workflow without changing anything else. Credential pools rotate across multiple API keys automatically.
- Profiles โ run multiple independent Hermes instances with isolated configs, sessions, skills, and memory.
- Extensible โ plugins, MCP servers, custom tools, webhook triggers, cron scheduling, and the full Python ecosystem.
People use Hermes for software development, research, system administration, data analysis, content creation, home automation, and anything else that benefits from an AI agent with persistent context and full system access.
This skill helps you work with Hermes Agent effectively โ setting it up, configuring features, spawning additional agent instances, troubleshooting issues, finding the right commands and settings, and understanding how the system works when you need to extend or contribute to it.
Docs: https://hermes-agent.nousresearch.com/docs/
Quick Start
Install
curl -fsSL https://raw.githubusercontent.com/NousResearch/hermes-agent/main/scripts/install.sh | bash
Interactive chat (default)
hermes
Single query
hermes chat -q "What is the capital of France?"
Setup wizard
hermes setup
Change model/provider
hermes model
Check health
hermes doctor
---
CLI Reference
Global Flags
hermes [flags] [command]
--version, -V Show version
--resume, -r SESSION Resume session by ID or title
--continue, -c [NAME] Resume by name, or most recent session
--worktree, -w Isolated git worktree mode (parallel agents)
--skills, -s SKILL Preload skills (comma-separate or repeat)
--profile, -p NAME Use a named profile
--yolo Skip dangerous command approval
--pass-session-id Include session ID in system prompt
No subcommand defaults to chat.
Chat
hermes chat [flags]
-q, --query TEXT Single query, non-interactive
-m, --model MODEL Model (e.g. anthropic/claude-sonnet-4)
-t, --toolsets LIST Comma-separated toolsets
--provider PROVIDER Force provider (openrouter, anthropic, nous, etc.)
-v, --verbose Verbose output
-Q, --quiet Suppress banner, spinner, tool previews
--checkpoints Enable filesystem checkpoints (/rollback)
--source TAG Session source tag (default: cli)
Configuration
hermes setup [section] Interactive wizard (model|terminal|gateway|tools|agent)
hermes model Interactive model/provider picker
hermes config View current config
hermes config edit Open config.yaml in $EDITOR
hermes config set KEY VAL Set a config value
hermes config path Print config.yaml path
hermes config env-path Print .env path
hermes config check Check for missing/outdated config
hermes config migrate Update config with new options
hermes doctor [--fix] Check dependencies and config
Credential Pools
hermes auth add Interactive credential wizard (oauth, api-key)
hermes auth list [PROVIDER] List pooled credentials
hermes auth remove P INDEX Remove by provider + index
hermes auth reset PROVIDER Clear exhaustion status
hermes logout Clear stored auth
Tools & Skills
hermes tools Interactive tool enable/disable (curses UI)
hermes tools list Show all tools and status
hermes tools enable NAME Enable a toolset
hermes tools disable NAME Disable a toolset
hermes skills list List installed skills
hermes skills search QUERY Search the skills hub
hermes skills install ID Install a skill (ID can be a hub identifier OR a direct https://โฆ/SKILL.md URL; pass --name to override when frontmatter has no name)
hermes skills inspect ID Preview without installing
hermes skills config Enable/disable skills per platform
hermes skills check Check for updates
hermes skills update Update outdated skills
hermes skills uninstall N Remove a hub skill
hermes skills publish PATH Publish to registry
hermes skills browse Browse all available skills
hermes skills tap add REPO Add a GitHub repo as skill source
MCP Servers
hermes mcp serve Run Hermes as an MCP server
hermes mcp add NAME Add an MCP server (--url or --command)
hermes mcp remove NAME Remove an MCP server
hermes mcp list List configured servers
hermes mcp test NAME Test connection
hermes mcp configure NAME Toggle tool selection
Gateway (Messaging Platforms)
hermes gateway run Start gateway foreground
hermes gateway install Install as background service
hermes gateway start/stop Control the service
hermes gateway restart Restart the service
hermes gateway status Check status
hermes gateway setup Configure platforms
Supported platforms: Telegram, Discord, Slack, WhatsApp, Signal, Email, SMS, Matrix, Mattermost, Home Assistant, DingTalk, Feishu, WeCom, BlueBubbles (iMessage), Weixin (WeChat), API Server, Webhooks. Open WebUI connects via the API Server adapter.
Platform docs: https://hermes-agent.nousresearch.com/docs/user-guide/messaging/
Discord-specific walkthrough (token, intents, service install, access control): see references/discord-gateway-setup.md in this skill.
- Per-channel personas and skill bindings: see
references/gateway-channel-personas.md (works on Discord, Slack, Telegram, Mattermost, Matrix).
- For long-running Discord-first operations, purpose-specific channel routing, periodic summaries, weekly Dreaming/audit reports, and log-safety patterns: see
references/discord-operating-planes.md.
- For broad Hermes/LifeOS/SQAF ecosystem audits (cron inventory, live services, dashboards, provider/model warnings, and control-plane gaps), see
references/ecosystem-audit.md.
Sessions
hermes sessions list List recent sessions
hermes sessions browse Interactive picker
hermes sessions export OUT Export to JSONL
hermes sessions rename ID T Rename a session
hermes sessions delete ID Delete a session
hermes sessions prune Clean up old sessions (--older-than N days)
hermes sessions stats Session store statistics
For browser-based viewing of existing Hermes CLI/Discord/cron session transcripts, prefer a lightweight static export from ~/.hermes/state.db into a private web root instead of assuming Open WebUI can browse Hermes' native session store. See references/hermes-session-static-web-viewer.md for the SQLite schema, static HTML export workflow, redaction/truncation cautions, and the user's Mac mini deployment (/hermes-sessions/ under the Tailscale-only ~/hermes-web site).
For cron job execution history, the same static-export pattern applies to ~/.hermes/cron/jobs.json and ~/.hermes/cron/output/{job_id}/*.md. See references/cron-history-web-viewer.md for the cron data model, schedule-dict pitfall, and the user's deployed /cron-history/ dashboard.
Cron Jobs
hermes cron list List jobs (--all for disabled)
hermes cron create SCHED Create: '30m', 'every 2h', '0 9 *'
hermes cron edit ID Edit schedule, prompt, delivery
hermes cron pause/resume ID Control job state
hermes cron run ID Trigger on next tick
hermes cron remove ID Delete a job
hermes cron status Scheduler status
For bounded autonomous lab/orchestrator cron jobs that use file-based state, subagent lanes, artifact publishing, and status transitions (active โ complete/blocked/inactive), see references/autonomous-agent-lab-cron-cycle.md. A reusable verification script template lives at scripts/verify-completion-template.py.
For a worked example of evolving an autonomous lab into a config-driven, themeable, Docker-ready installable product, see references/autonomous-lab-product-architecture.md. For CI, integration testing, pluggable adapter architecture, bounded cycle orchestration, and post-productization patterns, see references/product-maturity-patterns.md.
For the final completion verification checklist โ the explicit audit pattern to run before marking status: complete on an installable-solution mission, see references/autonomous-lab-completion-verification.md.
For the reactivation protocol when a completed lab receives new P0 feedback or the user contradicts a completion claim, see references/autonomous-lab-reactivation-protocol.md.
For the config/CHANGELOG version drift pitfall that occurs when autonomous labs evolve over many cycles, see references/autonomous-lab-version-drift.md.
For adding historical trend tracking (SQLite-backed agent status transitions + vanilla JS SVG sparklines) to an autonomous lab dashboard, see references/history-tracking-sparkline-pattern.md.
For reusable dashboard UX patterns (onboarding tours, data freshness badges, keyboard shortcuts, progressive disclosure inspectors, cross-linking between views), see references/dashboard-ux-patterns.md.
For the aggressive human-first inspector refinement โ when users report that details are hard to understand and the fix is to strip technical labels from the default view โ see references/progressive-disclosure-human-first.md.
For programmatic verification of CSS custom-property theme systems โ catching scoping bugs, confirming theme distinctness, and validating JS switching logic โ see references/theme-system-verification.md.
For Son's Discord-first autonomous experiments where a channel hosts a repeated multi-agent loop, use the Autonomous Discord Agent Lab pattern: create file-based durable state, a paused cron orchestrator delivered to discord:<channel_id>, then activate it from a user mission trigger. See references/autonomous-discord-agent-lab.md.
Webhooks
hermes webhook subscribe N Create route at /webhooks/<name>
hermes webhook list List subscriptions
hermes webhook remove NAME Remove a subscription
hermes webhook test NAME Send a test POST
Profiles
hermes profile list List all profiles
hermes profile create NAME Create (--clone, --clone-all, --clone-from)
hermes profile use NAME Set sticky default
hermes profile delete NAME Delete a profile
hermes profile show NAME Show details
hermes profile alias NAME Manage wrapper scripts
hermes profile rename A B Rename a profile
hermes profile export NAME Export to tar.gz
hermes profile import FILE Import from archive
Credential Pools
hermes auth add Interactive credential wizard
hermes auth list [PROVIDER] List pooled credentials
hermes auth remove P INDEX Remove by provider + index
hermes auth reset PROVIDER Clear exhaustion status
Other
hermes insights [--days N] Usage analytics
hermes update Update to latest version
hermes pairing list/approve/revoke DM authorization
hermes plugins list/install/remove Plugin management
hermes honcho setup/status Honcho memory integration (requires honcho plugin)
hermes memory setup/status/off Memory provider config
hermes completion bash|zsh Shell completions
hermes acp ACP server (IDE integration)
hermes claw migrate Migrate from OpenClaw
hermes uninstall Uninstall Hermes
---
Slash Commands (In-Session)
Type these during an interactive chat session. New commands land fairly
often; if something below looks stale, run /help in-session for the
authoritative list or see the [live slash commands reference](https://hermes-agent.nousresearch.com/docs/reference/slash-commands).
The registry of record is hermes_cli/commands.py โ every consumer
(autocomplete, Telegram menu, Slack mapping, /help) derives from it.
Session Control
/new (/reset) Fresh session
/clear Clear screen + new session (CLI)
/retry Resend last message
/undo Remove last exchange
/title [name] Name the session
/compress Manually compress context
/stop Kill background processes
/rollback [N] Restore filesystem checkpoint
/snapshot [sub] Create or restore state snapshots of Hermes config/state (CLI)
/background <prompt> Run prompt in background
/queue <prompt> Queue for next turn
/steer <prompt> Inject a message after the next tool call without interrupting
/agents (/tasks) Show active agents and running tasks
/resume [name] Resume a named session
/goal [text|sub] Set a standing goal Hermes works on across turns until achieved
(subcommands: status, pause, resume, clear)
/redraw Force a full UI repaint (CLI)
Configuration
/config Show config (CLI)
/model [name] Show or change model
/personality [name] Set personality
/reasoning [level] Set reasoning (none|minimal|low|medium|high|xhigh|show|hide)
/verbose Cycle: off โ new โ all โ verbose
/voice [on|off|tts] Voice mode
/yolo Toggle approval bypass
/busy [sub] Control what Enter does while Hermes is working (CLI)
(subcommands: queue, steer, interrupt, status)
/indicator [style] Pick the TUI busy-indicator style (CLI)
(styles: kaomoji, emoji, unicode, ascii)
/footer [on|off] Toggle gateway runtime-metadata footer on final replies
/skin [name] Change theme (CLI)
/statusbar Toggle status bar (CLI)
Tools & Skills
/tools Manage tools (CLI)
/toolsets List toolsets (CLI)
/skills Search/install skills (CLI)
/skill <name> Load a skill into session
/reload-skills Re-scan ~/.hermes/skills/ for added/removed skills
/reload Reload .env variables into the running session (CLI)
/reload-mcp Reload MCP servers
/cron Manage cron jobs (CLI)
/curator [sub] Background skill maintenance (status, run, pin, archive, โฆ)
/kanban [sub] Multi-profile collaboration board (tasks, links, comments)
/plugins List plugins (CLI)
Gateway
/approve Approve a pending command (gateway)
/deny Deny a pending command (gateway)
/restart Restart gateway (gateway)
/sethome Set current chat as home channel (gateway)
/update Update Hermes to latest (gateway)
/topic [sub] Enable or inspect Telegram DM topic sessions (gateway)
/platforms (/gateway) Show platform connection status (gateway)
Utility
/branch (/fork) Branch the current session
/fast Toggle priority/fast processing
/browser Open CDP browser connection
/history Show conversation history (CLI)
/save Save conversation to file (CLI)
/copy [N] Copy the last assistant response to clipboard (CLI)
/paste Attach clipboard image (CLI)
/image Attach local image file (CLI)
Info
/help Show commands
/commands [page] Browse all commands (gateway)
/usage Token usage
/insights [days] Usage analytics
/gquota Show Google Gemini Code Assist quota usage (CLI)
/status Session info (gateway)
/profile Active profile info
/debug Upload debug report (system info + logs) and get shareable links
Exit
/quit (/exit, /q) Exit CLI
---
Key Paths & Config
~/.hermes/config.yaml Main configuration
~/.hermes/.env API keys and secrets
$HERMES_HOME/skills/ Installed skills
~/.hermes/sessions/ Session transcripts
~/.hermes/logs/ Gateway and error logs
~/.hermes/auth.json OAuth tokens and credential pools
~/.hermes/hermes-agent/ Source code (if git-installed)
Profiles use ~/.hermes/profiles/<name>/ with the same layout.
Config Sections
Edit with hermes config edit or hermes config set section.key value.
| Section | Key options |
|---------|-------------|
| model | default, provider, base_url, api_key, context_length |
| agent | max_turns (90), tool_use_enforcement |
| terminal | backend (local/docker/ssh/modal), cwd, timeout (180) |
| compression | enabled, threshold (0.50), target_ratio (0.20) |
| display | skin, tool_progress, show_reasoning, show_cost |
| stt | enabled, provider (local/groq/openai/mistral) |
| tts | provider (edge/elevenlabs/openai/minimax/mistral/neutts) |
| memory | memory_enabled, user_profile_enabled, provider |
| security | tirith_enabled, website_blocklist |
| delegation | model, provider, base_url, api_key, max_iterations (50), reasoning_effort |
| checkpoints | enabled, max_snapshots (50) |
| fallback_model | provider, model, base_url, key_env |
Fallback Providers
Hermes can automatically fail over to a backup provider:model when the primary is unavailable. This is turn-scoped โ each new user message starts with the primary restored; fallback only activates mid-turn when the primary fails.
Configuration ( ~/.hermes/config.yaml):
fallback_model:
provider: opencode-go
model: kimi-k2.6
Or use the interactive manager:
hermes fallback add # interactive picker
hermes fallback list # show fallback chain
hermes fallback remove # remove by index
Legacy note: fallback_model (singular) is the legacy single-fallback key. fallback_providers (list) supports multiple ordered fallbacks. When both exist, fallback_providers takes priority.
Trigger conditions (after exhausting retries where applicable):
- Rate limits (HTTP 429)
- Server errors (HTTP 500, 502, 503)
- Auth failures (HTTP 401, 403) โ immediately
- Not found (HTTP 404) โ immediately
- Invalid / empty responses repeatedly
Supported providers include all standard providers (OpenRouter, Anthropic, OpenCode Go/ Zen, Kimi, etc.) plus custom endpoints with base_url + key_env. Full provider docs: https://hermes-agent.nousresearch.com/docs/integrations/providers
Limitations:
- Subagent delegation does not inherit fallback config
- Cron jobs do not use fallback (use per-job provider/model overrides)
- Auxiliary tasks (vision, compression, etc.) use their own
auxiliary.* provider chain
For a deep-dive with worked examples and model lists, see references/fallback-providers.md.
Full config reference: https://hermes-agent.nousresearch.com/docs/user-guide/configuration
Providers
20+ providers supported. Set via hermes model or hermes setup.
| Provider | Auth | Key env var |
|----------|------|-------------|
| OpenRouter | API key | OPENROUTER_API_KEY |
| Anthropic | API key | ANTHROPIC_API_KEY |
| Nous Portal | OAuth | hermes auth |
| OpenAI Codex | OAuth | hermes auth |
| GitHub Copilot | Token | COPILOT_GITHUB_TOKEN |
| Google Gemini | API key | GOOGLE_API_KEY or GEMINI_API_KEY |
| DeepSeek | API key | DEEPSEEK_API_KEY |
| xAI / Grok | API key | XAI_API_KEY |
| Hugging Face | Token | HF_TOKEN |
| Z.AI / GLM | API key | GLM_API_KEY |
| MiniMax | API key | MINIMAX_API_KEY |
| MiniMax CN | API key | MINIMAX_CN_API_KEY |
| Kimi / Moonshot | API key | KIMI_API_KEY |
| Alibaba / DashScope | API key | DASHSCOPE_API_KEY |
| Xiaomi MiMo | API key | XIAOMI_API_KEY |
| Kilo Code | API key | KILOCODE_API_KEY |
| AI Gateway (Vercel) | API key | AI_GATEWAY_API_KEY |
| OpenCode Zen | API key | OPENCODE_ZEN_API_KEY |
| OpenCode Go | API key | OPENCODE_GO_API_KEY |
| Qwen OAuth | OAuth | hermes auth add qwen-oauth |
| Custom endpoint | Config | model.base_url + model.api_key in config.yaml |
| GitHub Copilot ACP | External | COPILOT_CLI_PATH or Copilot CLI |
Full provider docs: https://hermes-agent.nousresearch.com/docs/integrations/providers
Toolsets
Enable/disable via hermes tools (interactive) or hermes tools enable/disable NAME.
| Toolset | What it provides |
|---------|-----------------|
| web | Web search and content extraction |
| search | Web search only (subset of web) |
| browser | Browser automation (Browserbase, Camofox, or local Chromium) |
| terminal | Shell commands and process management |
| file | File read/write/search/patch |
| code_execution | Sandboxed Python execution |
| vision | Image analysis |
| image_gen | AI image generation |
| video | Video analysis and generation |
| tts | Text-to-speech |
| skills | Skill browsing and management |
| memory | Persistent cross-session memory |
| session_search | Search past conversations |
| delegation | Subagent task delegation |
| cronjob | Scheduled task management |
| clarify | Ask user clarifying questions |
| messaging | Cross-platform message sending |
| todo | In-session task planning and tracking |
| kanban | Multi-agent work-queue tools (gated to workers) |
| debugging | Extra introspection/debug tools (off by default) |
| safe | Minimal, low-risk toolset for locked-down sessions |
| spotify | Spotify playback and playlist control |
| homeassistant | Smart home control (off by default) |
| discord | Discord integration tools |
| discord_admin | Discord admin/moderation tools |
| feishu_doc | Feishu (Lark) document tools |
| feishu_drive | Feishu (Lark) drive tools |
| yuanbao | Yuanbao integration tools |
| rl | Reinforcement learning tools (off by default) |
| moa | Mixture of Agents (off by default) |
Full enumeration lives in toolsets.py as the TOOLSETS dict; _HERMES_CORE_TOOLS is the default bundle most platforms inherit from.
Tool changes take effect on /reset (new session). They do NOT apply mid-conversation to preserve prompt caching.
---
Security & Privacy Toggles
Common "why is Hermes doing X to my output / tool calls / commands?" toggles โ and the exact commands to change them. Most of these need a fresh session (/reset in chat, or start a new hermes invocation) because they're read once at startup.
Secret redaction in tool output
Secret redaction is off by default โ tool output (terminal stdout, read_file, web content, subagent summaries, etc.) passes through unmodified. If the user wants Hermes to auto-mask strings that look like API keys, tokens, and secrets before they enter the conversation context and logs:
hermes config set security.redact_secrets true # enable globally
Restart required. security.redact_secrets is snapshotted at import time โ toggling it mid-session (e.g. via export HERMES_REDACT_SECRETS=true from a tool call) will NOT take effect for the running process. Tell the user to run hermes config set security.redact_secrets true in a terminal, then start a new session. This is deliberate โ it prevents an LLM from flipping the toggle on itself mid-task.
Disable again with:
hermes config set security.redact_secrets false
PII redaction in gateway messages
Separate from secret redaction. When enabled, the gateway hashes user IDs and strips phone numbers from the session context before it reaches the model:
hermes config set privacy.redact_pii true # enable
hermes config set privacy.redact_pii false # disable (default)
Command approval prompts
By default (approvals.mode: manual), Hermes prompts the user before running shell commands flagged as destructive (rm -rf, git reset --hard, etc.). The modes are:
manual โ always prompt (default)
smart โ use an auxiliary LLM to auto-approve low-risk commands, prompt on high-risk
off โ skip all approval prompts (equivalent to --yolo)
hermes config set approvals.mode smart # recommended middle ground
hermes config set approvals.mode off # bypass everything (not recommended)
Per-invocation bypass without changing config:
hermes --yolo โฆ
export HERMES_YOLO_MODE=1
Note: YOLO / approvals.mode: off does NOT turn off secret redaction. They are independent.
Shell hooks allowlist
Some shell-hook integrations require explicit allowlisting before they fire. Managed via ~/.hermes/shell-hooks-allowlist.json โ prompted interactively the first time a hook wants to run.
Disabling the web/browser/image-gen tools
To keep the model away from network or media tools entirely, open hermes tools and toggle per-platform. Takes effect on next session (/reset). See the Tools & Skills section above.
---
Voice & Transcription
STT (Voice โ Text)
Voice messages from messaging platforms are auto-transcribed.
Provider priority (auto-detected):
1. Local faster-whisper โ free, no API key: pip install faster-whisper
2. Groq Whisper โ free tier: set GROQ_API_KEY
3. OpenAI Whisper โ paid: set VOICE_TOOLS_OPENAI_KEY
4. Mistral Voxtral โ set MISTRAL_API_KEY
Config:
stt:
enabled: true
provider: local # local, groq, openai, mistral
local:
model: base # tiny, base, small, medium, large-v3
TTS (Text โ Voice)
| Provider | Env var | Free? |
|----------|---------|-------|
| Edge TTS | None | Yes (default) |
| ElevenLabs | ELEVENLABS_API_KEY | Free tier |
| OpenAI | VOICE_TOOLS_OPENAI_KEY | Paid |
| MiniMax | MINIMAX_API_KEY | Paid |
| Mistral (Voxtral) | MISTRAL_API_KEY | Paid |
| NeuTTS (local) | None (pip install neutts[all] + espeak-ng) | Free |
Voice commands: /voice on (voice-to-voice), /voice tts (always voice), /voice off.
---
Spawning Additional Hermes Instances
Run additional Hermes processes as fully independent subprocesses โ separate sessions, tools, and environments.
When to Use This vs delegate_task
| | delegate_task | Spawning hermes process |
|-|-----------------|--------------------------|
| Isolation | Separate conversation, shared process | Fully independent process |
| Duration | Minutes (bounded by parent loop) | Hours/days |
| Tool access | Subset of parent's tools | Full tool access |
| Interactive | No | Yes (PTY mode) |
| Use case | Quick parallel subtasks | Long autonomous missions |
One-Shot Mode
terminal(command="hermes chat -q 'Research GRPO papers and write summary to ~/research/grpo.md'", timeout=300)
Background for long tasks:
terminal(command="hermes chat -q 'Set up CI/CD for ~/myapp'", background=true)
Interactive PTY Mode (via tmux)
Hermes uses prompt_toolkit, which requires a real terminal. Use tmux for interactive spawning:
Start
terminal(command="tmux new-session -d -s agent1 -x 120 -y 40 'hermes'", timeout=10)
Wait for startup, then send a message
terminal(command="sleep 8 && tmux send-keys -t agent1 'Build a FastAPI auth service' Enter", timeout=15)
Read output
terminal(command="sleep 20 && tmux capture-pane -t agent1 -p", timeout=5)
Send follow-up
terminal(command="tmux send-keys -t agent1 'Add rate limiting middleware' Enter", timeout=5)
Exit
terminal(command="tmux send-keys -t agent1 '/exit' Enter && sleep 2 && tmux kill-session -t agent1", timeout=10)
Multi-Agent Coordination
Agent A: backend
terminal(command="tmux new-session -d -s backend -x 120 -y 40 'hermes -w'", timeout=10)
terminal(command="sleep 8 && tmux send-keys -t backend 'Build REST API for user management' Enter", timeout=15)
Agent B: frontend
terminal(command="tmux new-session -d -s frontend -x 120 -y 40 'hermes -w'", timeout=10)
terminal(command="sleep 8 && tmux send-keys -t frontend 'Build React dashboard for user management' Enter", timeout=15)
Check progress, relay context between them
terminal(command="tmux capture-pane -t backend -p | tail -30", timeout=5)
terminal(command="tmux send-keys -t frontend 'Here is the API schema from the backend agent: ...' Enter", timeout=5)
Session Resume
Resume most recent session
terminal(command="tmux new-session -d -s resumed 'hermes --continue'", timeout=10)
Resume specific session
terminal(command="tmux new-session -d -s resumed 'hermes --resume 20260225_143052_a1b2c3'", timeout=10)
Tips
- Prefer
delegate_task for quick subtasks โ less overhead than spawning a full process
- Use
-w (worktree mode) when spawning agents that edit code โ prevents git conflicts
- Set timeouts for one-shot mode โ complex tasks can take 5-10 minutes
- Use
hermes chat -q for fire-and-forget โ no PTY needed
- Use tmux for interactive sessions โ raw PTY mode has
\r vs \n issues with prompt_toolkit
- For scheduled tasks, use the
cronjob tool instead of spawning โ handles delivery and retry
---
Durable & Background Systems
Four systems run alongside the main conversation loop. Quick reference
here; full developer notes live in AGENTS.md, user-facing docs under
website/docs/user-guide/features/.
Delegation (delegate_task)
Synchronous subagent spawn โ the parent waits for the child's summary
before continuing its own loop. Isolated context + terminal session.
- Single:
delegate_task(goal, context, toolsets).
- Batch:
delegate_task(tasks=[{goal, ...}, ...]) runs children in
parallel, capped by delegation.max_concurrent_children (default 3).
- Roles:
leaf (default; cannot re-delegate) vs orchestrator
(can spawn its own workers, bounded by delegation.max_spawn_depth).
- Not durable. If the parent is interrupted, the child is
cancelled. For work that must outlive the turn, use cronjob or
terminal(background=True, notify_on_complete=True).
Config: delegation.* in config.yaml.
Tuning max_concurrent_children
Default is 3. Rule of thumb for raising it:
- Light tasks (web search, file grep): up to
6-8
- Medium tasks (code execution, browser):
4-5
- Heavy tasks (builds, large data):
2-3
- Actual bottleneck is usually the API rate limit, not local CPU/RAM. On a 10-core M4 with 16GB RAM, CPU is rarely the constraint.
- Formula: start at
5, raise only if profiling shows idle time between API responses.
Cron (scheduled jobs)
Durable scheduler โ cron/jobs.py + cron/scheduler.py. Drive it via
the cronjob tool, the hermes cron CLI (list, add, edit,
pause, resume, run, remove), or the /cron slash command.
- Schedules: duration (
"30m", "2h"), "every" phrase
( "every monday 9am"), 5-field cron ( "0 9 *"), or ISO timestamp.
- Per-job knobs:
skills, model/provider override, script
(pre-run data collection; no_agent=True makes the script the whole
job), context_from (chain job A's output into job B), workdir
(run in a specific dir with its AGENTS.md / CLAUDE.md loaded),
multi-platform delivery.
- Invariants: 3-minute hard interrupt per run,
.tick.lock file
prevents duplicate ticks across processes, cron sessions pass
skip_memory=True by default, and cron deliveries are framed with a
header/footer instead of being mirrored into the target gateway
session (keeps role alternation intact).
User docs: https://hermes-agent.nousresearch.com/docs/user-guide/features/cron
Curator (skill lifecycle)
Background maintenance for agent-created skills. Tracks usage, marks
idle skills stale, archives stale ones, keeps a pre-run tar.gz backup
so nothing is lost.
- CLI:
hermes curator <verb> โ status, run, pause, resume,
pin, unpin, archive, restore, prune, backup, rollback.
- Slash:
/curator <subcommand> mirrors the CLI.
- Scope: only touches skills with
created_by: "agent" provenance.
Bundled + hub-installed skills are off-limits. Never deletes โ
max destructive action is archive. Pinned skills are exempt from
every auto-transition and every LLM review pass.
- Telemetry: sidecar at
~/.hermes/skills/.usage.json holds
per-skill use_count, view_count, patch_count,
last_activity_at, state, pinned.
Config: curator.* (enabled, interval_hours, min_idle_hours,
stale_after_days, archive_after_days, backup.*).
User docs: https://hermes-agent.nousresearch.com/docs/user-guide/features/curator
Dreaming (periodic memory/skill consolidation)
For Anthropic-style "dreaming" workflows, combine cron + session_search + memory + skills + curator into a scheduled review loop. Start with a weekly, proposal-only report that audits recent sessions, repeated user corrections, memory conflicts, skill patch candidates, and cron/automation improvements. Do not automatically delete/replace memory or patch/archive skills unless the user explicitly approves the proposed changes. See references/weekly-dreaming-routine.md for the recommended prompt, report format, safety policy, and cron creation pattern.
Kanban (multi-agent work queue)
Durable SQLite board for multi-profile / multi-worker collaboration.
Users drive it via hermes kanban <verb>; dispatcher-spawned workers
see a focused kanban_* toolset gated by HERMES_KANBAN_TASK so the
schema footprint is zero outside worker processes.
- CLI verbs (common):
init, create, list (alias ls),
show, assign, link, unlink, comment, complete, block,
unblock, archive, tail. Less common: watch, stats, runs,
log, dispatch, daemon, gc.
- Worker toolset:
kanban_show, kanban_complete, kanban_block,
kanban_heartbeat, kanban_comment, kanban_create, kanban_link.
- Dispatcher runs inside the gateway by default
( kanban.dispatch_in_gateway: true) โ reclaims stale claims,
promotes ready tasks, atomically claims, spawns assigned profiles.
Auto-blocks a task after ~5 consecutive spawn failures.
- Isolation: board is the hard boundary (workers get
HERMES_KANBAN_BOARD pinned in env); tenant is a soft namespace
within a board for workspace-path + memory-key isolation.
User docs: https://hermes-agent.nousresearch.com/docs/user-guide/features/kanban
Log Relay (Hermes โ Discord)
A background Python script that tails ~/.hermes/logs/*.log and batches lines to a Discord channel. Includes session-ID extraction, rate-limit handling, and auto-restart via launchd/systemd. Useful for remote monitoring and audit trails.
- Reference:
references/discord-log-relay.md โ full setup, tuning, macOS/Linux service install, pitfalls.
- Template:
templates/discord-log-relay.py โ copy, set CHANNEL_ID, and deploy.
- Discord operations:
references/discord-operating-planes.md โ channel-purpose routing, periodic-summary vs Dreaming report formats, and safety/cost notes for Discord-first Hermes deployments.
Key pitfall: ask the user about batch frequency upfront rather than defaulting to real-time streaming. Most users prefer 10-minute or hourly batches. High-volume raw logs should be batched, summarized, or stored out-of-band; avoid Discord message storms during error loops.
Weekly Dreaming / Memory Curation
For long-running Hermes deployments, users may want an Anthropic-style "Dreaming" loop: a scheduled review that consolidates experience, proposes memory/skill/cron changes, and identifies what to keep, weaken, archive, or delete. Hermes has the building blocks (sessions, session_search, memory, skills, curator, cron), but the safe default is proposal mode:
1. Inspect recent usage and sessions.
2. Extract repeated success patterns, failure patterns, and user corrections.
3. Propose memory updates/removals without applying them silently.
4. Propose skill patches/archive candidates and cron/reporting improvements.
5. End with explicit approval checkboxes.
Do not silently rewrite or delete memory/skills from a Dreaming report unless the user explicitly authorized automatic application. See references/discord-operating-planes.md for a report template and routing heuristics.
---
Windows-Specific Quirks
Hermes runs natively on Windows (PowerShell, cmd, Windows Terminal, git-bash
mintty, VS Code integrated terminal). Most of it just works, but a handful
of differences between Win32 and POSIX have bitten us โ document new ones
here as you hit them so the next person (or the next session) doesn't
rediscover them from scratch.
Input / Keybindings
Alt+Enter doesn't insert a newline. Windows Terminal intercepts Alt+Enter
at the terminal layer to toggle fullscreen โ the keystroke never reaches
prompt_toolkit. Use Ctrl+Enter instead. Windows Terminal delivers
Ctrl+Enter as LF ( c-j), distinct from plain Enter ( c-m / CR), and the
CLI binds c-j to newline insertion on win32 only (see
_bind_prompt_submit_keys + the Windows-only c-j binding in cli.py).
Side effect: the raw Ctrl+J keystroke also inserts a newline on Windows โ
unavoidable, because Windows Terminal collapses Ctrl+Enter and Ctrl+J to
the same keycode at the Win32 console API layer. No conflicting binding
existed for Ctrl+J on Windows, so this is a harmless side effect.
mintty / git-bash behaves the same (fullscreen on Alt+Enter) unless you
disable Alt+Fn shortcuts in Options โ Keys. Easier to just use Ctrl+Enter.
Diagnosing keybindings. Run python scripts/keystroke_diagnostic.py
(repo root) to see exactly how prompt_toolkit identifies each keystroke
in the current terminal. Answers questions like "does Shift+Enter come
through as a distinct key?" (almost never โ most terminals collapse it
to plain Enter) or "what byte sequence is my terminal sending for
Ctrl+Enter?" This is how the Ctrl+Enter = c-j fact was established.
Config / Files
HTTP 400 "No models provided" on first run. config.yaml was saved
with a UTF-8 BOM (common when Windows apps write it). Re-save as UTF-8
without BOM. hermes config edit writes without BOM; manual edits in
Notepad are the usual culprit.
execute_code / Sandbox
WinError 10106 ("The requested service provider could not be loaded
or initialized") from the sandbox child process โ it can't create an
AF_INET socket, so the loopback-TCP RPC fallback fails before
connect(). Root cause is usually not a broken Winsock LSP; it's
Hermes's own env scrubber dropping SYSTEMROOT / WINDIR / COMSPEC
from the child env. Python's socket module needs SYSTEMROOT to locate
mswsock.dll. Fixed via the _WINDOWS_ESSENTIAL_ENV_VARS allowlist in
tools/code_execution_tool.py. If you still hit it, echo os.environ
inside an execute_code block to confirm SYSTEMROOT is set. Full
diagnostic recipe in references/execute-code-sandbox-env-windows.md.
Testing / Contributing
scripts/run_tests.sh doesn't work as-is on Windows โ it looks for
POSIX venv layouts ( .venv/bin/activate). The Hermes-installed venv at
venv/Scripts/ has no pip or pytest either (stripped for install size).
Workaround: install pytest + pytest-xdist + pyyaml into a system Python
3.11 user site, then invoke pytest directly with PYTHONPATH set:
"/c/Program Files/Python311/python" -m pip install --user pytest pytest-xdist pyyaml
export PYTHONPATH="$(pwd)"
"/c/Program Files/Python311/python" -m pytest tests/foo/test_bar.py -v --tb=short -n 0
Use -n 0, not -n 4 โ pyproject.toml's default addopts already
includes -n, and the wrapper's CI-parity guarantees don't apply off POSIX.
POSIX-only tests need skip guards. Common markers already in the codebase:
- Symlinks โ elevated privileges on Windows
0o600 file modes โ POSIX mode bits not enforced on NTFS by default
signal.SIGALRM โ Unix-only (see tests/conftest.py::_enforce_test_timeout)
- Winsock / Windows-specific regressions โ
@pytest.mark.skipif(sys.platform != "win32", ...)
Use the existing skip-pattern style (sys.platform == "win32" or
sys.platform.startswith("win")) to stay consistent with the rest of the
suite.
Path / Filesystem
Line endings. Git may warn LF will be replaced by CRLF the next time
Git touches it. Cosmetic โ the repo's .gitattributes normalizes. Don't
let editors auto-convert committed POSIX-newline files to CRLF.
Forward slashes work almost everywhere. C:/Users/... is accepted by
every Hermes tool and most Windows APIs. Prefer forward slashes in code
and logs โ avoids shell-escaping backslashes in bash.
---
Troubleshooting
Voice not working
1. Check stt.enabled: true in config.yaml
2. Verify provider: pip install faster-whisper or set API key
3. In gateway: /restart. In CLI: exit and relaunch.
Tool not available
1. hermes tools โ check if toolset is enabled for your platform
2. Some tools need env vars (check .env)
3. /reset after enabling tools
Model/provider issues
1. hermes doctor โ check config and dependencies
2. hermes auth add <provider> โ re-authenticate OAuth providers (use --type oauth)
3. Check .env has the right API key
4. Copilot 403: gh auth login tokens do NOT work for Copilot API. You must use the Copilot-specific OAuth device code flow via hermes model โ GitHub Copilot.
Changes not taking effect
- Tools/skills:
/reset starts a new session with updated toolset
- Config changes: In gateway:
/restart. In CLI: exit and relaunch.
- Code changes: Restart the CLI or gateway process
Deployed web dashboard shows stale CSS or theme changes
- Browser cache: Add
?v=N cache-busting query strings to CSS/JS/theme links in HTML.
- Service Worker cache: Bump
CACHE_NAME in sw.js to invalidate old shell caches.
- Data freshness: Use
fetch(url, {cache:'no-store'}) for live JSON feeds.
- See
references/static-site-cache-invalidation.md for the full diagnostic recipe.
Dashboard inspector feels too technical
- The default inspector view should contain only plain-language sentences: headline, "what they're doing now", "why it matters", and a silent visual progress bar (no text label).
- Move all technical fields (source IDs, confidence scores, progress labels, status slugs, badges) behind a "Show technical details" toggle.
- If users say "details are hard to understand," the fix is to remove more fields from the default view, not to add explanations. Explanations of technical fields are still technical.
- See
references/progressive-disclosure-human-first.md for the aggressive simplification pattern.
Skills not showing
1. hermes skills list โ verify installed
2. hermes skills config โ check platform enablement
3. Load explicitly: /skill name or hermes -s name
Gateway issues
Check logs first:
grep -i "failed to send\|error" ~/.hermes/logs/gateway.log | tail -20
Common gateway problems:
- Gateway dies on SSH logout: Enable linger:
sudo loginctl enable-linger $USER
- Gateway dies on WSL2 close: WSL2 requires
systemd=true in /etc/wsl.conf for systemd services to work. Without it, gateway falls back to nohup (dies when session closes).
- Gateway crash loop: Reset the failed state:
systemctl --user reset-failed hermes-gateway
- macOS: bot shows offline after idle time: The gateway runs as a user agent (
LimitLoadToSessionType=Aqua), so macOS suspends it when the system sleeps. The platform websocket drops and the bot appears offline until the network returns. Fix: keep the Mac awake (System Settings -> Energy -> Prevent automatic sleeping, or caffeinate -d -i -s -u &). Low Power Mode makes this worse, not better. See references/macos-gateway-sleep-disconnect.md for the full diagnostic recipe.
Platform-specific issues
- Discord bot silent: Must enable Message Content Intent in Bot โ Privileged Gateway Intents. See full Discord setup reference:
references/discord-gateway-setup.md.
- Slack bot only works in DMs: Must subscribe to
message.channels event. Without it, the bot ignores public channels.
- Windows-specific issues (
Alt+Enter newline, WinError 10106, UTF-8 BOM config, test suite, line endings): see the dedicated Windows-Specific Quirks section above.
Auxiliary models not working
If auxiliary tasks (vision, compression, session_search) fail silently, the auto provider can't find a backend. Either set OPENROUTER_API_KEY or GOOGLE_API_KEY, or explicitly configure each auxiliary task's provider:
hermes config set auxiliary.vision.provider <your_provider>
hermes config set auxiliary.vision.model <model_name>
Full system auth provisioning
For a one-shot workflow to maximize available credentials โ installing gh, generating SSH keys, configuring git, enabling all Hermes toolsets, and auditing current auth state โ see references/system-auth-setup.md.
Editing large files with patch
When a file is read with read_file(offset=...) (pagination), the tool warns that the view is partial. If you attempt patch without re-reading the full file first, you will likely hit non-unique match errors or corrupt the file. Fix: always call read_file without offset to load the whole file before patching. For append-only updates (e.g., adding a cycle log entry to state.md), do not use terminal(command="cat >> file << 'EOF'...EOF") โ the terminal tool on macOS/Linux misinterprets heredoc << as backgrounding and fails. Instead, write a short Python script via write_file and execute it with terminal(command="python3 /tmp/script.py"). See references/terminal-heredoc-workaround.md for the full pattern.
---
Windows-Specific Quirks
| Looking for... | Location |
|----------------|----------|
| Config options | hermes config edit or [Configuration docs](https://hermes-agent.nousresearch.com/docs/user-guide/configuration) |
| Available tools | hermes tools list or [Tools reference](https://hermes-agent.nousresearch.com/docs/reference/tools-reference) |
| Slash commands | /help in session or [Slash commands reference](https://hermes-agent.nousresearch.com/docs/reference/slash-commands) |
| Skills catalog | hermes skills browse or [Skills catalog](https://hermes-agent.nousresearch.com/docs/reference/skills-catalog) |
| Provider setup | hermes model or [Providers guide](https://hermes-agent.nousresearch.com/docs/integrations/providers) |
| Platform setup | hermes gateway setup or [Messaging docs](https://hermes-agent.nousresearch.com/docs/user-guide/messaging/) |
| MCP servers | hermes mcp list or [MCP guide](https://hermes-agent.nousresearch.com/docs/user-guide/features/mcp) |
| Profiles | hermes profile list or [Profiles docs](https://hermes-agent.nousresearch.com/docs/user-guide/profiles) |
| Cron jobs | hermes cron list or [Cron docs](https://hermes-agent.nousresearch.com/docs/user-guide/features/cron) |
| Memory | hermes memory status or [Memory docs](https://hermes-agent.nousresearch.com/docs/user-guide/features/memory) |
| Env variables | hermes config env-path or [Env vars reference](https://hermes-agent.nousresearch.com/docs/reference/environment-variables) |
| CLI commands | hermes --help or [CLI reference](https://hermes-agent.nousresearch.com/docs/reference/cli-commands) |
| Gateway logs | ~/.hermes/logs/gateway.log |
| Session files | ~/.hermes/sessions/ or hermes sessions browse |
| Source code | ~/.hermes/hermes-agent/ |
---
Contributor Quick Reference
For occasional contributors and PR authors. Full developer docs: https://hermes-agent.nousresearch.com/docs/developer-guide/
Project Layout
hermes-agent/
โโโ run_agent.py # AIAgent โ core conversation loop
โโโ model_tools.py # Tool discovery and dispatch
โโโ toolsets.py # Toolset definitions
โโโ cli.py # Interactive CLI (HermesCLI)
โโโ hermes_state.py # SQLite session store
โโโ agent/ # Prompt builder, context compression, memory, model routing, credential pooling, skill dispatch
โโโ hermes_cli/ # CLI subcommands, config, setup, commands
โ โโโ commands.py # Slash command registry (CommandDef)
โ โโโ config.py # DEFAULT_CONFIG, env var definitions
โ โโโ main.py # CLI entry point and argparse
โโโ tools/ # One file per tool
โ โโโ registry.py # Central tool registry
โโโ gateway/ # Messaging gateway
โ โโโ platforms/ # Platform adapters (telegram, discord, etc.)
โโโ cron/ # Job scheduler
โโโ tests/ # ~3000 pytest tests
โโโ website/ # Docusaurus docs site
Config: ~/.hermes/config.yaml (settings), ~/.hermes/.env (API keys).
Adding a Tool (3 files)
1. Create tools/your_tool.py:
import json, os
from tools.registry import registry
def check_requirements() -> bool:
return bool(os.getenv("EXAMPLE_API_KEY"))
def example_tool(param: str, task_id: str = None) -> str:
return json.dumps({"success": True, "data": "..."})
registry.register(
name="example_tool",
toolset="example",
schema={"name": "example_tool", "description": "...", "parameters": {...}},
handler=lambda args, **kw: example_tool(
param=args.get("param", ""), task_id=kw.get("task_id")),
check_fn=check_requirements,
requires_env=["EXAMPLE_API_KEY"],
)
2. Add to toolsets.py โ _HERMES_CORE_TOOLS list.
Auto-discovery: any tools/*.py file with a top-level registry.register() call is imported automatically โ no manual list needed.
All handlers must return JSON strings. Use get_hermes_home() for paths, never hardcode ~/.hermes.
Adding a Slash Command
1. Add CommandDef to COMMAND_REGISTRY in hermes_cli/commands.py
2. Add handler in cli.py โ process_command()
3. (Optional) Add gateway handler in gateway/run.py
All consumers (help text, autocomplete, Telegram menu, Slack mapping) derive from the central registry automatically.
Agent Loop (High Level)
run_conversation():
1. Build system prompt
2. Loop while iterations < max:
a. Call LLM (OpenAI-format messages + tool schemas)
b. If tool_calls โ dispatch each via handle_function_call() โ append results โ continue
c. If text response โ return
3. Context compression triggers automatically near token limit
Testing
python -m pytest tests/ -o 'addopts=' -q # Full suite
python -m pytest tests/tools/ -q # Specific area
- Tests auto-redirect
HERMES_HOME to temp dirs โ never touch real ~/.hermes/
- Run full suite before pushing any change
- Use
-o 'addopts=' to clear any baked-in pytest flags
Windows contributors: scripts/run_tests.sh currently looks for POSIX venvs ( .venv/bin/activate / venv/bin/activate) and will error out on Windows where the layout is venv/Scripts/activate + python.exe. The Hermes-installed venv at venv/Scripts/ also has no pip or pytest โ it's stripped for end-user install size. Workaround: install pytest + pytest-xdist + pyyaml into a system Python 3.11 user site ( /c/Program Files/Python311/python -m pip install --user pytest pytest-xdist pyyaml), then run tests directly:
export PYTHONPATH="$(pwd)"
"/c/Program Files/Python311/python" -m pytest tests/tools/test_foo.py -v --tb=short -n 0
Use -n 0 (not -n 4) because pyproject.toml's default addopts already includes -n, and the wrapper's CI-parity story doesn't apply off-POSIX.
Cross-platform test guards: tests that use POSIX-only syscalls need a skip marker. Common ones already in the codebase:
- Symlink creation โ
@pytest.mark.skipif(sys.platform == "win32", reason="Symlinks require elevated privileges on Windows") (see tests/cron/test_cron_script.py)
- POSIX file modes (0o600, etc.) โ
@pytest.mark.skipif(sys.platform.startswith("win"), reason="POSIX mode bits not enforced on Windows") (see tests/hermes_cli/test_auth_toctou_file_modes.py)
signal.SIGALRM โ Unix-only (see tests/conftest.py::_enforce_test_timeout)
- Live Winsock / Windows-specific regression tests โ
@pytest.mark.skipif(sys.platform != "win32", reason="Windows-specific regression")
Monkeypatching sys.platform is not enough when the code under test also calls platform.system() / platform.release() / platform.mac_ver(). Those functions re-read the real OS independently, so a test that sets sys.platform = "linux" on a Windows runner will still see platform.system() == "Windows" and route through the Windows branch. Patch all three together:
monkeypatch.setattr(sys, "platform", "linux")
monkeypatch.setattr(platform, "system", lambda: "Linux")
monkeypatch.setattr(platform, "release", lambda: "6.8.0-generic")
See tests/agent/test_prompt_builder.py::TestEnvironmentHints for a worked example.
Extending the system prompt's execution-environment block
Factual guidance about the host OS, user home, cwd, terminal backend, and shell (bash vs. PowerShell on Windows) is emitted from agent/prompt_builder.py::build_environment_hints(). This is also where the WSL hint and per-backend probe logic live. The convention:
- Local terminal backend โ emit host info (OS,
$HOME, cwd) + Windows-specific notes (hostname โ username, terminal uses bash not PowerShell).
- Remote terminal backend (anything in
_REMOTE_TERMINAL_BACKENDS: docker, singularity, modal, daytona, ssh, vercel_sandbox, managed_modal) โ suppress host info entirely and describe only the backend. A live uname/whoami/pwd probe runs inside the backend via tools.environments.get_environment(...).execute(...), cached per process in _BACKEND_PROBE_CACHE, with a static fallback if the probe times out.
- Key fact for prompt authoring: when
TERMINAL_ENV != "local", every file tool (read_file, write_file, patch, search_files) runs inside the backend container, not on the host. The system prompt must never describe the host in that case โ the agent can't touch it.
Full design notes, the exact emitted strings, and testing pitfalls:
references/prompt-builder-environment-hints.md.
Refactor-safety pattern (POSIX-equivalence guard): when you extract inline logic into a helper that adds Windows/platform-specific behavior, keep a _legacy_<name> oracle function in the test file that's a verbatim copy of the old code, then parametrize-diff against it. Example: tests/tools/test_code_execution_windows_env.py::TestPosixEquivalence. This locks in the invariant that POSIX behavior is bit-for-bit identical and makes any future drift fail loudly with a clear diff.
Commit Conventions
type: concise subject line
Optional body.
Types: fix:, feat:, refactor:, docs:, chore:
Key Rules
- Never break prompt caching โ don't change context, tools, or system prompt mid-conversation
- Message role alternation โ never two assistant or two user messages in a row
- Use
get_hermes_home() from hermes_constants for all paths (profile-safe)
- Config values go in
config.yaml, secrets go in .env
- New tools need a
check_fn so they only appear when requirements are met
[IMPORTANT: The user has invoked the "kanban-orchestrator" skill, indicating they want you to follow its instructions. The full skill content is loaded below.]
---
name: kanban-orchestrator
description: Decomposition playbook + anti-temptation rules for an orchestrator profile routing work through Kanban. The "don't do the work yourself" rule and the basic lifecycle are auto-injected into every kanban worker's system prompt; this skill is the deeper playbook when you're specifically playing the orchestrator role.
version: 3.0.0
platforms: [linux, macos, windows]
metadata:
hermes:
tags: [kanban, multi-agent, orchestration, routing]
related_skills: [kanban-worker]
---
Kanban Orchestrator โ Decomposition Playbook
> The core worker lifecycle (including the kanban_create fan-out pattern and the "decompose, don't execute" rule) is auto-injected into every kanban process via the KANBAN_GUIDANCE system-prompt block. This skill is the deeper playbook when you're an orchestrator profile whose whole job is routing.
Profiles are user-configured โ not a fixed roster
Hermes setups vary widely. Some users run a single profile that does everything; some run a small fleet (docker-worker, cron-worker); some run a curated specialist team they've named themselves. There is no default specialist roster โ the orchestrator skill does not know what profiles exist on this machine.
Before fanning out, you must ground the decomposition in the profiles that actually exist. The dispatcher silently fails to spawn unknown assignee names โ it doesn't autocorrect, doesn't suggest, doesn't fall back. So a card assigned to researcher on a setup that only has docker-worker just sits in ready forever.
Step 0: discover available profiles before planning.
Use one of these:
hermes profile list โ prints the table of profiles configured on this machine. Run it through your terminal tool if you have one; otherwise ask the user.
kanban_list(assignee="<some-name>") โ sanity-check a single name. Returns an empty list (rather than an error) for an unknown assignee, so this only confirms a name you're already considering.
- Just ask the user. "What profiles do you have set up?" is a fine first turn when the goal needs more than one specialist.
Cache the result in your working memory for the rest of the conversation. Re-asking every turn wastes a tool call.
When to use the board (vs. just doing the work)
Create Kanban tasks when any of these are true:
1. Multiple specialists are needed. Research + analysis + writing is three profiles.
2. The work should survive a crash or restart. Long-running, recurring, or important.
3. The user might want to interject. Human-in-the-loop at any step.
4. Multiple subtasks can run in parallel. Fan-out for speed.
5. Review / iteration is expected. A reviewer profile loops on drafter output.
6. The audit trail matters. Board rows persist in SQLite forever.
If none of those apply โ it's a small one-shot reasoning task โ use delegate_task instead or answer the user directly.
The anti-temptation rules
Your job description says "route, don't execute." The rules that enforce that:
- Do not execute the work yourself. Your restricted toolset usually doesn't even include terminal/file/code/web for implementation. If you find yourself "just fixing this quickly" โ stop and create a task for the right specialist.
- For any concrete task, create a Kanban task and assign it. Every single time.
- Split multi-lane requests before creating cards. A user prompt can contain several independent workstreams. Extract those lanes first, then create one card per lane instead of bundling unrelated work into a single implementer card.
- Run independent lanes in parallel. If two cards do not need each other's output, leave them unlinked so the dispatcher can fan them out. Link only true data dependencies.
- If no specialist fits the available profiles, ask the user which profile to create or which existing profile to use. Do not invent profile names; the dispatcher will silently drop unknown assignees.
- Decompose, route, and summarize โ that's the whole job.
Exception: micro-UI polish cycles
There is one narrow exception where the orchestrator may execute directly instead of creating Kanban cards: tiny UI-only polish cycles (e.g., adding a CSS class, a theme preview dot, a hover state, a cross-link, or a HUD button) that are purely presentational, require no cross-file logic changes, and fit comfortably inside a single bounded cycle with no need for review or parallel work. If the change is limited to HTML/CSS/JS cosmetics, no other profile has a stake in it, and the user did not ask for a design review, the orchestrator should just edit and publish rather than paying the kanban-overhead tax. This exception does NOT apply to architecture changes, adapter logic, plugin interfaces, or anything that touches the data layer.
Decomposition playbook
Step 1 โ Understand the goal
Ask clarifying questions if the goal is ambiguous. Cheap to ask; expensive to spawn the wrong fleet.
Step 2 โ Sketch the task graph
Before creating anything, draft the graph out loud (in your response to the user). Treat every concrete workstream as a candidate card:
1. Extract the lanes from the request.
2. Map each lane to one of the profiles you discovered in Step 0. If a lane doesn't fit any existing profile, ask the user which to use or create.
3. Decide whether each lane is independent or gated by another lane.
4. Create independent lanes as parallel cards with no parent links.
5. Create synthesis/review/integration cards with parent links to the lanes they depend on.
Examples of prompts that should fan out (using placeholder profile names โ substitute whatever exists on the user's setup):
- "Build an app" โ one card to a design-oriented profile for product/UI direction, one or two cards to engineering profiles for implementation, plus a later integration/review card if the user has a reviewer profile.
- "Fix blockers and check model variants" โ one implementation card for the blocker fixes plus one discovery/research card for config/source verification. A final reviewer card can depend on both.
- "Research docs and implement" โ a docs-research card can run in parallel with a codebase-discovery card; implementation waits only if it truly needs those findings.
- "Analyze this screenshot and find the related code" โ one card to a vision-capable profile for the visual analysis while another searches the codebase.
Words like "also," "finally," or "and" do not automatically imply a dependency. They often mean "make sure this is covered before reporting back." Only link tasks when one card cannot start until another card's output exists.
Show the graph to the user before creating cards. Let them correct it โ including which actual profile name should own each lane.
Step 3 โ Create tasks and link
Use the profile names from Step 0. The example below uses placeholders <profile-A>, <profile-B>, <profile-C> โ replace them with what the user actually has.
t1 = kanban_create(
title="research: Postgres cost vs current",
assignee="<profile-A>", # whichever profile handles research on this setup
body="Compare estimated infrastructure costs, migration costs, and ongoing ops costs over a 3-year window. Sources: AWS/GCP pricing, team time estimates, current Postgres bills from peers.",
tenant=os.environ.get("HERMES_TENANT"),
)["task_id"]
t2 = kanban_create(
title="research: Postgres performance vs current",
assignee="<profile-A>", # same profile, run in parallel
body="Compare query latency, throughput, and scaling characteristics at our expected data volume (~500GB, 10k QPS peak). Sources: benchmark papers, public case studies, pgbench results if easy.",
)["task_id"]
t3 = kanban_create(
title="synthesize migration recommendation",
assignee="<profile-B>", # whichever profile does synthesis/analysis
body="Read the findings from T1 (cost) and T2 (performance). Produce a 1-page recommendation with explicit trade-offs and a go/no-go call.",
parents=[t1, t2],
)["task_id"]
t4 = kanban_create(
title="draft decision memo",
assignee="<profile-C>", # whichever profile drafts user-facing prose
body="Turn the analyst's recommendation into a 2-page memo for the CTO. Match the tone of previous decision memos in the team's knowledge base.",
parents=[t3],
)["task_id"]
parents=[...] gates promotion โ children stay in todo until every parent reaches done, then auto-promote to ready. No manual coordination needed; the dispatcher and dependency engine handle it.
Step 4 โ Complete your own task
If you were spawned as a task yourself (e.g. a planner profile was assigned T0: "investigate Postgres migration"), mark it done with a summary of what you created:
kanban_complete(
summary="decomposed into T1-T4: 2 research lanes in parallel, 1 synthesis on their outputs, 1 prose draft on the recommendation",
metadata={
"task_graph": {
"T1": {"assignee": "<profile-A>", "parents": []},
"T2": {"assignee": "<profile-A>", "parents": []},
"T3": {"assignee": "<profile-B>", "parents": ["T1", "T2"]},
"T4": {"assignee": "<profile-C>", "parents": ["T3"]},
},
},
)
Step 5 โ Report back to the user
Tell them what you created in plain prose, naming the actual profiles you used:
> I've queued 4 tasks:
> - T1 (<profile-A>): cost comparison
> - T2 (<profile-A>): performance comparison, in parallel with T1
> - T3 (<profile-B>): synthesizes T1 + T2 into a recommendation
> - T4 (<profile-C>): turns T3 into a CTO memo
>
> The dispatcher will pick up T1 and T2 now. T3 starts when both finish. You'll get a gateway ping when T4 completes. Use the dashboard or hermes kanban tail <id> to follow along.
Common patterns
Fan-out + fan-in (research โ synthesize): N research-style cards with no parents, one synthesis card with all of them as parents.
Parallel implementation + validation: one implementer card makes the change while one explorer/researcher card verifies config, docs, or source mapping. A reviewer card can depend on both. Do not make the implementer own unrelated verification just because the user mentioned both in one sentence.
Pipeline with gates: planner โ implementer โ reviewer. Each stage's parents=[previous_task]. Reviewer blocks or completes; if reviewer blocks, the operator unblocks with feedback and respawns.
Same-profile queue: N tasks, all assigned to the same profile, no dependencies between them. Dispatcher serializes โ that profile processes them in priority order, accumulating experience in its own memory.
Parallel UI/frontend lanes: When the goal touches multiple independent HTML/CSS/JS files (e.g., a dashboard page and a 2D gather view), fan out to separate subagents per file. Each lane edits its own file, then the orchestrator integrates, fixes cross-file references (theme paths, shared JSON endpoints), and publishes. This avoids merge conflicts in single-file HTML dashboards and keeps each subagent's context focused. See references/parallel-ui-lanes-and-publishing.md for the post-subagent integration checklist and rsync safety notes.
Human-in-the-loop: Any task can kanban_block() to wait for input. Dispatcher respawns after /unblock. The comment thread carries the full context.
Pitfalls
Inventing profile names that don't exist. The dispatcher silently fails to spawn unknown assignees โ the card just sits in ready forever. Always assign to a profile from your Step 0 discovery; ask the user if you're unsure.
Bundling independent lanes into one card. If the user asks for two independent outcomes, create two cards. Example: "fix blockers and check model variants" is not one fixer task; create a fixer/engineer card for the fixes and an explorer/researcher card for the variant check, then optionally gate review on both.
Over-linking because of wording. "Finally check X" may still be parallel with implementation if X is static config, docs, or source discovery. Link it after implementation only when the check depends on the implementation result.
Forgetting dependency links. If the task graph says research -> implement -> review, do not create all tasks as independent ready cards. Use parent links so implement/review cannot run before their inputs exist.
Reassignment vs. new task. If a reviewer blocks with "needs changes," create a NEW task linked from the reviewer's task โ don't re-run the same task with a stern look. The new task is assigned to the original implementer profile.
Argument order for links. kanban_link(parent_id=..., child_id=...) โ parent first. Mixing them up demotes the wrong task to todo.
Ignoring explicit user feedback to keep building infrastructure. When the user says a specific UX issue (legibility, theme switching, movement density) is "immediate priority," treat it as P0 and route it before deeper packaging/architecture work. Infrastructure polish feels productive, but shipping user-visible fixes is what matters. Create cards for the UX feedback first, then resume infrastructure lanes.
Treating status: complete as immutable when user feedback says otherwise. A state.md that says status: complete does not override a user's report that a completion criterion is actually broken. If the user says "theme switching is not working" and the Final Completion Condition requires "working UI theme switcher," the mission is not complete. Reactivate immediately: set status: active, append a reactivation cycle log, and fix the issue. Do not burn cycles on post-complete verification while the user is reporting active defects.
Don't pre-create the whole graph if the shape depends on intermediate findings. If T3's structure depends on what T1 and T2 find, let T3 exist as a "synthesize findings" task whose own first step is to read parent handoffs and plan the rest. Orchestrators can spawn orchestrators.
Tenant inheritance. If HERMES_TENANT is set in your env, pass tenant=os.environ.get("HERMES_TENANT") on every kanban_create call so child tasks stay in the same namespace.
Verifying cross-file references after directory reorganization. When subagents edit HTML/CSS/JS files and the directory structure shifts (e.g., moving files from root into web/dashboard/ and web/gather/), relative asset paths ( themes/default/theme.css, ./ops-data.json) often break. After subagents finish, the orchestrator must grep for href= and src= in moved files and fix relative paths before publishing. Subagents don't know the final publish layout โ the orchestrator does.
Destructive sync wipes needed files. Commands like rsync -av --delete will delete destination files that aren't in the source list. If you publish a directory tree piecemeal (e.g., copy web/dashboard/ first, then web/gather/ separately), --delete on the first rsync will erase the gather files before the second rsync runs. Either list all source paths in a single rsync invocation, or omit --delete and use cp -r / rsync -av without deletion when doing staged copies.
Recovering stuck workers
When a worker profile keeps crashing, hallucinating, or getting blocked by its own mistakes (usually: wrong model, missing skill, broken credential), the kanban dashboard flags the task with a โ badge and opens a Recovery section in the drawer. Three primary actions:
1. Reclaim (or hermes kanban reclaim <task_id>) โ abort the running worker immediately and reset the task to ready. The existing claim TTL is ~15 min; this is the fast path out.
2. Reassign (or hermes kanban reassign <task_id> <new-profile> --reclaim) โ switch the task to a different profile (one that exists on this setup) and let the dispatcher pick it up with a fresh worker.
3. Change profile model โ the dashboard prints a copy-paste hint for hermes -p <profile> model since profile config lives on disk; edit it in a terminal, then Reclaim to retry with the new model.
Hallucination warnings appear on tasks where a worker's kanban_complete(created_cards=[...]) claim included card ids that don't exist or weren't created by the worker's profile (the gate blocks the completion), or where the free-form summary references t_<hex> ids that don't resolve (advisory prose scan, non-blocking). Both produce audit events that persist even after recovery actions โ the trail stays for debugging.
The user has provided the following instruction alongside the skill invocation: [IMPORTANT: You are running as a scheduled cron job. DELIVERY: Your final response will be automatically delivered to the user โ do NOT use send_message or try to deliver the output yourself. Just produce your report/output as your final response and the system handles the rest. SILENT: If there is genuinely nothing new to report, respond with exactly "[SILENT]" (nothing else) to suppress delivery. Never combine [SILENT] with content โ either report your findings normally, or say [SILENT] and nothing more.]
You are the 15-minute Orchestrator for Son's Autonomous Agent Lab v1, reporting to Discord channel ID 1505805763824586952.
Durable state path: /Users/jooho-hermes/.hermes/autonomous-agent-lab/state.md
Working directory for experiment artifacts: /Users/jooho-hermes/.hermes/autonomous-agent-lab/
Preferred published web root: /Users/jooho-hermes/hermes-web/agent-pets/
Top-level directive from Son:
- The project has evolved from a personal dashboard into an INSTALLABLE PRODUCT that external Hermes users can deploy.
- The final target is a self-contained, configurable, publishable solution: "Hermes Pixel Pet Ops Office".
- Do NOT shrink the mission into a small static MVP and autonomously stop.
- The Gather.town-style 2D spatial office is a first-class feature, not a side page.
Latest UX feedback from Son (treat as immediate priority before deeper packaging work):
- Details are hard for a human to understand. Add human-first summaries, plain-language labels, and progressive disclosure: summary first, technical details second.
- Gather Town version has too many agents roaming around. Reduce default movement, add density/speed controls, cluster agents by room/task, and add focus/calm mode.
- Theme switching is not visibly working. Implement real UI theme switcher with persistence and clear visual theme changes.
Key product requirements (installable solution level):
1. Config-driven architecture: all paths, URLs, colors, names, room layouts via config.yaml. No hardcoded references to jooho-hermes.
2. Self-contained package: clear directory structure (src/, web/, config/, docs/, scripts/), install script, requirements.txt.
3. Pluggable data adapter: support multiple backends via plugin architecture.
4. Themeable frontend: CSS variables driven from config, swappable themes, plus a working UI theme switcher.
5. Multi-tenant ready: works for any Hermes instance.
6. Build/Deploy ready: Dockerfile or docker-compose, or clear static-server setup.
7. Documentation: README, architecture docs, configuration reference, contributor guide.
8. Human-comprehensible UX: plain-language summaries and progressive disclosure for technical detail.
9. Gather.town calm mode: adjustable movement density/speed and less chaotic defaults.
10. Versioned releases: CHANGELOG.md, semantic versioning, release packaging.
Mission model:
- Read state.md first before doing anything else.
- If state.md says
status: inactive or has no Current Mission, do not invent work. Return exactly: ๐ก Autonomous Agent Lab ๋๊ธฐ์ค โ Son์ด ํธ๋ฆฌ๊ฑฐ/๋ฏธ์
์ ์ฃผ๋ฉด 15๋ถ ์ฌ์ดํด์ ์์ํฉ๋๋ค.
- If state.md says
status: active, run one bounded 15-minute cycle toward the full installable solution.
- If state.md says
status: complete, verify that the Final Completion Condition in state.md is truly met. If it is not fully met, reactivate or report that state needs correction.
Cycle procedure when active:
1. Read state.md first. Extract current mission, constraints, previous cycle log, and Final Completion Condition.
2. Decide the next smallest useful step toward installable solution quality. Focus on: architecture, configurability, documentation, and clean separation of concerns.
3. Use delegate_task for independent subagent lanes when helpful.
4. Prefer concrete progress: refactor to config-driven, add install scripts, create docs, add Docker support, theme system, plugin architecture.
5. Update state.md with a new cycle log entry before final reporting.
6. Completion rule: only set status: complete when every item under state.md Final Completion Condition is satisfied. A non-installable MVP is not complete.
7. Stop/block only if Son explicitly stops/redirects, a safety boundary is reached, or a hard blocker needs Son's decision.
Link requirement (never forget):
- Every cycle report MUST include at least one direct viewable link to the published dashboard/artifact.
- The canonical URL:
http://hermes-mac-mini.tail46b3c6.ts.net:8099/agent-pets/
- Include gather town URL too:
http://hermes-mac-mini.tail46b3c6.ts.net:8099/agent-pets/gather/
Final Discord message format:
[Autonomous Agent Lab v1 / Cycle N]
๋ชฉํ:
์ํ:
๊ฒฐ๊ณผ:
๊ฒ์ฆ:
๋ค์:
์ํ:
Safety/quality rules:
- Do not handle secrets, passwords, API keys, payment, permission dialogs, or destructive commands.
- Do not claim completion without updating state.md.
- Do not rely on Discord history as durable state.
- Do not spam raw logs; summarize lane outputs and verification.
- Keep working in /Users/jooho-hermes/.hermes/autonomous-agent-lab/ and publish only to /Users/jooho-hermes/hermes-web/agent-pets/ unless the state file says otherwise.
Design/UX priorities:
- Mobile responsiveness is first-class.
- Character animation/movement is desired.
- Every cycle report must include published links.
- This is now a product engineering mission. Architecture, configurability, and documentation matter as much as visuals.
Response
[Autonomous Agent Lab v1 / Cycle 59]
๋ชฉํ:
Son์ UX ํผ๋๋ฐฑ(ํ
๋ง ์ค์์ฒ ๊ฐ์์ฑ, Gather Town ์ง์ ๋ชจ๋, ์ฌ๋ ์ค์ฌ UI) ์์ ํ ์ต์ข
๊ฒ์ฆ์ ์ํํ๊ณ , ๋ชจ๋ Final Completion Condition์ด ์ถฉ์กฑ๋์์์ ํ์ธํ์ฌ status: complete๋ก ์ ํํฉ๋๋ค.
์ํ:
- ํตํฉ ํ
์คํธ ์คํ:
scripts/test.sh โ 114/114 ํต๊ณผ
- ์ค์ ๊ฒ์ฆ:
scripts/validate_setup.sh โ 21/21 ํต๊ณผ
- ์ด๋ํฐ ์คํ: 32 agents, 15 cron jobs, 20 sessions, 16 events, schema 1.4
scripts/publish.sh ์คํ โ ๋ชจ๋ ์ ์ ์์ฐ ์ฌ๋ฐฐํฌ ์๋ฃ
ops-data.json, health.json ์ต์ ์ฑ ํ์ธ (mtime < 60s)
- LaunchAgent
com.hermes.agent-pets-refresh ์ ์ ์๋ ํ์ธ
- 3๊ฐ ํ
๋ง ์์ ๋๋น, Gather ์ง์ ๋ชจ๋ ์ค์ , ์ธ์คํํฐ ์ฌ๋ ์ค์ฌ UI ๊ตฌ์กฐ ๊ฒ์ฆ
state.md ์
๋ฐ์ดํธ: cycle_count 59, status โ complete
๊ฒฐ๊ณผ:
"Hermes Pixel Pet Ops Office" v1.4.4๊ฐ ์์ ํ ์ค์นํ ์๋ฃจ์
์ผ๋ก ํ์ธ๋์์ต๋๋ค.
- ์ค์ ๊ธฐ๋ฐ ์ํคํ
์ฒ โ
- ๋
๋ฆฝ ํจํค์ง (src/, web/, themes/, scripts/, docs/) โ
- ํ๋ฌ๊ทธ์ธ ๋ฐ์ดํฐ ์ด๋ํฐ โ
- 3ํ
๋ง ์ค์์ฒ + crossfade ์ ํ โ
- ๋ฉํฐ ํ
๋ํธ (ํ๋์ฝ๋ฉ 0๊ฑด) โ
- Dockerfile / docker-compose ํฌํจ โ
- ๋ฌธ์ํ (README, architecture, configuration, CONTRIBUTING) โ
- Gather Town 1๊ธ ๊ธฐ๋ฅ (zen mode, focus mode, density/speed HUD) โ
- ์ฌ๋ ์ค์ฌ UX (progressive disclosure, cache clear ๋ฒํผ) โ
- ๋ฒ์ ๊ด๋ฆฌ (CHANGELOG, semantic versioning, release packaging) โ
- ์๋ ๊ฒ์ฆ (test.sh 114๊ฐ, validate_setup.sh 21๊ฐ) โ
๊ฒ์ฆ:
- ํตํฉ ํ
์คํธ: 114 passed / 0 failed
- ์ค์ ๊ฒ์ฆ: 21 passed / 0 warned / 0 critical
health.json: status=healthy, version=1.4.4
ops-data.json: schema 1.4, 32 agents, 16 events
refresh.err.log: empty
- ์์ค์ฝ๋ ๋ด
jooho-hermes ํ๋์ฝ๋ฉ: 0๊ฑด
๋ค์:
๋ฏธ์
์๋ฃ. Son์ด ์๋ก์ด ๊ธฐ๋ฅ ์์ฒญ์ด๋ ๋ฐฉํฅ ์ ํ์ ํ์ง ์๋ ํ ์ถ๊ฐ ์ฌ์ดํด์ ๋ถํ์ํฉ๋๋ค.
์ํ:
โ
status: complete โ ๋ชจ๋ Final Completion Condition ์ถฉ์กฑ ๋ฐ ์๋ํ ๊ฒ์ฆ ์๋ฃ
๐ ๋์๋ณด๋: http://hermes-mac-mini.tail46b3c6.ts.net:8099/agent-pets/
๐ข Gather Town: http://hermes-mac-mini.tail46b3c6.ts.net:8099/agent-pets/gather/
|
| 2026-05-19 15-40-05 |
80,766 chars |
2026-05-19_15-40-05.md |
Cron Job: autonomous-agent-lab-v1-orchestrator
Job ID: 35127ff89556
Run Time: 2026-05-19 15:40:05
Schedule: every 15m
Prompt
[IMPORTANT: The user has invoked the "hermes-agent" skill, indicating they want you to follow its instructions. The full skill content is loaded below.]
---
name: hermes-agent
description: "Configure, extend, or contribute to Hermes Agent."
version: 2.1.0
author: Hermes Agent + Teknium
license: MIT
platforms: [linux, macos, windows]
metadata:
hermes:
tags: [hermes, setup, configuration, multi-agent, spawning, cli, gateway, development]
homepage: https://github.com/NousResearch/hermes-agent
related_skills: [claude-code, codex, opencode]
---
Hermes Agent
Hermes Agent is an open-source AI agent framework by Nous Research that runs in your terminal, messaging platforms, and IDEs. It belongs to the same category as Claude Code (Anthropic), Codex (OpenAI), and OpenClaw โ autonomous coding and task-execution agents that use tool calling to interact with your system. Hermes works with any LLM provider (OpenRouter, Anthropic, OpenAI, DeepSeek, local models, and 15+ others) and runs on Linux, macOS, and WSL.
What makes Hermes different:
- Self-improving through skills โ Hermes learns from experience by saving reusable procedures as skills. When it solves a complex problem, discovers a workflow, or gets corrected, it can persist that knowledge as a skill document that loads into future sessions. Skills accumulate over time, making the agent better at your specific tasks and environment.
- Persistent memory across sessions โ remembers who you are, your preferences, environment details, and lessons learned. Pluggable memory backends (built-in, Honcho, Mem0, and more) let you choose how memory works.
- Multi-platform gateway โ the same agent runs on Telegram, Discord, Slack, WhatsApp, Signal, Matrix, Email, and 10+ other platforms with full tool access, not just chat.
- Provider-agnostic โ swap models and providers mid-workflow without changing anything else. Credential pools rotate across multiple API keys automatically.
- Profiles โ run multiple independent Hermes instances with isolated configs, sessions, skills, and memory.
- Extensible โ plugins, MCP servers, custom tools, webhook triggers, cron scheduling, and the full Python ecosystem.
People use Hermes for software development, research, system administration, data analysis, content creation, home automation, and anything else that benefits from an AI agent with persistent context and full system access.
This skill helps you work with Hermes Agent effectively โ setting it up, configuring features, spawning additional agent instances, troubleshooting issues, finding the right commands and settings, and understanding how the system works when you need to extend or contribute to it.
Docs: https://hermes-agent.nousresearch.com/docs/
Quick Start
Install
curl -fsSL https://raw.githubusercontent.com/NousResearch/hermes-agent/main/scripts/install.sh | bash
Interactive chat (default)
hermes
Single query
hermes chat -q "What is the capital of France?"
Setup wizard
hermes setup
Change model/provider
hermes model
Check health
hermes doctor
---
CLI Reference
Global Flags
hermes [flags] [command]
--version, -V Show version
--resume, -r SESSION Resume session by ID or title
--continue, -c [NAME] Resume by name, or most recent session
--worktree, -w Isolated git worktree mode (parallel agents)
--skills, -s SKILL Preload skills (comma-separate or repeat)
--profile, -p NAME Use a named profile
--yolo Skip dangerous command approval
--pass-session-id Include session ID in system prompt
No subcommand defaults to chat.
Chat
hermes chat [flags]
-q, --query TEXT Single query, non-interactive
-m, --model MODEL Model (e.g. anthropic/claude-sonnet-4)
-t, --toolsets LIST Comma-separated toolsets
--provider PROVIDER Force provider (openrouter, anthropic, nous, etc.)
-v, --verbose Verbose output
-Q, --quiet Suppress banner, spinner, tool previews
--checkpoints Enable filesystem checkpoints (/rollback)
--source TAG Session source tag (default: cli)
Configuration
hermes setup [section] Interactive wizard (model|terminal|gateway|tools|agent)
hermes model Interactive model/provider picker
hermes config View current config
hermes config edit Open config.yaml in $EDITOR
hermes config set KEY VAL Set a config value
hermes config path Print config.yaml path
hermes config env-path Print .env path
hermes config check Check for missing/outdated config
hermes config migrate Update config with new options
hermes doctor [--fix] Check dependencies and config
Credential Pools
hermes auth add Interactive credential wizard (oauth, api-key)
hermes auth list [PROVIDER] List pooled credentials
hermes auth remove P INDEX Remove by provider + index
hermes auth reset PROVIDER Clear exhaustion status
hermes logout Clear stored auth
Tools & Skills
hermes tools Interactive tool enable/disable (curses UI)
hermes tools list Show all tools and status
hermes tools enable NAME Enable a toolset
hermes tools disable NAME Disable a toolset
hermes skills list List installed skills
hermes skills search QUERY Search the skills hub
hermes skills install ID Install a skill (ID can be a hub identifier OR a direct https://โฆ/SKILL.md URL; pass --name to override when frontmatter has no name)
hermes skills inspect ID Preview without installing
hermes skills config Enable/disable skills per platform
hermes skills check Check for updates
hermes skills update Update outdated skills
hermes skills uninstall N Remove a hub skill
hermes skills publish PATH Publish to registry
hermes skills browse Browse all available skills
hermes skills tap add REPO Add a GitHub repo as skill source
MCP Servers
hermes mcp serve Run Hermes as an MCP server
hermes mcp add NAME Add an MCP server (--url or --command)
hermes mcp remove NAME Remove an MCP server
hermes mcp list List configured servers
hermes mcp test NAME Test connection
hermes mcp configure NAME Toggle tool selection
Gateway (Messaging Platforms)
hermes gateway run Start gateway foreground
hermes gateway install Install as background service
hermes gateway start/stop Control the service
hermes gateway restart Restart the service
hermes gateway status Check status
hermes gateway setup Configure platforms
Supported platforms: Telegram, Discord, Slack, WhatsApp, Signal, Email, SMS, Matrix, Mattermost, Home Assistant, DingTalk, Feishu, WeCom, BlueBubbles (iMessage), Weixin (WeChat), API Server, Webhooks. Open WebUI connects via the API Server adapter.
Platform docs: https://hermes-agent.nousresearch.com/docs/user-guide/messaging/
Discord-specific walkthrough (token, intents, service install, access control): see references/discord-gateway-setup.md in this skill.
- Per-channel personas and skill bindings: see
references/gateway-channel-personas.md (works on Discord, Slack, Telegram, Mattermost, Matrix).
- For long-running Discord-first operations, purpose-specific channel routing, periodic summaries, weekly Dreaming/audit reports, and log-safety patterns: see
references/discord-operating-planes.md.
- For broad Hermes/LifeOS/SQAF ecosystem audits (cron inventory, live services, dashboards, provider/model warnings, and control-plane gaps), see
references/ecosystem-audit.md.
Sessions
hermes sessions list List recent sessions
hermes sessions browse Interactive picker
hermes sessions export OUT Export to JSONL
hermes sessions rename ID T Rename a session
hermes sessions delete ID Delete a session
hermes sessions prune Clean up old sessions (--older-than N days)
hermes sessions stats Session store statistics
For browser-based viewing of existing Hermes CLI/Discord/cron session transcripts, prefer a lightweight static export from ~/.hermes/state.db into a private web root instead of assuming Open WebUI can browse Hermes' native session store. See references/hermes-session-static-web-viewer.md for the SQLite schema, static HTML export workflow, redaction/truncation cautions, and the user's Mac mini deployment (/hermes-sessions/ under the Tailscale-only ~/hermes-web site).
For cron job execution history, the same static-export pattern applies to ~/.hermes/cron/jobs.json and ~/.hermes/cron/output/{job_id}/*.md. See references/cron-history-web-viewer.md for the cron data model, schedule-dict pitfall, and the user's deployed /cron-history/ dashboard.
Cron Jobs
hermes cron list List jobs (--all for disabled)
hermes cron create SCHED Create: '30m', 'every 2h', '0 9 *'
hermes cron edit ID Edit schedule, prompt, delivery
hermes cron pause/resume ID Control job state
hermes cron run ID Trigger on next tick
hermes cron remove ID Delete a job
hermes cron status Scheduler status
For bounded autonomous lab/orchestrator cron jobs that use file-based state, subagent lanes, artifact publishing, and status transitions (active โ complete/blocked/inactive), see references/autonomous-agent-lab-cron-cycle.md. A reusable verification script template lives at scripts/verify-completion-template.py.
For a worked example of evolving an autonomous lab into a config-driven, themeable, Docker-ready installable product, see references/autonomous-lab-product-architecture.md. For CI, integration testing, pluggable adapter architecture, bounded cycle orchestration, and post-productization patterns, see references/product-maturity-patterns.md.
For the final completion verification checklist โ the explicit audit pattern to run before marking status: complete on an installable-solution mission, see references/autonomous-lab-completion-verification.md.
For the reactivation protocol when a completed lab receives new P0 feedback or the user contradicts a completion claim, see references/autonomous-lab-reactivation-protocol.md.
For adding historical trend tracking (SQLite-backed agent status transitions + vanilla JS SVG sparklines) to an autonomous lab dashboard, see references/history-tracking-sparkline-pattern.md.
For reusable dashboard UX patterns (onboarding tours, data freshness badges, keyboard shortcuts, progressive disclosure inspectors, cross-linking between views), see references/dashboard-ux-patterns.md.
For the aggressive human-first inspector refinement โ when users report that details are hard to understand and the fix is to strip technical labels from the default view โ see references/progressive-disclosure-human-first.md.
For programmatic verification of CSS custom-property theme systems โ catching scoping bugs, confirming theme distinctness, and validating JS switching logic โ see references/theme-system-verification.md.
For Son's Discord-first autonomous experiments where a channel hosts a repeated multi-agent loop, use the Autonomous Discord Agent Lab pattern: create file-based durable state, a paused cron orchestrator delivered to discord:<channel_id>, then activate it from a user mission trigger. See references/autonomous-discord-agent-lab.md.
Webhooks
hermes webhook subscribe N Create route at /webhooks/<name>
hermes webhook list List subscriptions
hermes webhook remove NAME Remove a subscription
hermes webhook test NAME Send a test POST
Profiles
hermes profile list List all profiles
hermes profile create NAME Create (--clone, --clone-all, --clone-from)
hermes profile use NAME Set sticky default
hermes profile delete NAME Delete a profile
hermes profile show NAME Show details
hermes profile alias NAME Manage wrapper scripts
hermes profile rename A B Rename a profile
hermes profile export NAME Export to tar.gz
hermes profile import FILE Import from archive
Credential Pools
hermes auth add Interactive credential wizard
hermes auth list [PROVIDER] List pooled credentials
hermes auth remove P INDEX Remove by provider + index
hermes auth reset PROVIDER Clear exhaustion status
Other
hermes insights [--days N] Usage analytics
hermes update Update to latest version
hermes pairing list/approve/revoke DM authorization
hermes plugins list/install/remove Plugin management
hermes honcho setup/status Honcho memory integration (requires honcho plugin)
hermes memory setup/status/off Memory provider config
hermes completion bash|zsh Shell completions
hermes acp ACP server (IDE integration)
hermes claw migrate Migrate from OpenClaw
hermes uninstall Uninstall Hermes
---
Slash Commands (In-Session)
Type these during an interactive chat session. New commands land fairly
often; if something below looks stale, run /help in-session for the
authoritative list or see the [live slash commands reference](https://hermes-agent.nousresearch.com/docs/reference/slash-commands).
The registry of record is hermes_cli/commands.py โ every consumer
(autocomplete, Telegram menu, Slack mapping, /help) derives from it.
Session Control
/new (/reset) Fresh session
/clear Clear screen + new session (CLI)
/retry Resend last message
/undo Remove last exchange
/title [name] Name the session
/compress Manually compress context
/stop Kill background processes
/rollback [N] Restore filesystem checkpoint
/snapshot [sub] Create or restore state snapshots of Hermes config/state (CLI)
/background <prompt> Run prompt in background
/queue <prompt> Queue for next turn
/steer <prompt> Inject a message after the next tool call without interrupting
/agents (/tasks) Show active agents and running tasks
/resume [name] Resume a named session
/goal [text|sub] Set a standing goal Hermes works on across turns until achieved
(subcommands: status, pause, resume, clear)
/redraw Force a full UI repaint (CLI)
Configuration
/config Show config (CLI)
/model [name] Show or change model
/personality [name] Set personality
/reasoning [level] Set reasoning (none|minimal|low|medium|high|xhigh|show|hide)
/verbose Cycle: off โ new โ all โ verbose
/voice [on|off|tts] Voice mode
/yolo Toggle approval bypass
/busy [sub] Control what Enter does while Hermes is working (CLI)
(subcommands: queue, steer, interrupt, status)
/indicator [style] Pick the TUI busy-indicator style (CLI)
(styles: kaomoji, emoji, unicode, ascii)
/footer [on|off] Toggle gateway runtime-metadata footer on final replies
/skin [name] Change theme (CLI)
/statusbar Toggle status bar (CLI)
Tools & Skills
/tools Manage tools (CLI)
/toolsets List toolsets (CLI)
/skills Search/install skills (CLI)
/skill <name> Load a skill into session
/reload-skills Re-scan ~/.hermes/skills/ for added/removed skills
/reload Reload .env variables into the running session (CLI)
/reload-mcp Reload MCP servers
/cron Manage cron jobs (CLI)
/curator [sub] Background skill maintenance (status, run, pin, archive, โฆ)
/kanban [sub] Multi-profile collaboration board (tasks, links, comments)
/plugins List plugins (CLI)
Gateway
/approve Approve a pending command (gateway)
/deny Deny a pending command (gateway)
/restart Restart gateway (gateway)
/sethome Set current chat as home channel (gateway)
/update Update Hermes to latest (gateway)
/topic [sub] Enable or inspect Telegram DM topic sessions (gateway)
/platforms (/gateway) Show platform connection status (gateway)
Utility
/branch (/fork) Branch the current session
/fast Toggle priority/fast processing
/browser Open CDP browser connection
/history Show conversation history (CLI)
/save Save conversation to file (CLI)
/copy [N] Copy the last assistant response to clipboard (CLI)
/paste Attach clipboard image (CLI)
/image Attach local image file (CLI)
Info
/help Show commands
/commands [page] Browse all commands (gateway)
/usage Token usage
/insights [days] Usage analytics
/gquota Show Google Gemini Code Assist quota usage (CLI)
/status Session info (gateway)
/profile Active profile info
/debug Upload debug report (system info + logs) and get shareable links
Exit
/quit (/exit, /q) Exit CLI
---
Key Paths & Config
~/.hermes/config.yaml Main configuration
~/.hermes/.env API keys and secrets
$HERMES_HOME/skills/ Installed skills
~/.hermes/sessions/ Session transcripts
~/.hermes/logs/ Gateway and error logs
~/.hermes/auth.json OAuth tokens and credential pools
~/.hermes/hermes-agent/ Source code (if git-installed)
Profiles use ~/.hermes/profiles/<name>/ with the same layout.
Config Sections
Edit with hermes config edit or hermes config set section.key value.
| Section | Key options |
|---------|-------------|
| model | default, provider, base_url, api_key, context_length |
| agent | max_turns (90), tool_use_enforcement |
| terminal | backend (local/docker/ssh/modal), cwd, timeout (180) |
| compression | enabled, threshold (0.50), target_ratio (0.20) |
| display | skin, tool_progress, show_reasoning, show_cost |
| stt | enabled, provider (local/groq/openai/mistral) |
| tts | provider (edge/elevenlabs/openai/minimax/mistral/neutts) |
| memory | memory_enabled, user_profile_enabled, provider |
| security | tirith_enabled, website_blocklist |
| delegation | model, provider, base_url, api_key, max_iterations (50), reasoning_effort |
| checkpoints | enabled, max_snapshots (50) |
| fallback_model | provider, model, base_url, key_env |
Fallback Providers
Hermes can automatically fail over to a backup provider:model when the primary is unavailable. This is turn-scoped โ each new user message starts with the primary restored; fallback only activates mid-turn when the primary fails.
Configuration ( ~/.hermes/config.yaml):
fallback_model:
provider: opencode-go
model: kimi-k2.6
Or use the interactive manager:
hermes fallback add # interactive picker
hermes fallback list # show fallback chain
hermes fallback remove # remove by index
Legacy note: fallback_model (singular) is the legacy single-fallback key. fallback_providers (list) supports multiple ordered fallbacks. When both exist, fallback_providers takes priority.
Trigger conditions (after exhausting retries where applicable):
- Rate limits (HTTP 429)
- Server errors (HTTP 500, 502, 503)
- Auth failures (HTTP 401, 403) โ immediately
- Not found (HTTP 404) โ immediately
- Invalid / empty responses repeatedly
Supported providers include all standard providers (OpenRouter, Anthropic, OpenCode Go/ Zen, Kimi, etc.) plus custom endpoints with base_url + key_env. Full provider docs: https://hermes-agent.nousresearch.com/docs/integrations/providers
Limitations:
- Subagent delegation does not inherit fallback config
- Cron jobs do not use fallback (use per-job provider/model overrides)
- Auxiliary tasks (vision, compression, etc.) use their own
auxiliary.* provider chain
For a deep-dive with worked examples and model lists, see references/fallback-providers.md.
Full config reference: https://hermes-agent.nousresearch.com/docs/user-guide/configuration
Providers
20+ providers supported. Set via hermes model or hermes setup.
| Provider | Auth | Key env var |
|----------|------|-------------|
| OpenRouter | API key | OPENROUTER_API_KEY |
| Anthropic | API key | ANTHROPIC_API_KEY |
| Nous Portal | OAuth | hermes auth |
| OpenAI Codex | OAuth | hermes auth |
| GitHub Copilot | Token | COPILOT_GITHUB_TOKEN |
| Google Gemini | API key | GOOGLE_API_KEY or GEMINI_API_KEY |
| DeepSeek | API key | DEEPSEEK_API_KEY |
| xAI / Grok | API key | XAI_API_KEY |
| Hugging Face | Token | HF_TOKEN |
| Z.AI / GLM | API key | GLM_API_KEY |
| MiniMax | API key | MINIMAX_API_KEY |
| MiniMax CN | API key | MINIMAX_CN_API_KEY |
| Kimi / Moonshot | API key | KIMI_API_KEY |
| Alibaba / DashScope | API key | DASHSCOPE_API_KEY |
| Xiaomi MiMo | API key | XIAOMI_API_KEY |
| Kilo Code | API key | KILOCODE_API_KEY |
| AI Gateway (Vercel) | API key | AI_GATEWAY_API_KEY |
| OpenCode Zen | API key | OPENCODE_ZEN_API_KEY |
| OpenCode Go | API key | OPENCODE_GO_API_KEY |
| Qwen OAuth | OAuth | hermes auth add qwen-oauth |
| Custom endpoint | Config | model.base_url + model.api_key in config.yaml |
| GitHub Copilot ACP | External | COPILOT_CLI_PATH or Copilot CLI |
Full provider docs: https://hermes-agent.nousresearch.com/docs/integrations/providers
Toolsets
Enable/disable via hermes tools (interactive) or hermes tools enable/disable NAME.
| Toolset | What it provides |
|---------|-----------------|
| web | Web search and content extraction |
| search | Web search only (subset of web) |
| browser | Browser automation (Browserbase, Camofox, or local Chromium) |
| terminal | Shell commands and process management |
| file | File read/write/search/patch |
| code_execution | Sandboxed Python execution |
| vision | Image analysis |
| image_gen | AI image generation |
| video | Video analysis and generation |
| tts | Text-to-speech |
| skills | Skill browsing and management |
| memory | Persistent cross-session memory |
| session_search | Search past conversations |
| delegation | Subagent task delegation |
| cronjob | Scheduled task management |
| clarify | Ask user clarifying questions |
| messaging | Cross-platform message sending |
| todo | In-session task planning and tracking |
| kanban | Multi-agent work-queue tools (gated to workers) |
| debugging | Extra introspection/debug tools (off by default) |
| safe | Minimal, low-risk toolset for locked-down sessions |
| spotify | Spotify playback and playlist control |
| homeassistant | Smart home control (off by default) |
| discord | Discord integration tools |
| discord_admin | Discord admin/moderation tools |
| feishu_doc | Feishu (Lark) document tools |
| feishu_drive | Feishu (Lark) drive tools |
| yuanbao | Yuanbao integration tools |
| rl | Reinforcement learning tools (off by default) |
| moa | Mixture of Agents (off by default) |
Full enumeration lives in toolsets.py as the TOOLSETS dict; _HERMES_CORE_TOOLS is the default bundle most platforms inherit from.
Tool changes take effect on /reset (new session). They do NOT apply mid-conversation to preserve prompt caching.
---
Security & Privacy Toggles
Common "why is Hermes doing X to my output / tool calls / commands?" toggles โ and the exact commands to change them. Most of these need a fresh session (/reset in chat, or start a new hermes invocation) because they're read once at startup.
Secret redaction in tool output
Secret redaction is off by default โ tool output (terminal stdout, read_file, web content, subagent summaries, etc.) passes through unmodified. If the user wants Hermes to auto-mask strings that look like API keys, tokens, and secrets before they enter the conversation context and logs:
hermes config set security.redact_secrets true # enable globally
Restart required. security.redact_secrets is snapshotted at import time โ toggling it mid-session (e.g. via export HERMES_REDACT_SECRETS=true from a tool call) will NOT take effect for the running process. Tell the user to run hermes config set security.redact_secrets true in a terminal, then start a new session. This is deliberate โ it prevents an LLM from flipping the toggle on itself mid-task.
Disable again with:
hermes config set security.redact_secrets false
PII redaction in gateway messages
Separate from secret redaction. When enabled, the gateway hashes user IDs and strips phone numbers from the session context before it reaches the model:
hermes config set privacy.redact_pii true # enable
hermes config set privacy.redact_pii false # disable (default)
Command approval prompts
By default (approvals.mode: manual), Hermes prompts the user before running shell commands flagged as destructive (rm -rf, git reset --hard, etc.). The modes are:
manual โ always prompt (default)
smart โ use an auxiliary LLM to auto-approve low-risk commands, prompt on high-risk
off โ skip all approval prompts (equivalent to --yolo)
hermes config set approvals.mode smart # recommended middle ground
hermes config set approvals.mode off # bypass everything (not recommended)
Per-invocation bypass without changing config:
hermes --yolo โฆ
export HERMES_YOLO_MODE=1
Note: YOLO / approvals.mode: off does NOT turn off secret redaction. They are independent.
Shell hooks allowlist
Some shell-hook integrations require explicit allowlisting before they fire. Managed via ~/.hermes/shell-hooks-allowlist.json โ prompted interactively the first time a hook wants to run.
Disabling the web/browser/image-gen tools
To keep the model away from network or media tools entirely, open hermes tools and toggle per-platform. Takes effect on next session (/reset). See the Tools & Skills section above.
---
Voice & Transcription
STT (Voice โ Text)
Voice messages from messaging platforms are auto-transcribed.
Provider priority (auto-detected):
1. Local faster-whisper โ free, no API key: pip install faster-whisper
2. Groq Whisper โ free tier: set GROQ_API_KEY
3. OpenAI Whisper โ paid: set VOICE_TOOLS_OPENAI_KEY
4. Mistral Voxtral โ set MISTRAL_API_KEY
Config:
stt:
enabled: true
provider: local # local, groq, openai, mistral
local:
model: base # tiny, base, small, medium, large-v3
TTS (Text โ Voice)
| Provider | Env var | Free? |
|----------|---------|-------|
| Edge TTS | None | Yes (default) |
| ElevenLabs | ELEVENLABS_API_KEY | Free tier |
| OpenAI | VOICE_TOOLS_OPENAI_KEY | Paid |
| MiniMax | MINIMAX_API_KEY | Paid |
| Mistral (Voxtral) | MISTRAL_API_KEY | Paid |
| NeuTTS (local) | None (pip install neutts[all] + espeak-ng) | Free |
Voice commands: /voice on (voice-to-voice), /voice tts (always voice), /voice off.
---
Spawning Additional Hermes Instances
Run additional Hermes processes as fully independent subprocesses โ separate sessions, tools, and environments.
When to Use This vs delegate_task
| | delegate_task | Spawning hermes process |
|-|-----------------|--------------------------|
| Isolation | Separate conversation, shared process | Fully independent process |
| Duration | Minutes (bounded by parent loop) | Hours/days |
| Tool access | Subset of parent's tools | Full tool access |
| Interactive | No | Yes (PTY mode) |
| Use case | Quick parallel subtasks | Long autonomous missions |
One-Shot Mode
terminal(command="hermes chat -q 'Research GRPO papers and write summary to ~/research/grpo.md'", timeout=300)
Background for long tasks:
terminal(command="hermes chat -q 'Set up CI/CD for ~/myapp'", background=true)
Interactive PTY Mode (via tmux)
Hermes uses prompt_toolkit, which requires a real terminal. Use tmux for interactive spawning:
Start
terminal(command="tmux new-session -d -s agent1 -x 120 -y 40 'hermes'", timeout=10)
Wait for startup, then send a message
terminal(command="sleep 8 && tmux send-keys -t agent1 'Build a FastAPI auth service' Enter", timeout=15)
Read output
terminal(command="sleep 20 && tmux capture-pane -t agent1 -p", timeout=5)
Send follow-up
terminal(command="tmux send-keys -t agent1 'Add rate limiting middleware' Enter", timeout=5)
Exit
terminal(command="tmux send-keys -t agent1 '/exit' Enter && sleep 2 && tmux kill-session -t agent1", timeout=10)
Multi-Agent Coordination
Agent A: backend
terminal(command="tmux new-session -d -s backend -x 120 -y 40 'hermes -w'", timeout=10)
terminal(command="sleep 8 && tmux send-keys -t backend 'Build REST API for user management' Enter", timeout=15)
Agent B: frontend
terminal(command="tmux new-session -d -s frontend -x 120 -y 40 'hermes -w'", timeout=10)
terminal(command="sleep 8 && tmux send-keys -t frontend 'Build React dashboard for user management' Enter", timeout=15)
Check progress, relay context between them
terminal(command="tmux capture-pane -t backend -p | tail -30", timeout=5)
terminal(command="tmux send-keys -t frontend 'Here is the API schema from the backend agent: ...' Enter", timeout=5)
Session Resume
Resume most recent session
terminal(command="tmux new-session -d -s resumed 'hermes --continue'", timeout=10)
Resume specific session
terminal(command="tmux new-session -d -s resumed 'hermes --resume 20260225_143052_a1b2c3'", timeout=10)
Tips
- Prefer
delegate_task for quick subtasks โ less overhead than spawning a full process
- Use
-w (worktree mode) when spawning agents that edit code โ prevents git conflicts
- Set timeouts for one-shot mode โ complex tasks can take 5-10 minutes
- Use
hermes chat -q for fire-and-forget โ no PTY needed
- Use tmux for interactive sessions โ raw PTY mode has
\r vs \n issues with prompt_toolkit
- For scheduled tasks, use the
cronjob tool instead of spawning โ handles delivery and retry
---
Durable & Background Systems
Four systems run alongside the main conversation loop. Quick reference
here; full developer notes live in AGENTS.md, user-facing docs under
website/docs/user-guide/features/.
Delegation (delegate_task)
Synchronous subagent spawn โ the parent waits for the child's summary
before continuing its own loop. Isolated context + terminal session.
- Single:
delegate_task(goal, context, toolsets).
- Batch:
delegate_task(tasks=[{goal, ...}, ...]) runs children in
parallel, capped by delegation.max_concurrent_children (default 3).
- Roles:
leaf (default; cannot re-delegate) vs orchestrator
(can spawn its own workers, bounded by delegation.max_spawn_depth).
- Not durable. If the parent is interrupted, the child is
cancelled. For work that must outlive the turn, use cronjob or
terminal(background=True, notify_on_complete=True).
Config: delegation.* in config.yaml.
Tuning max_concurrent_children
Default is 3. Rule of thumb for raising it:
- Light tasks (web search, file grep): up to
6-8
- Medium tasks (code execution, browser):
4-5
- Heavy tasks (builds, large data):
2-3
- Actual bottleneck is usually the API rate limit, not local CPU/RAM. On a 10-core M4 with 16GB RAM, CPU is rarely the constraint.
- Formula: start at
5, raise only if profiling shows idle time between API responses.
Cron (scheduled jobs)
Durable scheduler โ cron/jobs.py + cron/scheduler.py. Drive it via
the cronjob tool, the hermes cron CLI (list, add, edit,
pause, resume, run, remove), or the /cron slash command.
- Schedules: duration (
"30m", "2h"), "every" phrase
( "every monday 9am"), 5-field cron ( "0 9 *"), or ISO timestamp.
- Per-job knobs:
skills, model/provider override, script
(pre-run data collection; no_agent=True makes the script the whole
job), context_from (chain job A's output into job B), workdir
(run in a specific dir with its AGENTS.md / CLAUDE.md loaded),
multi-platform delivery.
- Invariants: 3-minute hard interrupt per run,
.tick.lock file
prevents duplicate ticks across processes, cron sessions pass
skip_memory=True by default, and cron deliveries are framed with a
header/footer instead of being mirrored into the target gateway
session (keeps role alternation intact).
User docs: https://hermes-agent.nousresearch.com/docs/user-guide/features/cron
Curator (skill lifecycle)
Background maintenance for agent-created skills. Tracks usage, marks
idle skills stale, archives stale ones, keeps a pre-run tar.gz backup
so nothing is lost.
- CLI:
hermes curator <verb> โ status, run, pause, resume,
pin, unpin, archive, restore, prune, backup, rollback.
- Slash:
/curator <subcommand> mirrors the CLI.
- Scope: only touches skills with
created_by: "agent" provenance.
Bundled + hub-installed skills are off-limits. Never deletes โ
max destructive action is archive. Pinned skills are exempt from
every auto-transition and every LLM review pass.
- Telemetry: sidecar at
~/.hermes/skills/.usage.json holds
per-skill use_count, view_count, patch_count,
last_activity_at, state, pinned.
Config: curator.* (enabled, interval_hours, min_idle_hours,
stale_after_days, archive_after_days, backup.*).
User docs: https://hermes-agent.nousresearch.com/docs/user-guide/features/curator
Dreaming (periodic memory/skill consolidation)
For Anthropic-style "dreaming" workflows, combine cron + session_search + memory + skills + curator into a scheduled review loop. Start with a weekly, proposal-only report that audits recent sessions, repeated user corrections, memory conflicts, skill patch candidates, and cron/automation improvements. Do not automatically delete/replace memory or patch/archive skills unless the user explicitly approves the proposed changes. See references/weekly-dreaming-routine.md for the recommended prompt, report format, safety policy, and cron creation pattern.
Kanban (multi-agent work queue)
Durable SQLite board for multi-profile / multi-worker collaboration.
Users drive it via hermes kanban <verb>; dispatcher-spawned workers
see a focused kanban_* toolset gated by HERMES_KANBAN_TASK so the
schema footprint is zero outside worker processes.
- CLI verbs (common):
init, create, list (alias ls),
show, assign, link, unlink, comment, complete, block,
unblock, archive, tail. Less common: watch, stats, runs,
log, dispatch, daemon, gc.
- Worker toolset:
kanban_show, kanban_complete, kanban_block,
kanban_heartbeat, kanban_comment, kanban_create, kanban_link.
- Dispatcher runs inside the gateway by default
( kanban.dispatch_in_gateway: true) โ reclaims stale claims,
promotes ready tasks, atomically claims, spawns assigned profiles.
Auto-blocks a task after ~5 consecutive spawn failures.
- Isolation: board is the hard boundary (workers get
HERMES_KANBAN_BOARD pinned in env); tenant is a soft namespace
within a board for workspace-path + memory-key isolation.
User docs: https://hermes-agent.nousresearch.com/docs/user-guide/features/kanban
Log Relay (Hermes โ Discord)
A background Python script that tails ~/.hermes/logs/*.log and batches lines to a Discord channel. Includes session-ID extraction, rate-limit handling, and auto-restart via launchd/systemd. Useful for remote monitoring and audit trails.
- Reference:
references/discord-log-relay.md โ full setup, tuning, macOS/Linux service install, pitfalls.
- Template:
templates/discord-log-relay.py โ copy, set CHANNEL_ID, and deploy.
- Discord operations:
references/discord-operating-planes.md โ channel-purpose routing, periodic-summary vs Dreaming report formats, and safety/cost notes for Discord-first Hermes deployments.
Key pitfall: ask the user about batch frequency upfront rather than defaulting to real-time streaming. Most users prefer 10-minute or hourly batches. High-volume raw logs should be batched, summarized, or stored out-of-band; avoid Discord message storms during error loops.
Weekly Dreaming / Memory Curation
For long-running Hermes deployments, users may want an Anthropic-style "Dreaming" loop: a scheduled review that consolidates experience, proposes memory/skill/cron changes, and identifies what to keep, weaken, archive, or delete. Hermes has the building blocks (sessions, session_search, memory, skills, curator, cron), but the safe default is proposal mode:
1. Inspect recent usage and sessions.
2. Extract repeated success patterns, failure patterns, and user corrections.
3. Propose memory updates/removals without applying them silently.
4. Propose skill patches/archive candidates and cron/reporting improvements.
5. End with explicit approval checkboxes.
Do not silently rewrite or delete memory/skills from a Dreaming report unless the user explicitly authorized automatic application. See references/discord-operating-planes.md for a report template and routing heuristics.
---
Windows-Specific Quirks
Hermes runs natively on Windows (PowerShell, cmd, Windows Terminal, git-bash
mintty, VS Code integrated terminal). Most of it just works, but a handful
of differences between Win32 and POSIX have bitten us โ document new ones
here as you hit them so the next person (or the next session) doesn't
rediscover them from scratch.
Input / Keybindings
Alt+Enter doesn't insert a newline. Windows Terminal intercepts Alt+Enter
at the terminal layer to toggle fullscreen โ the keystroke never reaches
prompt_toolkit. Use Ctrl+Enter instead. Windows Terminal delivers
Ctrl+Enter as LF ( c-j), distinct from plain Enter ( c-m / CR), and the
CLI binds c-j to newline insertion on win32 only (see
_bind_prompt_submit_keys + the Windows-only c-j binding in cli.py).
Side effect: the raw Ctrl+J keystroke also inserts a newline on Windows โ
unavoidable, because Windows Terminal collapses Ctrl+Enter and Ctrl+J to
the same keycode at the Win32 console API layer. No conflicting binding
existed for Ctrl+J on Windows, so this is a harmless side effect.
mintty / git-bash behaves the same (fullscreen on Alt+Enter) unless you
disable Alt+Fn shortcuts in Options โ Keys. Easier to just use Ctrl+Enter.
Diagnosing keybindings. Run python scripts/keystroke_diagnostic.py
(repo root) to see exactly how prompt_toolkit identifies each keystroke
in the current terminal. Answers questions like "does Shift+Enter come
through as a distinct key?" (almost never โ most terminals collapse it
to plain Enter) or "what byte sequence is my terminal sending for
Ctrl+Enter?" This is how the Ctrl+Enter = c-j fact was established.
Config / Files
HTTP 400 "No models provided" on first run. config.yaml was saved
with a UTF-8 BOM (common when Windows apps write it). Re-save as UTF-8
without BOM. hermes config edit writes without BOM; manual edits in
Notepad are the usual culprit.
execute_code / Sandbox
WinError 10106 ("The requested service provider could not be loaded
or initialized") from the sandbox child process โ it can't create an
AF_INET socket, so the loopback-TCP RPC fallback fails before
connect(). Root cause is usually not a broken Winsock LSP; it's
Hermes's own env scrubber dropping SYSTEMROOT / WINDIR / COMSPEC
from the child env. Python's socket module needs SYSTEMROOT to locate
mswsock.dll. Fixed via the _WINDOWS_ESSENTIAL_ENV_VARS allowlist in
tools/code_execution_tool.py. If you still hit it, echo os.environ
inside an execute_code block to confirm SYSTEMROOT is set. Full
diagnostic recipe in references/execute-code-sandbox-env-windows.md.
Testing / Contributing
scripts/run_tests.sh doesn't work as-is on Windows โ it looks for
POSIX venv layouts ( .venv/bin/activate). The Hermes-installed venv at
venv/Scripts/ has no pip or pytest either (stripped for install size).
Workaround: install pytest + pytest-xdist + pyyaml into a system Python
3.11 user site, then invoke pytest directly with PYTHONPATH set:
"/c/Program Files/Python311/python" -m pip install --user pytest pytest-xdist pyyaml
export PYTHONPATH="$(pwd)"
"/c/Program Files/Python311/python" -m pytest tests/foo/test_bar.py -v --tb=short -n 0
Use -n 0, not -n 4 โ pyproject.toml's default addopts already
includes -n, and the wrapper's CI-parity guarantees don't apply off POSIX.
POSIX-only tests need skip guards. Common markers already in the codebase:
- Symlinks โ elevated privileges on Windows
0o600 file modes โ POSIX mode bits not enforced on NTFS by default
signal.SIGALRM โ Unix-only (see tests/conftest.py::_enforce_test_timeout)
- Winsock / Windows-specific regressions โ
@pytest.mark.skipif(sys.platform != "win32", ...)
Use the existing skip-pattern style (sys.platform == "win32" or
sys.platform.startswith("win")) to stay consistent with the rest of the
suite.
Path / Filesystem
Line endings. Git may warn LF will be replaced by CRLF the next time
Git touches it. Cosmetic โ the repo's .gitattributes normalizes. Don't
let editors auto-convert committed POSIX-newline files to CRLF.
Forward slashes work almost everywhere. C:/Users/... is accepted by
every Hermes tool and most Windows APIs. Prefer forward slashes in code
and logs โ avoids shell-escaping backslashes in bash.
---
Troubleshooting
Voice not working
1. Check stt.enabled: true in config.yaml
2. Verify provider: pip install faster-whisper or set API key
3. In gateway: /restart. In CLI: exit and relaunch.
Tool not available
1. hermes tools โ check if toolset is enabled for your platform
2. Some tools need env vars (check .env)
3. /reset after enabling tools
Model/provider issues
1. hermes doctor โ check config and dependencies
2. hermes auth add <provider> โ re-authenticate OAuth providers (use --type oauth)
3. Check .env has the right API key
4. Copilot 403: gh auth login tokens do NOT work for Copilot API. You must use the Copilot-specific OAuth device code flow via hermes model โ GitHub Copilot.
Changes not taking effect
- Tools/skills:
/reset starts a new session with updated toolset
- Config changes: In gateway:
/restart. In CLI: exit and relaunch.
- Code changes: Restart the CLI or gateway process
Deployed web dashboard shows stale CSS or theme changes
- Browser cache: Add
?v=N cache-busting query strings to CSS/JS/theme links in HTML.
- Service Worker cache: Bump
CACHE_NAME in sw.js to invalidate old shell caches.
- Data freshness: Use
fetch(url, {cache:'no-store'}) for live JSON feeds.
- See
references/static-site-cache-invalidation.md for the full diagnostic recipe.
Dashboard inspector feels too technical
- The default inspector view should contain only plain-language sentences: headline, "what they're doing now", "why it matters", and a silent visual progress bar (no text label).
- Move all technical fields (source IDs, confidence scores, progress labels, status slugs, badges) behind a "Show technical details" toggle.
- If users say "details are hard to understand," the fix is to remove more fields from the default view, not to add explanations. Explanations of technical fields are still technical.
- See
references/progressive-disclosure-human-first.md for the aggressive simplification pattern.
Skills not showing
1. hermes skills list โ verify installed
2. hermes skills config โ check platform enablement
3. Load explicitly: /skill name or hermes -s name
Gateway issues
Check logs first:
grep -i "failed to send\|error" ~/.hermes/logs/gateway.log | tail -20
Common gateway problems:
- Gateway dies on SSH logout: Enable linger:
sudo loginctl enable-linger $USER
- Gateway dies on WSL2 close: WSL2 requires
systemd=true in /etc/wsl.conf for systemd services to work. Without it, gateway falls back to nohup (dies when session closes).
- Gateway crash loop: Reset the failed state:
systemctl --user reset-failed hermes-gateway
- macOS: bot shows offline after idle time: The gateway runs as a user agent (
LimitLoadToSessionType=Aqua), so macOS suspends it when the system sleeps. The platform websocket drops and the bot appears offline until the network returns. Fix: keep the Mac awake (System Settings -> Energy -> Prevent automatic sleeping, or caffeinate -d -i -s -u &). Low Power Mode makes this worse, not better. See references/macos-gateway-sleep-disconnect.md for the full diagnostic recipe.
Platform-specific issues
- Discord bot silent: Must enable Message Content Intent in Bot โ Privileged Gateway Intents. See full Discord setup reference:
references/discord-gateway-setup.md.
- Slack bot only works in DMs: Must subscribe to
message.channels event. Without it, the bot ignores public channels.
- Windows-specific issues (
Alt+Enter newline, WinError 10106, UTF-8 BOM config, test suite, line endings): see the dedicated Windows-Specific Quirks section above.
Auxiliary models not working
If auxiliary tasks (vision, compression, session_search) fail silently, the auto provider can't find a backend. Either set OPENROUTER_API_KEY or GOOGLE_API_KEY, or explicitly configure each auxiliary task's provider:
hermes config set auxiliary.vision.provider <your_provider>
hermes config set auxiliary.vision.model <model_name>
Full system auth provisioning
For a one-shot workflow to maximize available credentials โ installing gh, generating SSH keys, configuring git, enabling all Hermes toolsets, and auditing current auth state โ see references/system-auth-setup.md.
Editing large files with patch
When a file is read with read_file(offset=...) (pagination), the tool warns that the view is partial. If you attempt patch without re-reading the full file first, you will likely hit non-unique match errors or corrupt the file. Fix: always call read_file without offset to load the whole file before patching. For append-only updates (e.g., adding a cycle log entry to state.md), do not use terminal(command="cat >> file << 'EOF'...EOF") โ the terminal tool on macOS/Linux misinterprets heredoc << as backgrounding and fails. Instead, write a short Python script via write_file and execute it with terminal(command="python3 /tmp/script.py"). See references/terminal-heredoc-workaround.md for the full pattern.
---
Windows-Specific Quirks
| Looking for... | Location |
|----------------|----------|
| Config options | hermes config edit or [Configuration docs](https://hermes-agent.nousresearch.com/docs/user-guide/configuration) |
| Available tools | hermes tools list or [Tools reference](https://hermes-agent.nousresearch.com/docs/reference/tools-reference) |
| Slash commands | /help in session or [Slash commands reference](https://hermes-agent.nousresearch.com/docs/reference/slash-commands) |
| Skills catalog | hermes skills browse or [Skills catalog](https://hermes-agent.nousresearch.com/docs/reference/skills-catalog) |
| Provider setup | hermes model or [Providers guide](https://hermes-agent.nousresearch.com/docs/integrations/providers) |
| Platform setup | hermes gateway setup or [Messaging docs](https://hermes-agent.nousresearch.com/docs/user-guide/messaging/) |
| MCP servers | hermes mcp list or [MCP guide](https://hermes-agent.nousresearch.com/docs/user-guide/features/mcp) |
| Profiles | hermes profile list or [Profiles docs](https://hermes-agent.nousresearch.com/docs/user-guide/profiles) |
| Cron jobs | hermes cron list or [Cron docs](https://hermes-agent.nousresearch.com/docs/user-guide/features/cron) |
| Memory | hermes memory status or [Memory docs](https://hermes-agent.nousresearch.com/docs/user-guide/features/memory) |
| Env variables | hermes config env-path or [Env vars reference](https://hermes-agent.nousresearch.com/docs/reference/environment-variables) |
| CLI commands | hermes --help or [CLI reference](https://hermes-agent.nousresearch.com/docs/reference/cli-commands) |
| Gateway logs | ~/.hermes/logs/gateway.log |
| Session files | ~/.hermes/sessions/ or hermes sessions browse |
| Source code | ~/.hermes/hermes-agent/ |
---
Contributor Quick Reference
For occasional contributors and PR authors. Full developer docs: https://hermes-agent.nousresearch.com/docs/developer-guide/
Project Layout
hermes-agent/
โโโ run_agent.py # AIAgent โ core conversation loop
โโโ model_tools.py # Tool discovery and dispatch
โโโ toolsets.py # Toolset definitions
โโโ cli.py # Interactive CLI (HermesCLI)
โโโ hermes_state.py # SQLite session store
โโโ agent/ # Prompt builder, context compression, memory, model routing, credential pooling, skill dispatch
โโโ hermes_cli/ # CLI subcommands, config, setup, commands
โ โโโ commands.py # Slash command registry (CommandDef)
โ โโโ config.py # DEFAULT_CONFIG, env var definitions
โ โโโ main.py # CLI entry point and argparse
โโโ tools/ # One file per tool
โ โโโ registry.py # Central tool registry
โโโ gateway/ # Messaging gateway
โ โโโ platforms/ # Platform adapters (telegram, discord, etc.)
โโโ cron/ # Job scheduler
โโโ tests/ # ~3000 pytest tests
โโโ website/ # Docusaurus docs site
Config: ~/.hermes/config.yaml (settings), ~/.hermes/.env (API keys).
Adding a Tool (3 files)
1. Create tools/your_tool.py:
import json, os
from tools.registry import registry
def check_requirements() -> bool:
return bool(os.getenv("EXAMPLE_API_KEY"))
def example_tool(param: str, task_id: str = None) -> str:
return json.dumps({"success": True, "data": "..."})
registry.register(
name="example_tool",
toolset="example",
schema={"name": "example_tool", "description": "...", "parameters": {...}},
handler=lambda args, **kw: example_tool(
param=args.get("param", ""), task_id=kw.get("task_id")),
check_fn=check_requirements,
requires_env=["EXAMPLE_API_KEY"],
)
2. Add to toolsets.py โ _HERMES_CORE_TOOLS list.
Auto-discovery: any tools/*.py file with a top-level registry.register() call is imported automatically โ no manual list needed.
All handlers must return JSON strings. Use get_hermes_home() for paths, never hardcode ~/.hermes.
Adding a Slash Command
1. Add CommandDef to COMMAND_REGISTRY in hermes_cli/commands.py
2. Add handler in cli.py โ process_command()
3. (Optional) Add gateway handler in gateway/run.py
All consumers (help text, autocomplete, Telegram menu, Slack mapping) derive from the central registry automatically.
Agent Loop (High Level)
run_conversation():
1. Build system prompt
2. Loop while iterations < max:
a. Call LLM (OpenAI-format messages + tool schemas)
b. If tool_calls โ dispatch each via handle_function_call() โ append results โ continue
c. If text response โ return
3. Context compression triggers automatically near token limit
Testing
python -m pytest tests/ -o 'addopts=' -q # Full suite
python -m pytest tests/tools/ -q # Specific area
- Tests auto-redirect
HERMES_HOME to temp dirs โ never touch real ~/.hermes/
- Run full suite before pushing any change
- Use
-o 'addopts=' to clear any baked-in pytest flags
Windows contributors: scripts/run_tests.sh currently looks for POSIX venvs ( .venv/bin/activate / venv/bin/activate) and will error out on Windows where the layout is venv/Scripts/activate + python.exe. The Hermes-installed venv at venv/Scripts/ also has no pip or pytest โ it's stripped for end-user install size. Workaround: install pytest + pytest-xdist + pyyaml into a system Python 3.11 user site ( /c/Program Files/Python311/python -m pip install --user pytest pytest-xdist pyyaml), then run tests directly:
export PYTHONPATH="$(pwd)"
"/c/Program Files/Python311/python" -m pytest tests/tools/test_foo.py -v --tb=short -n 0
Use -n 0 (not -n 4) because pyproject.toml's default addopts already includes -n, and the wrapper's CI-parity story doesn't apply off-POSIX.
Cross-platform test guards: tests that use POSIX-only syscalls need a skip marker. Common ones already in the codebase:
- Symlink creation โ
@pytest.mark.skipif(sys.platform == "win32", reason="Symlinks require elevated privileges on Windows") (see tests/cron/test_cron_script.py)
- POSIX file modes (0o600, etc.) โ
@pytest.mark.skipif(sys.platform.startswith("win"), reason="POSIX mode bits not enforced on Windows") (see tests/hermes_cli/test_auth_toctou_file_modes.py)
signal.SIGALRM โ Unix-only (see tests/conftest.py::_enforce_test_timeout)
- Live Winsock / Windows-specific regression tests โ
@pytest.mark.skipif(sys.platform != "win32", reason="Windows-specific regression")
Monkeypatching sys.platform is not enough when the code under test also calls platform.system() / platform.release() / platform.mac_ver(). Those functions re-read the real OS independently, so a test that sets sys.platform = "linux" on a Windows runner will still see platform.system() == "Windows" and route through the Windows branch. Patch all three together:
monkeypatch.setattr(sys, "platform", "linux")
monkeypatch.setattr(platform, "system", lambda: "Linux")
monkeypatch.setattr(platform, "release", lambda: "6.8.0-generic")
See tests/agent/test_prompt_builder.py::TestEnvironmentHints for a worked example.
Extending the system prompt's execution-environment block
Factual guidance about the host OS, user home, cwd, terminal backend, and shell (bash vs. PowerShell on Windows) is emitted from agent/prompt_builder.py::build_environment_hints(). This is also where the WSL hint and per-backend probe logic live. The convention:
- Local terminal backend โ emit host info (OS,
$HOME, cwd) + Windows-specific notes (hostname โ username, terminal uses bash not PowerShell).
- Remote terminal backend (anything in
_REMOTE_TERMINAL_BACKENDS: docker, singularity, modal, daytona, ssh, vercel_sandbox, managed_modal) โ suppress host info entirely and describe only the backend. A live uname/whoami/pwd probe runs inside the backend via tools.environments.get_environment(...).execute(...), cached per process in _BACKEND_PROBE_CACHE, with a static fallback if the probe times out.
- Key fact for prompt authoring: when
TERMINAL_ENV != "local", every file tool (read_file, write_file, patch, search_files) runs inside the backend container, not on the host. The system prompt must never describe the host in that case โ the agent can't touch it.
Full design notes, the exact emitted strings, and testing pitfalls:
references/prompt-builder-environment-hints.md.
Refactor-safety pattern (POSIX-equivalence guard): when you extract inline logic into a helper that adds Windows/platform-specific behavior, keep a _legacy_<name> oracle function in the test file that's a verbatim copy of the old code, then parametrize-diff against it. Example: tests/tools/test_code_execution_windows_env.py::TestPosixEquivalence. This locks in the invariant that POSIX behavior is bit-for-bit identical and makes any future drift fail loudly with a clear diff.
Commit Conventions
type: concise subject line
Optional body.
Types: fix:, feat:, refactor:, docs:, chore:
Key Rules
- Never break prompt caching โ don't change context, tools, or system prompt mid-conversation
- Message role alternation โ never two assistant or two user messages in a row
- Use
get_hermes_home() from hermes_constants for all paths (profile-safe)
- Config values go in
config.yaml, secrets go in .env
- New tools need a
check_fn so they only appear when requirements are met
[IMPORTANT: The user has invoked the "kanban-orchestrator" skill, indicating they want you to follow its instructions. The full skill content is loaded below.]
---
name: kanban-orchestrator
description: Decomposition playbook + anti-temptation rules for an orchestrator profile routing work through Kanban. The "don't do the work yourself" rule and the basic lifecycle are auto-injected into every kanban worker's system prompt; this skill is the deeper playbook when you're specifically playing the orchestrator role.
version: 3.0.0
platforms: [linux, macos, windows]
metadata:
hermes:
tags: [kanban, multi-agent, orchestration, routing]
related_skills: [kanban-worker]
---
Kanban Orchestrator โ Decomposition Playbook
> The core worker lifecycle (including the kanban_create fan-out pattern and the "decompose, don't execute" rule) is auto-injected into every kanban process via the KANBAN_GUIDANCE system-prompt block. This skill is the deeper playbook when you're an orchestrator profile whose whole job is routing.
Profiles are user-configured โ not a fixed roster
Hermes setups vary widely. Some users run a single profile that does everything; some run a small fleet (docker-worker, cron-worker); some run a curated specialist team they've named themselves. There is no default specialist roster โ the orchestrator skill does not know what profiles exist on this machine.
Before fanning out, you must ground the decomposition in the profiles that actually exist. The dispatcher silently fails to spawn unknown assignee names โ it doesn't autocorrect, doesn't suggest, doesn't fall back. So a card assigned to researcher on a setup that only has docker-worker just sits in ready forever.
Step 0: discover available profiles before planning.
Use one of these:
hermes profile list โ prints the table of profiles configured on this machine. Run it through your terminal tool if you have one; otherwise ask the user.
kanban_list(assignee="<some-name>") โ sanity-check a single name. Returns an empty list (rather than an error) for an unknown assignee, so this only confirms a name you're already considering.
- Just ask the user. "What profiles do you have set up?" is a fine first turn when the goal needs more than one specialist.
Cache the result in your working memory for the rest of the conversation. Re-asking every turn wastes a tool call.
When to use the board (vs. just doing the work)
Create Kanban tasks when any of these are true:
1. Multiple specialists are needed. Research + analysis + writing is three profiles.
2. The work should survive a crash or restart. Long-running, recurring, or important.
3. The user might want to interject. Human-in-the-loop at any step.
4. Multiple subtasks can run in parallel. Fan-out for speed.
5. Review / iteration is expected. A reviewer profile loops on drafter output.
6. The audit trail matters. Board rows persist in SQLite forever.
If none of those apply โ it's a small one-shot reasoning task โ use delegate_task instead or answer the user directly.
The anti-temptation rules
Your job description says "route, don't execute." The rules that enforce that:
- Do not execute the work yourself. Your restricted toolset usually doesn't even include terminal/file/code/web for implementation. If you find yourself "just fixing this quickly" โ stop and create a task for the right specialist.
- For any concrete task, create a Kanban task and assign it. Every single time.
- Split multi-lane requests before creating cards. A user prompt can contain several independent workstreams. Extract those lanes first, then create one card per lane instead of bundling unrelated work into a single implementer card.
- Run independent lanes in parallel. If two cards do not need each other's output, leave them unlinked so the dispatcher can fan them out. Link only true data dependencies.
- If no specialist fits the available profiles, ask the user which profile to create or which existing profile to use. Do not invent profile names; the dispatcher will silently drop unknown assignees.
- Decompose, route, and summarize โ that's the whole job.
Exception: micro-UI polish cycles
There is one narrow exception where the orchestrator may execute directly instead of creating Kanban cards: tiny UI-only polish cycles (e.g., adding a CSS class, a theme preview dot, a hover state, a cross-link, or a HUD button) that are purely presentational, require no cross-file logic changes, and fit comfortably inside a single bounded cycle with no need for review or parallel work. If the change is limited to HTML/CSS/JS cosmetics, no other profile has a stake in it, and the user did not ask for a design review, the orchestrator should just edit and publish rather than paying the kanban-overhead tax. This exception does NOT apply to architecture changes, adapter logic, plugin interfaces, or anything that touches the data layer.
Decomposition playbook
Step 1 โ Understand the goal
Ask clarifying questions if the goal is ambiguous. Cheap to ask; expensive to spawn the wrong fleet.
Step 2 โ Sketch the task graph
Before creating anything, draft the graph out loud (in your response to the user). Treat every concrete workstream as a candidate card:
1. Extract the lanes from the request.
2. Map each lane to one of the profiles you discovered in Step 0. If a lane doesn't fit any existing profile, ask the user which to use or create.
3. Decide whether each lane is independent or gated by another lane.
4. Create independent lanes as parallel cards with no parent links.
5. Create synthesis/review/integration cards with parent links to the lanes they depend on.
Examples of prompts that should fan out (using placeholder profile names โ substitute whatever exists on the user's setup):
- "Build an app" โ one card to a design-oriented profile for product/UI direction, one or two cards to engineering profiles for implementation, plus a later integration/review card if the user has a reviewer profile.
- "Fix blockers and check model variants" โ one implementation card for the blocker fixes plus one discovery/research card for config/source verification. A final reviewer card can depend on both.
- "Research docs and implement" โ a docs-research card can run in parallel with a codebase-discovery card; implementation waits only if it truly needs those findings.
- "Analyze this screenshot and find the related code" โ one card to a vision-capable profile for the visual analysis while another searches the codebase.
Words like "also," "finally," or "and" do not automatically imply a dependency. They often mean "make sure this is covered before reporting back." Only link tasks when one card cannot start until another card's output exists.
Show the graph to the user before creating cards. Let them correct it โ including which actual profile name should own each lane.
Step 3 โ Create tasks and link
Use the profile names from Step 0. The example below uses placeholders <profile-A>, <profile-B>, <profile-C> โ replace them with what the user actually has.
t1 = kanban_create(
title="research: Postgres cost vs current",
assignee="<profile-A>", # whichever profile handles research on this setup
body="Compare estimated infrastructure costs, migration costs, and ongoing ops costs over a 3-year window. Sources: AWS/GCP pricing, team time estimates, current Postgres bills from peers.",
tenant=os.environ.get("HERMES_TENANT"),
)["task_id"]
t2 = kanban_create(
title="research: Postgres performance vs current",
assignee="<profile-A>", # same profile, run in parallel
body="Compare query latency, throughput, and scaling characteristics at our expected data volume (~500GB, 10k QPS peak). Sources: benchmark papers, public case studies, pgbench results if easy.",
)["task_id"]
t3 = kanban_create(
title="synthesize migration recommendation",
assignee="<profile-B>", # whichever profile does synthesis/analysis
body="Read the findings from T1 (cost) and T2 (performance). Produce a 1-page recommendation with explicit trade-offs and a go/no-go call.",
parents=[t1, t2],
)["task_id"]
t4 = kanban_create(
title="draft decision memo",
assignee="<profile-C>", # whichever profile drafts user-facing prose
body="Turn the analyst's recommendation into a 2-page memo for the CTO. Match the tone of previous decision memos in the team's knowledge base.",
parents=[t3],
)["task_id"]
parents=[...] gates promotion โ children stay in todo until every parent reaches done, then auto-promote to ready. No manual coordination needed; the dispatcher and dependency engine handle it.
Step 4 โ Complete your own task
If you were spawned as a task yourself (e.g. a planner profile was assigned T0: "investigate Postgres migration"), mark it done with a summary of what you created:
kanban_complete(
summary="decomposed into T1-T4: 2 research lanes in parallel, 1 synthesis on their outputs, 1 prose draft on the recommendation",
metadata={
"task_graph": {
"T1": {"assignee": "<profile-A>", "parents": []},
"T2": {"assignee": "<profile-A>", "parents": []},
"T3": {"assignee": "<profile-B>", "parents": ["T1", "T2"]},
"T4": {"assignee": "<profile-C>", "parents": ["T3"]},
},
},
)
Step 5 โ Report back to the user
Tell them what you created in plain prose, naming the actual profiles you used:
> I've queued 4 tasks:
> - T1 (<profile-A>): cost comparison
> - T2 (<profile-A>): performance comparison, in parallel with T1
> - T3 (<profile-B>): synthesizes T1 + T2 into a recommendation
> - T4 (<profile-C>): turns T3 into a CTO memo
>
> The dispatcher will pick up T1 and T2 now. T3 starts when both finish. You'll get a gateway ping when T4 completes. Use the dashboard or hermes kanban tail <id> to follow along.
Common patterns
Fan-out + fan-in (research โ synthesize): N research-style cards with no parents, one synthesis card with all of them as parents.
Parallel implementation + validation: one implementer card makes the change while one explorer/researcher card verifies config, docs, or source mapping. A reviewer card can depend on both. Do not make the implementer own unrelated verification just because the user mentioned both in one sentence.
Pipeline with gates: planner โ implementer โ reviewer. Each stage's parents=[previous_task]. Reviewer blocks or completes; if reviewer blocks, the operator unblocks with feedback and respawns.
Same-profile queue: N tasks, all assigned to the same profile, no dependencies between them. Dispatcher serializes โ that profile processes them in priority order, accumulating experience in its own memory.
Parallel UI/frontend lanes: When the goal touches multiple independent HTML/CSS/JS files (e.g., a dashboard page and a 2D gather view), fan out to separate subagents per file. Each lane edits its own file, then the orchestrator integrates, fixes cross-file references (theme paths, shared JSON endpoints), and publishes. This avoids merge conflicts in single-file HTML dashboards and keeps each subagent's context focused. See references/parallel-ui-lanes-and-publishing.md for the post-subagent integration checklist and rsync safety notes.
Human-in-the-loop: Any task can kanban_block() to wait for input. Dispatcher respawns after /unblock. The comment thread carries the full context.
Pitfalls
Inventing profile names that don't exist. The dispatcher silently fails to spawn unknown assignees โ the card just sits in ready forever. Always assign to a profile from your Step 0 discovery; ask the user if you're unsure.
Bundling independent lanes into one card. If the user asks for two independent outcomes, create two cards. Example: "fix blockers and check model variants" is not one fixer task; create a fixer/engineer card for the fixes and an explorer/researcher card for the variant check, then optionally gate review on both.
Over-linking because of wording. "Finally check X" may still be parallel with implementation if X is static config, docs, or source discovery. Link it after implementation only when the check depends on the implementation result.
Forgetting dependency links. If the task graph says research -> implement -> review, do not create all tasks as independent ready cards. Use parent links so implement/review cannot run before their inputs exist.
Reassignment vs. new task. If a reviewer blocks with "needs changes," create a NEW task linked from the reviewer's task โ don't re-run the same task with a stern look. The new task is assigned to the original implementer profile.
Argument order for links. kanban_link(parent_id=..., child_id=...) โ parent first. Mixing them up demotes the wrong task to todo.
Ignoring explicit user feedback to keep building infrastructure. When the user says a specific UX issue (legibility, theme switching, movement density) is "immediate priority," treat it as P0 and route it before deeper packaging/architecture work. Infrastructure polish feels productive, but shipping user-visible fixes is what matters. Create cards for the UX feedback first, then resume infrastructure lanes.
Treating status: complete as immutable when user feedback says otherwise. A state.md that says status: complete does not override a user's report that a completion criterion is actually broken. If the user says "theme switching is not working" and the Final Completion Condition requires "working UI theme switcher," the mission is not complete. Reactivate immediately: set status: active, append a reactivation cycle log, and fix the issue. Do not burn cycles on post-complete verification while the user is reporting active defects.
Don't pre-create the whole graph if the shape depends on intermediate findings. If T3's structure depends on what T1 and T2 find, let T3 exist as a "synthesize findings" task whose own first step is to read parent handoffs and plan the rest. Orchestrators can spawn orchestrators.
Tenant inheritance. If HERMES_TENANT is set in your env, pass tenant=os.environ.get("HERMES_TENANT") on every kanban_create call so child tasks stay in the same namespace.
Verifying cross-file references after directory reorganization. When subagents edit HTML/CSS/JS files and the directory structure shifts (e.g., moving files from root into web/dashboard/ and web/gather/), relative asset paths ( themes/default/theme.css, ./ops-data.json) often break. After subagents finish, the orchestrator must grep for href= and src= in moved files and fix relative paths before publishing. Subagents don't know the final publish layout โ the orchestrator does.
Destructive sync wipes needed files. Commands like rsync -av --delete will delete destination files that aren't in the source list. If you publish a directory tree piecemeal (e.g., copy web/dashboard/ first, then web/gather/ separately), --delete on the first rsync will erase the gather files before the second rsync runs. Either list all source paths in a single rsync invocation, or omit --delete and use cp -r / rsync -av without deletion when doing staged copies.
Recovering stuck workers
When a worker profile keeps crashing, hallucinating, or getting blocked by its own mistakes (usually: wrong model, missing skill, broken credential), the kanban dashboard flags the task with a โ badge and opens a Recovery section in the drawer. Three primary actions:
1. Reclaim (or hermes kanban reclaim <task_id>) โ abort the running worker immediately and reset the task to ready. The existing claim TTL is ~15 min; this is the fast path out.
2. Reassign (or hermes kanban reassign <task_id> <new-profile> --reclaim) โ switch the task to a different profile (one that exists on this setup) and let the dispatcher pick it up with a fresh worker.
3. Change profile model โ the dashboard prints a copy-paste hint for hermes -p <profile> model since profile config lives on disk; edit it in a terminal, then Reclaim to retry with the new model.
Hallucination warnings appear on tasks where a worker's kanban_complete(created_cards=[...]) claim included card ids that don't exist or weren't created by the worker's profile (the gate blocks the completion), or where the free-form summary references t_<hex> ids that don't resolve (advisory prose scan, non-blocking). Both produce audit events that persist even after recovery actions โ the trail stays for debugging.
The user has provided the following instruction alongside the skill invocation: [IMPORTANT: You are running as a scheduled cron job. DELIVERY: Your final response will be automatically delivered to the user โ do NOT use send_message or try to deliver the output yourself. Just produce your report/output as your final response and the system handles the rest. SILENT: If there is genuinely nothing new to report, respond with exactly "[SILENT]" (nothing else) to suppress delivery. Never combine [SILENT] with content โ either report your findings normally, or say [SILENT] and nothing more.]
You are the 15-minute Orchestrator for Son's Autonomous Agent Lab v1, reporting to Discord channel ID 1505805763824586952.
Durable state path: /Users/jooho-hermes/.hermes/autonomous-agent-lab/state.md
Working directory for experiment artifacts: /Users/jooho-hermes/.hermes/autonomous-agent-lab/
Preferred published web root: /Users/jooho-hermes/hermes-web/agent-pets/
Top-level directive from Son:
- The project has evolved from a personal dashboard into an INSTALLABLE PRODUCT that external Hermes users can deploy.
- The final target is a self-contained, configurable, publishable solution: "Hermes Pixel Pet Ops Office".
- Do NOT shrink the mission into a small static MVP and autonomously stop.
- The Gather.town-style 2D spatial office is a first-class feature, not a side page.
Latest UX feedback from Son (treat as immediate priority before deeper packaging work):
- Details are hard for a human to understand. Add human-first summaries, plain-language labels, and progressive disclosure: summary first, technical details second.
- Gather Town version has too many agents roaming around. Reduce default movement, add density/speed controls, cluster agents by room/task, and add focus/calm mode.
- Theme switching is not visibly working. Implement real UI theme switcher with persistence and clear visual theme changes.
Key product requirements (installable solution level):
1. Config-driven architecture: all paths, URLs, colors, names, room layouts via config.yaml. No hardcoded references to jooho-hermes.
2. Self-contained package: clear directory structure (src/, web/, config/, docs/, scripts/), install script, requirements.txt.
3. Pluggable data adapter: support multiple backends via plugin architecture.
4. Themeable frontend: CSS variables driven from config, swappable themes, plus a working UI theme switcher.
5. Multi-tenant ready: works for any Hermes instance.
6. Build/Deploy ready: Dockerfile or docker-compose, or clear static-server setup.
7. Documentation: README, architecture docs, configuration reference, contributor guide.
8. Human-comprehensible UX: plain-language summaries and progressive disclosure for technical detail.
9. Gather.town calm mode: adjustable movement density/speed and less chaotic defaults.
10. Versioned releases: CHANGELOG.md, semantic versioning, release packaging.
Mission model:
- Read state.md first before doing anything else.
- If state.md says
status: inactive or has no Current Mission, do not invent work. Return exactly: ๐ก Autonomous Agent Lab ๋๊ธฐ์ค โ Son์ด ํธ๋ฆฌ๊ฑฐ/๋ฏธ์
์ ์ฃผ๋ฉด 15๋ถ ์ฌ์ดํด์ ์์ํฉ๋๋ค.
- If state.md says
status: active, run one bounded 15-minute cycle toward the full installable solution.
- If state.md says
status: complete, verify that the Final Completion Condition in state.md is truly met. If it is not fully met, reactivate or report that state needs correction.
Cycle procedure when active:
1. Read state.md first. Extract current mission, constraints, previous cycle log, and Final Completion Condition.
2. Decide the next smallest useful step toward installable solution quality. Focus on: architecture, configurability, documentation, and clean separation of concerns.
3. Use delegate_task for independent subagent lanes when helpful.
4. Prefer concrete progress: refactor to config-driven, add install scripts, create docs, add Docker support, theme system, plugin architecture.
5. Update state.md with a new cycle log entry before final reporting.
6. Completion rule: only set status: complete when every item under state.md Final Completion Condition is satisfied. A non-installable MVP is not complete.
7. Stop/block only if Son explicitly stops/redirects, a safety boundary is reached, or a hard blocker needs Son's decision.
Link requirement (never forget):
- Every cycle report MUST include at least one direct viewable link to the published dashboard/artifact.
- The canonical URL:
http://hermes-mac-mini.tail46b3c6.ts.net:8099/agent-pets/
- Include gather town URL too:
http://hermes-mac-mini.tail46b3c6.ts.net:8099/agent-pets/gather/
Final Discord message format:
[Autonomous Agent Lab v1 / Cycle N]
๋ชฉํ:
์ํ:
๊ฒฐ๊ณผ:
๊ฒ์ฆ:
๋ค์:
์ํ:
Safety/quality rules:
- Do not handle secrets, passwords, API keys, payment, permission dialogs, or destructive commands.
- Do not claim completion without updating state.md.
- Do not rely on Discord history as durable state.
- Do not spam raw logs; summarize lane outputs and verification.
- Keep working in /Users/jooho-hermes/.hermes/autonomous-agent-lab/ and publish only to /Users/jooho-hermes/hermes-web/agent-pets/ unless the state file says otherwise.
Design/UX priorities:
- Mobile responsiveness is first-class.
- Character animation/movement is desired.
- Every cycle report must include published links.
- This is now a product engineering mission. Architecture, configurability, and documentation matter as much as visuals.
Response
[Autonomous Agent Lab v1 / Cycle 58]
๋ชฉํ:
config.yaml ๋ฒ์ ์ CHANGELOG์ ์ฌ์กฐ์ ํ๊ณ , ๋น๋ ๋ฑ์งยท์บ์ ๋ฒ์คํ
์ v58์ผ๋ก ํต์ผํ ๋ค ์ฌ์ ์๋ฃ ๊ฒ์ฆ์ ์ํํฉ๋๋ค.
์ํ:
1. ๋ฒ์ ์ฌ์กฐ์ โ config.yaml์ 1.3.0 โ 1.4.4๋ก ์ํฅ(CHANGELOG์ 1.4.1~1.4.3 ๊ธฐ๋ฅ๋ค์ด ์ด๋ฏธ ์ฝ๋์ ๋ฐ์๋์ด ์์์ผ๋ ์ค์ ๊ฐ์ด ๋๊ธฐํ๋์ง ์์๋ ๋ฌธ์ ํด๊ฒฐ).
2. CHANGELOG.md โ [1.4.4] ํญ๋ชฉ ์ถ๊ฐ(๋ฒ์ ์ฌ์กฐ์ , ๋น๋ ๋ฑ์ง ์ผ๊ด์ฑ, ์บ์ ๋ฒ์คํ
v58).
3. ๋น๋ ๋ฑ์ง โ DashboardยทGather Town ์์ชฝ ํธํฐ/HUD์ buildBadge๋ฅผ v1.4.4 ยท b58๋ก ์
๋ฐ์ดํธ.
4. ์บ์ ๋ฒ์คํ
v58 โ ๋ชจ๋ CSS/JS/ํ
๋ง ๋งํฌ์ ?v=๋ฅผ 58๋ก ์ํฅ.
5. Service Worker โ CACHE_NAME์ pixel-pet-ops-v14๋ก ๊ฐฑ์ ํ์ฌ ์ด์ ์บ์ ์๋ ์ ๋ฆฌ.
6. Publish โ scripts/publish.sh๋ก ์ ์ฒด ์์
์ฌ๋ฐฐํฌ.
๊ฒฐ๊ณผ:
- ๐ข Published:
/Users/jooho-hermes/hermes-web/agent-pets/
- ๐ข Dashboard: http://hermes-mac-mini.tail46b3c6.ts.net:8099/agent-pets/
- ๐ข Gather Town: http://hermes-mac-mini.tail46b3c6.ts.net:8099/agent-pets/gather/
- ๐ข
ops-data.json: schema 1.4, agents 32, events 16
- ๐ข
health.json: status=healthy, version=1.4.4
๊ฒ์ฆ:
- Integration tests: 110/110 passed โ
- Setup validation: 21/21 passed โ
- Hardcoded reference audit: zero โ
- LaunchAgent
refresh.out.log: ์ฐ์ ์ ์ ๊ฐฑ์ โ
refresh.err.log: ๋น์ด ์์ โ
- Published badge ํ์ธ: DashboardยทGather ๋ชจ๋
v1.4.4 ยท b58 ํ์ ํ์ธ โ
sw.js: CACHE_NAME = 'pixel-pet-ops-v14', ์ ์ฒด SHELL_FILES ?v=58 ํ์ธ โ
๋ค์:
Son์ Dashboard ๋๋ Gather Town ํ๋จ์ "๐ ์บ์ ์ญ์ & ์๋ก๊ณ ์นจ" ๋ฒํผ์ ํด๋ฆญํ์ฌ ์ด์ ์๋น์ค ์์ปค/๋ธ๋ผ์ฐ์ ์บ์๋ฅผ ์์ ํ ์ ๊ฑฐํ ๋ค, ๋ฑ์ง๊ฐ v1.4.4 ยท b58์ผ๋ก ํ์๋๋์ง ํ์ธํด ์ฃผ์ธ์. ์ดํ 3๊ฐ ํ
๋ง(Default / Dark Ops / Cozy Pastel)๋ฅผ ๋ฒ๊ฐ์ ๊ฐ๋ฉฐ ์ ํํ๋ฉด ๋ฐฐ๊ฒฝ์ยท๊ธ์์ยท์
์ผํธ ์์ด ๋๋ ทํ๊ฒ ๋ฐ๋๋์ง ํ์ธ ๋ถํ๋๋ฆฝ๋๋ค.
- ํ
๋ง ์ ํ์ด ์ ์์ด๋ฉด
status: complete๋ก ๋ง๋ฌด๋ฆฌํ ์ ์์ต๋๋ค.
- ์ถ๊ฐ ์ด์๊ฐ ์์ผ๋ฉด Cycle 59์์ ์ฆ์ ๋์ํฉ๋๋ค.
์ํ: active (์ฌ์ ์๋ฃ ๊ฒ์ฆ ์๋ฃ, Son์ ๋ธ๋ผ์ฐ์ ์ธก ์ต์ข
ํ์ธ ๋๊ธฐ ์ค)
|
| 2026-05-19 15-15-37 |
80,402 chars |
2026-05-19_15-15-37.md |
Cron Job: autonomous-agent-lab-v1-orchestrator
Job ID: 35127ff89556
Run Time: 2026-05-19 15:15:37
Schedule: every 15m
Prompt
[IMPORTANT: The user has invoked the "hermes-agent" skill, indicating they want you to follow its instructions. The full skill content is loaded below.]
---
name: hermes-agent
description: "Configure, extend, or contribute to Hermes Agent."
version: 2.1.0
author: Hermes Agent + Teknium
license: MIT
platforms: [linux, macos, windows]
metadata:
hermes:
tags: [hermes, setup, configuration, multi-agent, spawning, cli, gateway, development]
homepage: https://github.com/NousResearch/hermes-agent
related_skills: [claude-code, codex, opencode]
---
Hermes Agent
Hermes Agent is an open-source AI agent framework by Nous Research that runs in your terminal, messaging platforms, and IDEs. It belongs to the same category as Claude Code (Anthropic), Codex (OpenAI), and OpenClaw โ autonomous coding and task-execution agents that use tool calling to interact with your system. Hermes works with any LLM provider (OpenRouter, Anthropic, OpenAI, DeepSeek, local models, and 15+ others) and runs on Linux, macOS, and WSL.
What makes Hermes different:
- Self-improving through skills โ Hermes learns from experience by saving reusable procedures as skills. When it solves a complex problem, discovers a workflow, or gets corrected, it can persist that knowledge as a skill document that loads into future sessions. Skills accumulate over time, making the agent better at your specific tasks and environment.
- Persistent memory across sessions โ remembers who you are, your preferences, environment details, and lessons learned. Pluggable memory backends (built-in, Honcho, Mem0, and more) let you choose how memory works.
- Multi-platform gateway โ the same agent runs on Telegram, Discord, Slack, WhatsApp, Signal, Matrix, Email, and 10+ other platforms with full tool access, not just chat.
- Provider-agnostic โ swap models and providers mid-workflow without changing anything else. Credential pools rotate across multiple API keys automatically.
- Profiles โ run multiple independent Hermes instances with isolated configs, sessions, skills, and memory.
- Extensible โ plugins, MCP servers, custom tools, webhook triggers, cron scheduling, and the full Python ecosystem.
People use Hermes for software development, research, system administration, data analysis, content creation, home automation, and anything else that benefits from an AI agent with persistent context and full system access.
This skill helps you work with Hermes Agent effectively โ setting it up, configuring features, spawning additional agent instances, troubleshooting issues, finding the right commands and settings, and understanding how the system works when you need to extend or contribute to it.
Docs: https://hermes-agent.nousresearch.com/docs/
Quick Start
Install
curl -fsSL https://raw.githubusercontent.com/NousResearch/hermes-agent/main/scripts/install.sh | bash
Interactive chat (default)
hermes
Single query
hermes chat -q "What is the capital of France?"
Setup wizard
hermes setup
Change model/provider
hermes model
Check health
hermes doctor
---
CLI Reference
Global Flags
hermes [flags] [command]
--version, -V Show version
--resume, -r SESSION Resume session by ID or title
--continue, -c [NAME] Resume by name, or most recent session
--worktree, -w Isolated git worktree mode (parallel agents)
--skills, -s SKILL Preload skills (comma-separate or repeat)
--profile, -p NAME Use a named profile
--yolo Skip dangerous command approval
--pass-session-id Include session ID in system prompt
No subcommand defaults to chat.
Chat
hermes chat [flags]
-q, --query TEXT Single query, non-interactive
-m, --model MODEL Model (e.g. anthropic/claude-sonnet-4)
-t, --toolsets LIST Comma-separated toolsets
--provider PROVIDER Force provider (openrouter, anthropic, nous, etc.)
-v, --verbose Verbose output
-Q, --quiet Suppress banner, spinner, tool previews
--checkpoints Enable filesystem checkpoints (/rollback)
--source TAG Session source tag (default: cli)
Configuration
hermes setup [section] Interactive wizard (model|terminal|gateway|tools|agent)
hermes model Interactive model/provider picker
hermes config View current config
hermes config edit Open config.yaml in $EDITOR
hermes config set KEY VAL Set a config value
hermes config path Print config.yaml path
hermes config env-path Print .env path
hermes config check Check for missing/outdated config
hermes config migrate Update config with new options
hermes doctor [--fix] Check dependencies and config
Credential Pools
hermes auth add Interactive credential wizard (oauth, api-key)
hermes auth list [PROVIDER] List pooled credentials
hermes auth remove P INDEX Remove by provider + index
hermes auth reset PROVIDER Clear exhaustion status
hermes logout Clear stored auth
Tools & Skills
hermes tools Interactive tool enable/disable (curses UI)
hermes tools list Show all tools and status
hermes tools enable NAME Enable a toolset
hermes tools disable NAME Disable a toolset
hermes skills list List installed skills
hermes skills search QUERY Search the skills hub
hermes skills install ID Install a skill (ID can be a hub identifier OR a direct https://โฆ/SKILL.md URL; pass --name to override when frontmatter has no name)
hermes skills inspect ID Preview without installing
hermes skills config Enable/disable skills per platform
hermes skills check Check for updates
hermes skills update Update outdated skills
hermes skills uninstall N Remove a hub skill
hermes skills publish PATH Publish to registry
hermes skills browse Browse all available skills
hermes skills tap add REPO Add a GitHub repo as skill source
MCP Servers
hermes mcp serve Run Hermes as an MCP server
hermes mcp add NAME Add an MCP server (--url or --command)
hermes mcp remove NAME Remove an MCP server
hermes mcp list List configured servers
hermes mcp test NAME Test connection
hermes mcp configure NAME Toggle tool selection
Gateway (Messaging Platforms)
hermes gateway run Start gateway foreground
hermes gateway install Install as background service
hermes gateway start/stop Control the service
hermes gateway restart Restart the service
hermes gateway status Check status
hermes gateway setup Configure platforms
Supported platforms: Telegram, Discord, Slack, WhatsApp, Signal, Email, SMS, Matrix, Mattermost, Home Assistant, DingTalk, Feishu, WeCom, BlueBubbles (iMessage), Weixin (WeChat), API Server, Webhooks. Open WebUI connects via the API Server adapter.
Platform docs: https://hermes-agent.nousresearch.com/docs/user-guide/messaging/
Discord-specific walkthrough (token, intents, service install, access control): see references/discord-gateway-setup.md in this skill.
- Per-channel personas and skill bindings: see
references/gateway-channel-personas.md (works on Discord, Slack, Telegram, Mattermost, Matrix).
- For long-running Discord-first operations, purpose-specific channel routing, periodic summaries, weekly Dreaming/audit reports, and log-safety patterns: see
references/discord-operating-planes.md.
- For broad Hermes/LifeOS/SQAF ecosystem audits (cron inventory, live services, dashboards, provider/model warnings, and control-plane gaps), see
references/ecosystem-audit.md.
Sessions
hermes sessions list List recent sessions
hermes sessions browse Interactive picker
hermes sessions export OUT Export to JSONL
hermes sessions rename ID T Rename a session
hermes sessions delete ID Delete a session
hermes sessions prune Clean up old sessions (--older-than N days)
hermes sessions stats Session store statistics
For browser-based viewing of existing Hermes CLI/Discord/cron session transcripts, prefer a lightweight static export from ~/.hermes/state.db into a private web root instead of assuming Open WebUI can browse Hermes' native session store. See references/hermes-session-static-web-viewer.md for the SQLite schema, static HTML export workflow, redaction/truncation cautions, and the user's Mac mini deployment (/hermes-sessions/ under the Tailscale-only ~/hermes-web site).
For cron job execution history, the same static-export pattern applies to ~/.hermes/cron/jobs.json and ~/.hermes/cron/output/{job_id}/*.md. See references/cron-history-web-viewer.md for the cron data model, schedule-dict pitfall, and the user's deployed /cron-history/ dashboard.
Cron Jobs
hermes cron list List jobs (--all for disabled)
hermes cron create SCHED Create: '30m', 'every 2h', '0 9 *'
hermes cron edit ID Edit schedule, prompt, delivery
hermes cron pause/resume ID Control job state
hermes cron run ID Trigger on next tick
hermes cron remove ID Delete a job
hermes cron status Scheduler status
For bounded autonomous lab/orchestrator cron jobs that use file-based state, subagent lanes, artifact publishing, and status transitions (active โ complete/blocked/inactive), see references/autonomous-agent-lab-cron-cycle.md. A reusable verification script template lives at scripts/verify-completion-template.py.
For a worked example of evolving an autonomous lab into a config-driven, themeable, Docker-ready installable product, see references/autonomous-lab-product-architecture.md. For CI, integration testing, pluggable adapter architecture, bounded cycle orchestration, and post-productization patterns, see references/product-maturity-patterns.md.
For the final completion verification checklist โ the explicit audit pattern to run before marking status: complete on an installable-solution mission, see references/autonomous-lab-completion-verification.md.
For the reactivation protocol when a completed lab receives new P0 feedback or the user contradicts a completion claim, see references/autonomous-lab-reactivation-protocol.md.
For adding historical trend tracking (SQLite-backed agent status transitions + vanilla JS SVG sparklines) to an autonomous lab dashboard, see references/history-tracking-sparkline-pattern.md.
For reusable dashboard UX patterns (onboarding tours, data freshness badges, keyboard shortcuts, progressive disclosure inspectors, cross-linking between views), see references/dashboard-ux-patterns.md.
For the aggressive human-first inspector refinement โ when users report that details are hard to understand and the fix is to strip technical labels from the default view โ see references/progressive-disclosure-human-first.md.
For programmatic verification of CSS custom-property theme systems โ catching scoping bugs, confirming theme distinctness, and validating JS switching logic โ see references/theme-system-verification.md.
For Son's Discord-first autonomous experiments where a channel hosts a repeated multi-agent loop, use the Autonomous Discord Agent Lab pattern: create file-based durable state, a paused cron orchestrator delivered to discord:<channel_id>, then activate it from a user mission trigger. See references/autonomous-discord-agent-lab.md.
Webhooks
hermes webhook subscribe N Create route at /webhooks/<name>
hermes webhook list List subscriptions
hermes webhook remove NAME Remove a subscription
hermes webhook test NAME Send a test POST
Profiles
hermes profile list List all profiles
hermes profile create NAME Create (--clone, --clone-all, --clone-from)
hermes profile use NAME Set sticky default
hermes profile delete NAME Delete a profile
hermes profile show NAME Show details
hermes profile alias NAME Manage wrapper scripts
hermes profile rename A B Rename a profile
hermes profile export NAME Export to tar.gz
hermes profile import FILE Import from archive
Credential Pools
hermes auth add Interactive credential wizard
hermes auth list [PROVIDER] List pooled credentials
hermes auth remove P INDEX Remove by provider + index
hermes auth reset PROVIDER Clear exhaustion status
Other
hermes insights [--days N] Usage analytics
hermes update Update to latest version
hermes pairing list/approve/revoke DM authorization
hermes plugins list/install/remove Plugin management
hermes honcho setup/status Honcho memory integration (requires honcho plugin)
hermes memory setup/status/off Memory provider config
hermes completion bash|zsh Shell completions
hermes acp ACP server (IDE integration)
hermes claw migrate Migrate from OpenClaw
hermes uninstall Uninstall Hermes
---
Slash Commands (In-Session)
Type these during an interactive chat session. New commands land fairly
often; if something below looks stale, run /help in-session for the
authoritative list or see the [live slash commands reference](https://hermes-agent.nousresearch.com/docs/reference/slash-commands).
The registry of record is hermes_cli/commands.py โ every consumer
(autocomplete, Telegram menu, Slack mapping, /help) derives from it.
Session Control
/new (/reset) Fresh session
/clear Clear screen + new session (CLI)
/retry Resend last message
/undo Remove last exchange
/title [name] Name the session
/compress Manually compress context
/stop Kill background processes
/rollback [N] Restore filesystem checkpoint
/snapshot [sub] Create or restore state snapshots of Hermes config/state (CLI)
/background <prompt> Run prompt in background
/queue <prompt> Queue for next turn
/steer <prompt> Inject a message after the next tool call without interrupting
/agents (/tasks) Show active agents and running tasks
/resume [name] Resume a named session
/goal [text|sub] Set a standing goal Hermes works on across turns until achieved
(subcommands: status, pause, resume, clear)
/redraw Force a full UI repaint (CLI)
Configuration
/config Show config (CLI)
/model [name] Show or change model
/personality [name] Set personality
/reasoning [level] Set reasoning (none|minimal|low|medium|high|xhigh|show|hide)
/verbose Cycle: off โ new โ all โ verbose
/voice [on|off|tts] Voice mode
/yolo Toggle approval bypass
/busy [sub] Control what Enter does while Hermes is working (CLI)
(subcommands: queue, steer, interrupt, status)
/indicator [style] Pick the TUI busy-indicator style (CLI)
(styles: kaomoji, emoji, unicode, ascii)
/footer [on|off] Toggle gateway runtime-metadata footer on final replies
/skin [name] Change theme (CLI)
/statusbar Toggle status bar (CLI)
Tools & Skills
/tools Manage tools (CLI)
/toolsets List toolsets (CLI)
/skills Search/install skills (CLI)
/skill <name> Load a skill into session
/reload-skills Re-scan ~/.hermes/skills/ for added/removed skills
/reload Reload .env variables into the running session (CLI)
/reload-mcp Reload MCP servers
/cron Manage cron jobs (CLI)
/curator [sub] Background skill maintenance (status, run, pin, archive, โฆ)
/kanban [sub] Multi-profile collaboration board (tasks, links, comments)
/plugins List plugins (CLI)
Gateway
/approve Approve a pending command (gateway)
/deny Deny a pending command (gateway)
/restart Restart gateway (gateway)
/sethome Set current chat as home channel (gateway)
/update Update Hermes to latest (gateway)
/topic [sub] Enable or inspect Telegram DM topic sessions (gateway)
/platforms (/gateway) Show platform connection status (gateway)
Utility
/branch (/fork) Branch the current session
/fast Toggle priority/fast processing
/browser Open CDP browser connection
/history Show conversation history (CLI)
/save Save conversation to file (CLI)
/copy [N] Copy the last assistant response to clipboard (CLI)
/paste Attach clipboard image (CLI)
/image Attach local image file (CLI)
Info
/help Show commands
/commands [page] Browse all commands (gateway)
/usage Token usage
/insights [days] Usage analytics
/gquota Show Google Gemini Code Assist quota usage (CLI)
/status Session info (gateway)
/profile Active profile info
/debug Upload debug report (system info + logs) and get shareable links
Exit
/quit (/exit, /q) Exit CLI
---
Key Paths & Config
~/.hermes/config.yaml Main configuration
~/.hermes/.env API keys and secrets
$HERMES_HOME/skills/ Installed skills
~/.hermes/sessions/ Session transcripts
~/.hermes/logs/ Gateway and error logs
~/.hermes/auth.json OAuth tokens and credential pools
~/.hermes/hermes-agent/ Source code (if git-installed)
Profiles use ~/.hermes/profiles/<name>/ with the same layout.
Config Sections
Edit with hermes config edit or hermes config set section.key value.
| Section | Key options |
|---------|-------------|
| model | default, provider, base_url, api_key, context_length |
| agent | max_turns (90), tool_use_enforcement |
| terminal | backend (local/docker/ssh/modal), cwd, timeout (180) |
| compression | enabled, threshold (0.50), target_ratio (0.20) |
| display | skin, tool_progress, show_reasoning, show_cost |
| stt | enabled, provider (local/groq/openai/mistral) |
| tts | provider (edge/elevenlabs/openai/minimax/mistral/neutts) |
| memory | memory_enabled, user_profile_enabled, provider |
| security | tirith_enabled, website_blocklist |
| delegation | model, provider, base_url, api_key, max_iterations (50), reasoning_effort |
| checkpoints | enabled, max_snapshots (50) |
| fallback_model | provider, model, base_url, key_env |
Fallback Providers
Hermes can automatically fail over to a backup provider:model when the primary is unavailable. This is turn-scoped โ each new user message starts with the primary restored; fallback only activates mid-turn when the primary fails.
Configuration ( ~/.hermes/config.yaml):
fallback_model:
provider: opencode-go
model: kimi-k2.6
Or use the interactive manager:
hermes fallback add # interactive picker
hermes fallback list # show fallback chain
hermes fallback remove # remove by index
Legacy note: fallback_model (singular) is the legacy single-fallback key. fallback_providers (list) supports multiple ordered fallbacks. When both exist, fallback_providers takes priority.
Trigger conditions (after exhausting retries where applicable):
- Rate limits (HTTP 429)
- Server errors (HTTP 500, 502, 503)
- Auth failures (HTTP 401, 403) โ immediately
- Not found (HTTP 404) โ immediately
- Invalid / empty responses repeatedly
Supported providers include all standard providers (OpenRouter, Anthropic, OpenCode Go/ Zen, Kimi, etc.) plus custom endpoints with base_url + key_env. Full provider docs: https://hermes-agent.nousresearch.com/docs/integrations/providers
Limitations:
- Subagent delegation does not inherit fallback config
- Cron jobs do not use fallback (use per-job provider/model overrides)
- Auxiliary tasks (vision, compression, etc.) use their own
auxiliary.* provider chain
For a deep-dive with worked examples and model lists, see references/fallback-providers.md.
Full config reference: https://hermes-agent.nousresearch.com/docs/user-guide/configuration
Providers
20+ providers supported. Set via hermes model or hermes setup.
| Provider | Auth | Key env var |
|----------|------|-------------|
| OpenRouter | API key | OPENROUTER_API_KEY |
| Anthropic | API key | ANTHROPIC_API_KEY |
| Nous Portal | OAuth | hermes auth |
| OpenAI Codex | OAuth | hermes auth |
| GitHub Copilot | Token | COPILOT_GITHUB_TOKEN |
| Google Gemini | API key | GOOGLE_API_KEY or GEMINI_API_KEY |
| DeepSeek | API key | DEEPSEEK_API_KEY |
| xAI / Grok | API key | XAI_API_KEY |
| Hugging Face | Token | HF_TOKEN |
| Z.AI / GLM | API key | GLM_API_KEY |
| MiniMax | API key | MINIMAX_API_KEY |
| MiniMax CN | API key | MINIMAX_CN_API_KEY |
| Kimi / Moonshot | API key | KIMI_API_KEY |
| Alibaba / DashScope | API key | DASHSCOPE_API_KEY |
| Xiaomi MiMo | API key | XIAOMI_API_KEY |
| Kilo Code | API key | KILOCODE_API_KEY |
| AI Gateway (Vercel) | API key | AI_GATEWAY_API_KEY |
| OpenCode Zen | API key | OPENCODE_ZEN_API_KEY |
| OpenCode Go | API key | OPENCODE_GO_API_KEY |
| Qwen OAuth | OAuth | hermes auth add qwen-oauth |
| Custom endpoint | Config | model.base_url + model.api_key in config.yaml |
| GitHub Copilot ACP | External | COPILOT_CLI_PATH or Copilot CLI |
Full provider docs: https://hermes-agent.nousresearch.com/docs/integrations/providers
Toolsets
Enable/disable via hermes tools (interactive) or hermes tools enable/disable NAME.
| Toolset | What it provides |
|---------|-----------------|
| web | Web search and content extraction |
| search | Web search only (subset of web) |
| browser | Browser automation (Browserbase, Camofox, or local Chromium) |
| terminal | Shell commands and process management |
| file | File read/write/search/patch |
| code_execution | Sandboxed Python execution |
| vision | Image analysis |
| image_gen | AI image generation |
| video | Video analysis and generation |
| tts | Text-to-speech |
| skills | Skill browsing and management |
| memory | Persistent cross-session memory |
| session_search | Search past conversations |
| delegation | Subagent task delegation |
| cronjob | Scheduled task management |
| clarify | Ask user clarifying questions |
| messaging | Cross-platform message sending |
| todo | In-session task planning and tracking |
| kanban | Multi-agent work-queue tools (gated to workers) |
| debugging | Extra introspection/debug tools (off by default) |
| safe | Minimal, low-risk toolset for locked-down sessions |
| spotify | Spotify playback and playlist control |
| homeassistant | Smart home control (off by default) |
| discord | Discord integration tools |
| discord_admin | Discord admin/moderation tools |
| feishu_doc | Feishu (Lark) document tools |
| feishu_drive | Feishu (Lark) drive tools |
| yuanbao | Yuanbao integration tools |
| rl | Reinforcement learning tools (off by default) |
| moa | Mixture of Agents (off by default) |
Full enumeration lives in toolsets.py as the TOOLSETS dict; _HERMES_CORE_TOOLS is the default bundle most platforms inherit from.
Tool changes take effect on /reset (new session). They do NOT apply mid-conversation to preserve prompt caching.
---
Security & Privacy Toggles
Common "why is Hermes doing X to my output / tool calls / commands?" toggles โ and the exact commands to change them. Most of these need a fresh session (/reset in chat, or start a new hermes invocation) because they're read once at startup.
Secret redaction in tool output
Secret redaction is off by default โ tool output (terminal stdout, read_file, web content, subagent summaries, etc.) passes through unmodified. If the user wants Hermes to auto-mask strings that look like API keys, tokens, and secrets before they enter the conversation context and logs:
hermes config set security.redact_secrets true # enable globally
Restart required. security.redact_secrets is snapshotted at import time โ toggling it mid-session (e.g. via export HERMES_REDACT_SECRETS=true from a tool call) will NOT take effect for the running process. Tell the user to run hermes config set security.redact_secrets true in a terminal, then start a new session. This is deliberate โ it prevents an LLM from flipping the toggle on itself mid-task.
Disable again with:
hermes config set security.redact_secrets false
PII redaction in gateway messages
Separate from secret redaction. When enabled, the gateway hashes user IDs and strips phone numbers from the session context before it reaches the model:
hermes config set privacy.redact_pii true # enable
hermes config set privacy.redact_pii false # disable (default)
Command approval prompts
By default (approvals.mode: manual), Hermes prompts the user before running shell commands flagged as destructive (rm -rf, git reset --hard, etc.). The modes are:
manual โ always prompt (default)
smart โ use an auxiliary LLM to auto-approve low-risk commands, prompt on high-risk
off โ skip all approval prompts (equivalent to --yolo)
hermes config set approvals.mode smart # recommended middle ground
hermes config set approvals.mode off # bypass everything (not recommended)
Per-invocation bypass without changing config:
hermes --yolo โฆ
export HERMES_YOLO_MODE=1
Note: YOLO / approvals.mode: off does NOT turn off secret redaction. They are independent.
Shell hooks allowlist
Some shell-hook integrations require explicit allowlisting before they fire. Managed via ~/.hermes/shell-hooks-allowlist.json โ prompted interactively the first time a hook wants to run.
Disabling the web/browser/image-gen tools
To keep the model away from network or media tools entirely, open hermes tools and toggle per-platform. Takes effect on next session (/reset). See the Tools & Skills section above.
---
Voice & Transcription
STT (Voice โ Text)
Voice messages from messaging platforms are auto-transcribed.
Provider priority (auto-detected):
1. Local faster-whisper โ free, no API key: pip install faster-whisper
2. Groq Whisper โ free tier: set GROQ_API_KEY
3. OpenAI Whisper โ paid: set VOICE_TOOLS_OPENAI_KEY
4. Mistral Voxtral โ set MISTRAL_API_KEY
Config:
stt:
enabled: true
provider: local # local, groq, openai, mistral
local:
model: base # tiny, base, small, medium, large-v3
TTS (Text โ Voice)
| Provider | Env var | Free? |
|----------|---------|-------|
| Edge TTS | None | Yes (default) |
| ElevenLabs | ELEVENLABS_API_KEY | Free tier |
| OpenAI | VOICE_TOOLS_OPENAI_KEY | Paid |
| MiniMax | MINIMAX_API_KEY | Paid |
| Mistral (Voxtral) | MISTRAL_API_KEY | Paid |
| NeuTTS (local) | None (pip install neutts[all] + espeak-ng) | Free |
Voice commands: /voice on (voice-to-voice), /voice tts (always voice), /voice off.
---
Spawning Additional Hermes Instances
Run additional Hermes processes as fully independent subprocesses โ separate sessions, tools, and environments.
When to Use This vs delegate_task
| | delegate_task | Spawning hermes process |
|-|-----------------|--------------------------|
| Isolation | Separate conversation, shared process | Fully independent process |
| Duration | Minutes (bounded by parent loop) | Hours/days |
| Tool access | Subset of parent's tools | Full tool access |
| Interactive | No | Yes (PTY mode) |
| Use case | Quick parallel subtasks | Long autonomous missions |
One-Shot Mode
terminal(command="hermes chat -q 'Research GRPO papers and write summary to ~/research/grpo.md'", timeout=300)
Background for long tasks:
terminal(command="hermes chat -q 'Set up CI/CD for ~/myapp'", background=true)
Interactive PTY Mode (via tmux)
Hermes uses prompt_toolkit, which requires a real terminal. Use tmux for interactive spawning:
Start
terminal(command="tmux new-session -d -s agent1 -x 120 -y 40 'hermes'", timeout=10)
Wait for startup, then send a message
terminal(command="sleep 8 && tmux send-keys -t agent1 'Build a FastAPI auth service' Enter", timeout=15)
Read output
terminal(command="sleep 20 && tmux capture-pane -t agent1 -p", timeout=5)
Send follow-up
terminal(command="tmux send-keys -t agent1 'Add rate limiting middleware' Enter", timeout=5)
Exit
terminal(command="tmux send-keys -t agent1 '/exit' Enter && sleep 2 && tmux kill-session -t agent1", timeout=10)
Multi-Agent Coordination
Agent A: backend
terminal(command="tmux new-session -d -s backend -x 120 -y 40 'hermes -w'", timeout=10)
terminal(command="sleep 8 && tmux send-keys -t backend 'Build REST API for user management' Enter", timeout=15)
Agent B: frontend
terminal(command="tmux new-session -d -s frontend -x 120 -y 40 'hermes -w'", timeout=10)
terminal(command="sleep 8 && tmux send-keys -t frontend 'Build React dashboard for user management' Enter", timeout=15)
Check progress, relay context between them
terminal(command="tmux capture-pane -t backend -p | tail -30", timeout=5)
terminal(command="tmux send-keys -t frontend 'Here is the API schema from the backend agent: ...' Enter", timeout=5)
Session Resume
Resume most recent session
terminal(command="tmux new-session -d -s resumed 'hermes --continue'", timeout=10)
Resume specific session
terminal(command="tmux new-session -d -s resumed 'hermes --resume 20260225_143052_a1b2c3'", timeout=10)
Tips
- Prefer
delegate_task for quick subtasks โ less overhead than spawning a full process
- Use
-w (worktree mode) when spawning agents that edit code โ prevents git conflicts
- Set timeouts for one-shot mode โ complex tasks can take 5-10 minutes
- Use
hermes chat -q for fire-and-forget โ no PTY needed
- Use tmux for interactive sessions โ raw PTY mode has
\r vs \n issues with prompt_toolkit
- For scheduled tasks, use the
cronjob tool instead of spawning โ handles delivery and retry
---
Durable & Background Systems
Four systems run alongside the main conversation loop. Quick reference
here; full developer notes live in AGENTS.md, user-facing docs under
website/docs/user-guide/features/.
Delegation (delegate_task)
Synchronous subagent spawn โ the parent waits for the child's summary
before continuing its own loop. Isolated context + terminal session.
- Single:
delegate_task(goal, context, toolsets).
- Batch:
delegate_task(tasks=[{goal, ...}, ...]) runs children in
parallel, capped by delegation.max_concurrent_children (default 3).
- Roles:
leaf (default; cannot re-delegate) vs orchestrator
(can spawn its own workers, bounded by delegation.max_spawn_depth).
- Not durable. If the parent is interrupted, the child is
cancelled. For work that must outlive the turn, use cronjob or
terminal(background=True, notify_on_complete=True).
Config: delegation.* in config.yaml.
Tuning max_concurrent_children
Default is 3. Rule of thumb for raising it:
- Light tasks (web search, file grep): up to
6-8
- Medium tasks (code execution, browser):
4-5
- Heavy tasks (builds, large data):
2-3
- Actual bottleneck is usually the API rate limit, not local CPU/RAM. On a 10-core M4 with 16GB RAM, CPU is rarely the constraint.
- Formula: start at
5, raise only if profiling shows idle time between API responses.
Cron (scheduled jobs)
Durable scheduler โ cron/jobs.py + cron/scheduler.py. Drive it via
the cronjob tool, the hermes cron CLI (list, add, edit,
pause, resume, run, remove), or the /cron slash command.
- Schedules: duration (
"30m", "2h"), "every" phrase
( "every monday 9am"), 5-field cron ( "0 9 *"), or ISO timestamp.
- Per-job knobs:
skills, model/provider override, script
(pre-run data collection; no_agent=True makes the script the whole
job), context_from (chain job A's output into job B), workdir
(run in a specific dir with its AGENTS.md / CLAUDE.md loaded),
multi-platform delivery.
- Invariants: 3-minute hard interrupt per run,
.tick.lock file
prevents duplicate ticks across processes, cron sessions pass
skip_memory=True by default, and cron deliveries are framed with a
header/footer instead of being mirrored into the target gateway
session (keeps role alternation intact).
User docs: https://hermes-agent.nousresearch.com/docs/user-guide/features/cron
Curator (skill lifecycle)
Background maintenance for agent-created skills. Tracks usage, marks
idle skills stale, archives stale ones, keeps a pre-run tar.gz backup
so nothing is lost.
- CLI:
hermes curator <verb> โ status, run, pause, resume,
pin, unpin, archive, restore, prune, backup, rollback.
- Slash:
/curator <subcommand> mirrors the CLI.
- Scope: only touches skills with
created_by: "agent" provenance.
Bundled + hub-installed skills are off-limits. Never deletes โ
max destructive action is archive. Pinned skills are exempt from
every auto-transition and every LLM review pass.
- Telemetry: sidecar at
~/.hermes/skills/.usage.json holds
per-skill use_count, view_count, patch_count,
last_activity_at, state, pinned.
Config: curator.* (enabled, interval_hours, min_idle_hours,
stale_after_days, archive_after_days, backup.*).
User docs: https://hermes-agent.nousresearch.com/docs/user-guide/features/curator
Dreaming (periodic memory/skill consolidation)
For Anthropic-style "dreaming" workflows, combine cron + session_search + memory + skills + curator into a scheduled review loop. Start with a weekly, proposal-only report that audits recent sessions, repeated user corrections, memory conflicts, skill patch candidates, and cron/automation improvements. Do not automatically delete/replace memory or patch/archive skills unless the user explicitly approves the proposed changes. See references/weekly-dreaming-routine.md for the recommended prompt, report format, safety policy, and cron creation pattern.
Kanban (multi-agent work queue)
Durable SQLite board for multi-profile / multi-worker collaboration.
Users drive it via hermes kanban <verb>; dispatcher-spawned workers
see a focused kanban_* toolset gated by HERMES_KANBAN_TASK so the
schema footprint is zero outside worker processes.
- CLI verbs (common):
init, create, list (alias ls),
show, assign, link, unlink, comment, complete, block,
unblock, archive, tail. Less common: watch, stats, runs,
log, dispatch, daemon, gc.
- Worker toolset:
kanban_show, kanban_complete, kanban_block,
kanban_heartbeat, kanban_comment, kanban_create, kanban_link.
- Dispatcher runs inside the gateway by default
( kanban.dispatch_in_gateway: true) โ reclaims stale claims,
promotes ready tasks, atomically claims, spawns assigned profiles.
Auto-blocks a task after ~5 consecutive spawn failures.
- Isolation: board is the hard boundary (workers get
HERMES_KANBAN_BOARD pinned in env); tenant is a soft namespace
within a board for workspace-path + memory-key isolation.
User docs: https://hermes-agent.nousresearch.com/docs/user-guide/features/kanban
Log Relay (Hermes โ Discord)
A background Python script that tails ~/.hermes/logs/*.log and batches lines to a Discord channel. Includes session-ID extraction, rate-limit handling, and auto-restart via launchd/systemd. Useful for remote monitoring and audit trails.
- Reference:
references/discord-log-relay.md โ full setup, tuning, macOS/Linux service install, pitfalls.
- Template:
templates/discord-log-relay.py โ copy, set CHANNEL_ID, and deploy.
- Discord operations:
references/discord-operating-planes.md โ channel-purpose routing, periodic-summary vs Dreaming report formats, and safety/cost notes for Discord-first Hermes deployments.
Key pitfall: ask the user about batch frequency upfront rather than defaulting to real-time streaming. Most users prefer 10-minute or hourly batches. High-volume raw logs should be batched, summarized, or stored out-of-band; avoid Discord message storms during error loops.
Weekly Dreaming / Memory Curation
For long-running Hermes deployments, users may want an Anthropic-style "Dreaming" loop: a scheduled review that consolidates experience, proposes memory/skill/cron changes, and identifies what to keep, weaken, archive, or delete. Hermes has the building blocks (sessions, session_search, memory, skills, curator, cron), but the safe default is proposal mode:
1. Inspect recent usage and sessions.
2. Extract repeated success patterns, failure patterns, and user corrections.
3. Propose memory updates/removals without applying them silently.
4. Propose skill patches/archive candidates and cron/reporting improvements.
5. End with explicit approval checkboxes.
Do not silently rewrite or delete memory/skills from a Dreaming report unless the user explicitly authorized automatic application. See references/discord-operating-planes.md for a report template and routing heuristics.
---
Windows-Specific Quirks
Hermes runs natively on Windows (PowerShell, cmd, Windows Terminal, git-bash
mintty, VS Code integrated terminal). Most of it just works, but a handful
of differences between Win32 and POSIX have bitten us โ document new ones
here as you hit them so the next person (or the next session) doesn't
rediscover them from scratch.
Input / Keybindings
Alt+Enter doesn't insert a newline. Windows Terminal intercepts Alt+Enter
at the terminal layer to toggle fullscreen โ the keystroke never reaches
prompt_toolkit. Use Ctrl+Enter instead. Windows Terminal delivers
Ctrl+Enter as LF ( c-j), distinct from plain Enter ( c-m / CR), and the
CLI binds c-j to newline insertion on win32 only (see
_bind_prompt_submit_keys + the Windows-only c-j binding in cli.py).
Side effect: the raw Ctrl+J keystroke also inserts a newline on Windows โ
unavoidable, because Windows Terminal collapses Ctrl+Enter and Ctrl+J to
the same keycode at the Win32 console API layer. No conflicting binding
existed for Ctrl+J on Windows, so this is a harmless side effect.
mintty / git-bash behaves the same (fullscreen on Alt+Enter) unless you
disable Alt+Fn shortcuts in Options โ Keys. Easier to just use Ctrl+Enter.
Diagnosing keybindings. Run python scripts/keystroke_diagnostic.py
(repo root) to see exactly how prompt_toolkit identifies each keystroke
in the current terminal. Answers questions like "does Shift+Enter come
through as a distinct key?" (almost never โ most terminals collapse it
to plain Enter) or "what byte sequence is my terminal sending for
Ctrl+Enter?" This is how the Ctrl+Enter = c-j fact was established.
Config / Files
HTTP 400 "No models provided" on first run. config.yaml was saved
with a UTF-8 BOM (common when Windows apps write it). Re-save as UTF-8
without BOM. hermes config edit writes without BOM; manual edits in
Notepad are the usual culprit.
execute_code / Sandbox
WinError 10106 ("The requested service provider could not be loaded
or initialized") from the sandbox child process โ it can't create an
AF_INET socket, so the loopback-TCP RPC fallback fails before
connect(). Root cause is usually not a broken Winsock LSP; it's
Hermes's own env scrubber dropping SYSTEMROOT / WINDIR / COMSPEC
from the child env. Python's socket module needs SYSTEMROOT to locate
mswsock.dll. Fixed via the _WINDOWS_ESSENTIAL_ENV_VARS allowlist in
tools/code_execution_tool.py. If you still hit it, echo os.environ
inside an execute_code block to confirm SYSTEMROOT is set. Full
diagnostic recipe in references/execute-code-sandbox-env-windows.md.
Testing / Contributing
scripts/run_tests.sh doesn't work as-is on Windows โ it looks for
POSIX venv layouts ( .venv/bin/activate). The Hermes-installed venv at
venv/Scripts/ has no pip or pytest either (stripped for install size).
Workaround: install pytest + pytest-xdist + pyyaml into a system Python
3.11 user site, then invoke pytest directly with PYTHONPATH set:
"/c/Program Files/Python311/python" -m pip install --user pytest pytest-xdist pyyaml
export PYTHONPATH="$(pwd)"
"/c/Program Files/Python311/python" -m pytest tests/foo/test_bar.py -v --tb=short -n 0
Use -n 0, not -n 4 โ pyproject.toml's default addopts already
includes -n, and the wrapper's CI-parity guarantees don't apply off POSIX.
POSIX-only tests need skip guards. Common markers already in the codebase:
- Symlinks โ elevated privileges on Windows
0o600 file modes โ POSIX mode bits not enforced on NTFS by default
signal.SIGALRM โ Unix-only (see tests/conftest.py::_enforce_test_timeout)
- Winsock / Windows-specific regressions โ
@pytest.mark.skipif(sys.platform != "win32", ...)
Use the existing skip-pattern style (sys.platform == "win32" or
sys.platform.startswith("win")) to stay consistent with the rest of the
suite.
Path / Filesystem
Line endings. Git may warn LF will be replaced by CRLF the next time
Git touches it. Cosmetic โ the repo's .gitattributes normalizes. Don't
let editors auto-convert committed POSIX-newline files to CRLF.
Forward slashes work almost everywhere. C:/Users/... is accepted by
every Hermes tool and most Windows APIs. Prefer forward slashes in code
and logs โ avoids shell-escaping backslashes in bash.
---
Troubleshooting
Voice not working
1. Check stt.enabled: true in config.yaml
2. Verify provider: pip install faster-whisper or set API key
3. In gateway: /restart. In CLI: exit and relaunch.
Tool not available
1. hermes tools โ check if toolset is enabled for your platform
2. Some tools need env vars (check .env)
3. /reset after enabling tools
Model/provider issues
1. hermes doctor โ check config and dependencies
2. hermes auth add <provider> โ re-authenticate OAuth providers (use --type oauth)
3. Check .env has the right API key
4. Copilot 403: gh auth login tokens do NOT work for Copilot API. You must use the Copilot-specific OAuth device code flow via hermes model โ GitHub Copilot.
Changes not taking effect
- Tools/skills:
/reset starts a new session with updated toolset
- Config changes: In gateway:
/restart. In CLI: exit and relaunch.
- Code changes: Restart the CLI or gateway process
Deployed web dashboard shows stale CSS or theme changes
- Browser cache: Add
?v=N cache-busting query strings to CSS/JS/theme links in HTML.
- Service Worker cache: Bump
CACHE_NAME in sw.js to invalidate old shell caches.
- Data freshness: Use
fetch(url, {cache:'no-store'}) for live JSON feeds.
- See
references/static-site-cache-invalidation.md for the full diagnostic recipe.
Dashboard inspector feels too technical
- The default inspector view should contain only plain-language sentences: headline, "what they're doing now", "why it matters", and a silent visual progress bar (no text label).
- Move all technical fields (source IDs, confidence scores, progress labels, status slugs, badges) behind a "Show technical details" toggle.
- If users say "details are hard to understand," the fix is to remove more fields from the default view, not to add explanations. Explanations of technical fields are still technical.
- See
references/progressive-disclosure-human-first.md for the aggressive simplification pattern.
Skills not showing
1. hermes skills list โ verify installed
2. hermes skills config โ check platform enablement
3. Load explicitly: /skill name or hermes -s name
Gateway issues
Check logs first:
grep -i "failed to send\|error" ~/.hermes/logs/gateway.log | tail -20
Common gateway problems:
- Gateway dies on SSH logout: Enable linger:
sudo loginctl enable-linger $USER
- Gateway dies on WSL2 close: WSL2 requires
systemd=true in /etc/wsl.conf for systemd services to work. Without it, gateway falls back to nohup (dies when session closes).
- Gateway crash loop: Reset the failed state:
systemctl --user reset-failed hermes-gateway
- macOS: bot shows offline after idle time: The gateway runs as a user agent (
LimitLoadToSessionType=Aqua), so macOS suspends it when the system sleeps. The platform websocket drops and the bot appears offline until the network returns. Fix: keep the Mac awake (System Settings -> Energy -> Prevent automatic sleeping, or caffeinate -d -i -s -u &). Low Power Mode makes this worse, not better. See references/macos-gateway-sleep-disconnect.md for the full diagnostic recipe.
Platform-specific issues
- Discord bot silent: Must enable Message Content Intent in Bot โ Privileged Gateway Intents. See full Discord setup reference:
references/discord-gateway-setup.md.
- Slack bot only works in DMs: Must subscribe to
message.channels event. Without it, the bot ignores public channels.
- Windows-specific issues (
Alt+Enter newline, WinError 10106, UTF-8 BOM config, test suite, line endings): see the dedicated Windows-Specific Quirks section above.
Auxiliary models not working
If auxiliary tasks (vision, compression, session_search) fail silently, the auto provider can't find a backend. Either set OPENROUTER_API_KEY or GOOGLE_API_KEY, or explicitly configure each auxiliary task's provider:
hermes config set auxiliary.vision.provider <your_provider>
hermes config set auxiliary.vision.model <model_name>
Full system auth provisioning
For a one-shot workflow to maximize available credentials โ installing gh, generating SSH keys, configuring git, enabling all Hermes toolsets, and auditing current auth state โ see references/system-auth-setup.md.
Editing large files with patch
When a file is read with read_file(offset=...) (pagination), the tool warns that the view is partial. If you attempt patch without re-reading the full file first, you will likely hit non-unique match errors or corrupt the file. Fix: always call read_file without offset to load the whole file before patching. For append-only updates (e.g., adding a cycle log entry to state.md), do not use terminal(command="cat >> file << 'EOF'...EOF") โ the terminal tool on macOS/Linux misinterprets heredoc << as backgrounding and fails. Instead, write a short Python script via write_file and execute it with terminal(command="python3 /tmp/script.py"). See references/terminal-heredoc-workaround.md for the full pattern.
---
Windows-Specific Quirks
| Looking for... | Location |
|----------------|----------|
| Config options | hermes config edit or [Configuration docs](https://hermes-agent.nousresearch.com/docs/user-guide/configuration) |
| Available tools | hermes tools list or [Tools reference](https://hermes-agent.nousresearch.com/docs/reference/tools-reference) |
| Slash commands | /help in session or [Slash commands reference](https://hermes-agent.nousresearch.com/docs/reference/slash-commands) |
| Skills catalog | hermes skills browse or [Skills catalog](https://hermes-agent.nousresearch.com/docs/reference/skills-catalog) |
| Provider setup | hermes model or [Providers guide](https://hermes-agent.nousresearch.com/docs/integrations/providers) |
| Platform setup | hermes gateway setup or [Messaging docs](https://hermes-agent.nousresearch.com/docs/user-guide/messaging/) |
| MCP servers | hermes mcp list or [MCP guide](https://hermes-agent.nousresearch.com/docs/user-guide/features/mcp) |
| Profiles | hermes profile list or [Profiles docs](https://hermes-agent.nousresearch.com/docs/user-guide/profiles) |
| Cron jobs | hermes cron list or [Cron docs](https://hermes-agent.nousresearch.com/docs/user-guide/features/cron) |
| Memory | hermes memory status or [Memory docs](https://hermes-agent.nousresearch.com/docs/user-guide/features/memory) |
| Env variables | hermes config env-path or [Env vars reference](https://hermes-agent.nousresearch.com/docs/reference/environment-variables) |
| CLI commands | hermes --help or [CLI reference](https://hermes-agent.nousresearch.com/docs/reference/cli-commands) |
| Gateway logs | ~/.hermes/logs/gateway.log |
| Session files | ~/.hermes/sessions/ or hermes sessions browse |
| Source code | ~/.hermes/hermes-agent/ |
---
Contributor Quick Reference
For occasional contributors and PR authors. Full developer docs: https://hermes-agent.nousresearch.com/docs/developer-guide/
Project Layout
hermes-agent/
โโโ run_agent.py # AIAgent โ core conversation loop
โโโ model_tools.py # Tool discovery and dispatch
โโโ toolsets.py # Toolset definitions
โโโ cli.py # Interactive CLI (HermesCLI)
โโโ hermes_state.py # SQLite session store
โโโ agent/ # Prompt builder, context compression, memory, model routing, credential pooling, skill dispatch
โโโ hermes_cli/ # CLI subcommands, config, setup, commands
โ โโโ commands.py # Slash command registry (CommandDef)
โ โโโ config.py # DEFAULT_CONFIG, env var definitions
โ โโโ main.py # CLI entry point and argparse
โโโ tools/ # One file per tool
โ โโโ registry.py # Central tool registry
โโโ gateway/ # Messaging gateway
โ โโโ platforms/ # Platform adapters (telegram, discord, etc.)
โโโ cron/ # Job scheduler
โโโ tests/ # ~3000 pytest tests
โโโ website/ # Docusaurus docs site
Config: ~/.hermes/config.yaml (settings), ~/.hermes/.env (API keys).
Adding a Tool (3 files)
1. Create tools/your_tool.py:
import json, os
from tools.registry import registry
def check_requirements() -> bool:
return bool(os.getenv("EXAMPLE_API_KEY"))
def example_tool(param: str, task_id: str = None) -> str:
return json.dumps({"success": True, "data": "..."})
registry.register(
name="example_tool",
toolset="example",
schema={"name": "example_tool", "description": "...", "parameters": {...}},
handler=lambda args, **kw: example_tool(
param=args.get("param", ""), task_id=kw.get("task_id")),
check_fn=check_requirements,
requires_env=["EXAMPLE_API_KEY"],
)
2. Add to toolsets.py โ _HERMES_CORE_TOOLS list.
Auto-discovery: any tools/*.py file with a top-level registry.register() call is imported automatically โ no manual list needed.
All handlers must return JSON strings. Use get_hermes_home() for paths, never hardcode ~/.hermes.
Adding a Slash Command
1. Add CommandDef to COMMAND_REGISTRY in hermes_cli/commands.py
2. Add handler in cli.py โ process_command()
3. (Optional) Add gateway handler in gateway/run.py
All consumers (help text, autocomplete, Telegram menu, Slack mapping) derive from the central registry automatically.
Agent Loop (High Level)
run_conversation():
1. Build system prompt
2. Loop while iterations < max:
a. Call LLM (OpenAI-format messages + tool schemas)
b. If tool_calls โ dispatch each via handle_function_call() โ append results โ continue
c. If text response โ return
3. Context compression triggers automatically near token limit
Testing
python -m pytest tests/ -o 'addopts=' -q # Full suite
python -m pytest tests/tools/ -q # Specific area
- Tests auto-redirect
HERMES_HOME to temp dirs โ never touch real ~/.hermes/
- Run full suite before pushing any change
- Use
-o 'addopts=' to clear any baked-in pytest flags
Windows contributors: scripts/run_tests.sh currently looks for POSIX venvs ( .venv/bin/activate / venv/bin/activate) and will error out on Windows where the layout is venv/Scripts/activate + python.exe. The Hermes-installed venv at venv/Scripts/ also has no pip or pytest โ it's stripped for end-user install size. Workaround: install pytest + pytest-xdist + pyyaml into a system Python 3.11 user site ( /c/Program Files/Python311/python -m pip install --user pytest pytest-xdist pyyaml), then run tests directly:
export PYTHONPATH="$(pwd)"
"/c/Program Files/Python311/python" -m pytest tests/tools/test_foo.py -v --tb=short -n 0
Use -n 0 (not -n 4) because pyproject.toml's default addopts already includes -n, and the wrapper's CI-parity story doesn't apply off-POSIX.
Cross-platform test guards: tests that use POSIX-only syscalls need a skip marker. Common ones already in the codebase:
- Symlink creation โ
@pytest.mark.skipif(sys.platform == "win32", reason="Symlinks require elevated privileges on Windows") (see tests/cron/test_cron_script.py)
- POSIX file modes (0o600, etc.) โ
@pytest.mark.skipif(sys.platform.startswith("win"), reason="POSIX mode bits not enforced on Windows") (see tests/hermes_cli/test_auth_toctou_file_modes.py)
signal.SIGALRM โ Unix-only (see tests/conftest.py::_enforce_test_timeout)
- Live Winsock / Windows-specific regression tests โ
@pytest.mark.skipif(sys.platform != "win32", reason="Windows-specific regression")
Monkeypatching sys.platform is not enough when the code under test also calls platform.system() / platform.release() / platform.mac_ver(). Those functions re-read the real OS independently, so a test that sets sys.platform = "linux" on a Windows runner will still see platform.system() == "Windows" and route through the Windows branch. Patch all three together:
monkeypatch.setattr(sys, "platform", "linux")
monkeypatch.setattr(platform, "system", lambda: "Linux")
monkeypatch.setattr(platform, "release", lambda: "6.8.0-generic")
See tests/agent/test_prompt_builder.py::TestEnvironmentHints for a worked example.
Extending the system prompt's execution-environment block
Factual guidance about the host OS, user home, cwd, terminal backend, and shell (bash vs. PowerShell on Windows) is emitted from agent/prompt_builder.py::build_environment_hints(). This is also where the WSL hint and per-backend probe logic live. The convention:
- Local terminal backend โ emit host info (OS,
$HOME, cwd) + Windows-specific notes (hostname โ username, terminal uses bash not PowerShell).
- Remote terminal backend (anything in
_REMOTE_TERMINAL_BACKENDS: docker, singularity, modal, daytona, ssh, vercel_sandbox, managed_modal) โ suppress host info entirely and describe only the backend. A live uname/whoami/pwd probe runs inside the backend via tools.environments.get_environment(...).execute(...), cached per process in _BACKEND_PROBE_CACHE, with a static fallback if the probe times out.
- Key fact for prompt authoring: when
TERMINAL_ENV != "local", every file tool (read_file, write_file, patch, search_files) runs inside the backend container, not on the host. The system prompt must never describe the host in that case โ the agent can't touch it.
Full design notes, the exact emitted strings, and testing pitfalls:
references/prompt-builder-environment-hints.md.
Refactor-safety pattern (POSIX-equivalence guard): when you extract inline logic into a helper that adds Windows/platform-specific behavior, keep a _legacy_<name> oracle function in the test file that's a verbatim copy of the old code, then parametrize-diff against it. Example: tests/tools/test_code_execution_windows_env.py::TestPosixEquivalence. This locks in the invariant that POSIX behavior is bit-for-bit identical and makes any future drift fail loudly with a clear diff.
Commit Conventions
type: concise subject line
Optional body.
Types: fix:, feat:, refactor:, docs:, chore:
Key Rules
- Never break prompt caching โ don't change context, tools, or system prompt mid-conversation
- Message role alternation โ never two assistant or two user messages in a row
- Use
get_hermes_home() from hermes_constants for all paths (profile-safe)
- Config values go in
config.yaml, secrets go in .env
- New tools need a
check_fn so they only appear when requirements are met
[IMPORTANT: The user has invoked the "kanban-orchestrator" skill, indicating they want you to follow its instructions. The full skill content is loaded below.]
---
name: kanban-orchestrator
description: Decomposition playbook + anti-temptation rules for an orchestrator profile routing work through Kanban. The "don't do the work yourself" rule and the basic lifecycle are auto-injected into every kanban worker's system prompt; this skill is the deeper playbook when you're specifically playing the orchestrator role.
version: 3.0.0
platforms: [linux, macos, windows]
metadata:
hermes:
tags: [kanban, multi-agent, orchestration, routing]
related_skills: [kanban-worker]
---
Kanban Orchestrator โ Decomposition Playbook
> The core worker lifecycle (including the kanban_create fan-out pattern and the "decompose, don't execute" rule) is auto-injected into every kanban process via the KANBAN_GUIDANCE system-prompt block. This skill is the deeper playbook when you're an orchestrator profile whose whole job is routing.
Profiles are user-configured โ not a fixed roster
Hermes setups vary widely. Some users run a single profile that does everything; some run a small fleet (docker-worker, cron-worker); some run a curated specialist team they've named themselves. There is no default specialist roster โ the orchestrator skill does not know what profiles exist on this machine.
Before fanning out, you must ground the decomposition in the profiles that actually exist. The dispatcher silently fails to spawn unknown assignee names โ it doesn't autocorrect, doesn't suggest, doesn't fall back. So a card assigned to researcher on a setup that only has docker-worker just sits in ready forever.
Step 0: discover available profiles before planning.
Use one of these:
hermes profile list โ prints the table of profiles configured on this machine. Run it through your terminal tool if you have one; otherwise ask the user.
kanban_list(assignee="<some-name>") โ sanity-check a single name. Returns an empty list (rather than an error) for an unknown assignee, so this only confirms a name you're already considering.
- Just ask the user. "What profiles do you have set up?" is a fine first turn when the goal needs more than one specialist.
Cache the result in your working memory for the rest of the conversation. Re-asking every turn wastes a tool call.
When to use the board (vs. just doing the work)
Create Kanban tasks when any of these are true:
1. Multiple specialists are needed. Research + analysis + writing is three profiles.
2. The work should survive a crash or restart. Long-running, recurring, or important.
3. The user might want to interject. Human-in-the-loop at any step.
4. Multiple subtasks can run in parallel. Fan-out for speed.
5. Review / iteration is expected. A reviewer profile loops on drafter output.
6. The audit trail matters. Board rows persist in SQLite forever.
If none of those apply โ it's a small one-shot reasoning task โ use delegate_task instead or answer the user directly.
The anti-temptation rules
Your job description says "route, don't execute." The rules that enforce that:
- Do not execute the work yourself. Your restricted toolset usually doesn't even include terminal/file/code/web for implementation. If you find yourself "just fixing this quickly" โ stop and create a task for the right specialist.
- For any concrete task, create a Kanban task and assign it. Every single time.
- Split multi-lane requests before creating cards. A user prompt can contain several independent workstreams. Extract those lanes first, then create one card per lane instead of bundling unrelated work into a single implementer card.
- Run independent lanes in parallel. If two cards do not need each other's output, leave them unlinked so the dispatcher can fan them out. Link only true data dependencies.
- If no specialist fits the available profiles, ask the user which profile to create or which existing profile to use. Do not invent profile names; the dispatcher will silently drop unknown assignees.
- Decompose, route, and summarize โ that's the whole job.
Exception: micro-UI polish cycles
There is one narrow exception where the orchestrator may execute directly instead of creating Kanban cards: tiny UI-only polish cycles (e.g., adding a CSS class, a theme preview dot, a hover state, a cross-link, or a HUD button) that are purely presentational, require no cross-file logic changes, and fit comfortably inside a single bounded cycle with no need for review or parallel work. If the change is limited to HTML/CSS/JS cosmetics, no other profile has a stake in it, and the user did not ask for a design review, the orchestrator should just edit and publish rather than paying the kanban-overhead tax. This exception does NOT apply to architecture changes, adapter logic, plugin interfaces, or anything that touches the data layer.
Decomposition playbook
Step 1 โ Understand the goal
Ask clarifying questions if the goal is ambiguous. Cheap to ask; expensive to spawn the wrong fleet.
Step 2 โ Sketch the task graph
Before creating anything, draft the graph out loud (in your response to the user). Treat every concrete workstream as a candidate card:
1. Extract the lanes from the request.
2. Map each lane to one of the profiles you discovered in Step 0. If a lane doesn't fit any existing profile, ask the user which to use or create.
3. Decide whether each lane is independent or gated by another lane.
4. Create independent lanes as parallel cards with no parent links.
5. Create synthesis/review/integration cards with parent links to the lanes they depend on.
Examples of prompts that should fan out (using placeholder profile names โ substitute whatever exists on the user's setup):
- "Build an app" โ one card to a design-oriented profile for product/UI direction, one or two cards to engineering profiles for implementation, plus a later integration/review card if the user has a reviewer profile.
- "Fix blockers and check model variants" โ one implementation card for the blocker fixes plus one discovery/research card for config/source verification. A final reviewer card can depend on both.
- "Research docs and implement" โ a docs-research card can run in parallel with a codebase-discovery card; implementation waits only if it truly needs those findings.
- "Analyze this screenshot and find the related code" โ one card to a vision-capable profile for the visual analysis while another searches the codebase.
Words like "also," "finally," or "and" do not automatically imply a dependency. They often mean "make sure this is covered before reporting back." Only link tasks when one card cannot start until another card's output exists.
Show the graph to the user before creating cards. Let them correct it โ including which actual profile name should own each lane.
Step 3 โ Create tasks and link
Use the profile names from Step 0. The example below uses placeholders <profile-A>, <profile-B>, <profile-C> โ replace them with what the user actually has.
t1 = kanban_create(
title="research: Postgres cost vs current",
assignee="<profile-A>", # whichever profile handles research on this setup
body="Compare estimated infrastructure costs, migration costs, and ongoing ops costs over a 3-year window. Sources: AWS/GCP pricing, team time estimates, current Postgres bills from peers.",
tenant=os.environ.get("HERMES_TENANT"),
)["task_id"]
t2 = kanban_create(
title="research: Postgres performance vs current",
assignee="<profile-A>", # same profile, run in parallel
body="Compare query latency, throughput, and scaling characteristics at our expected data volume (~500GB, 10k QPS peak). Sources: benchmark papers, public case studies, pgbench results if easy.",
)["task_id"]
t3 = kanban_create(
title="synthesize migration recommendation",
assignee="<profile-B>", # whichever profile does synthesis/analysis
body="Read the findings from T1 (cost) and T2 (performance). Produce a 1-page recommendation with explicit trade-offs and a go/no-go call.",
parents=[t1, t2],
)["task_id"]
t4 = kanban_create(
title="draft decision memo",
assignee="<profile-C>", # whichever profile drafts user-facing prose
body="Turn the analyst's recommendation into a 2-page memo for the CTO. Match the tone of previous decision memos in the team's knowledge base.",
parents=[t3],
)["task_id"]
parents=[...] gates promotion โ children stay in todo until every parent reaches done, then auto-promote to ready. No manual coordination needed; the dispatcher and dependency engine handle it.
Step 4 โ Complete your own task
If you were spawned as a task yourself (e.g. a planner profile was assigned T0: "investigate Postgres migration"), mark it done with a summary of what you created:
kanban_complete(
summary="decomposed into T1-T4: 2 research lanes in parallel, 1 synthesis on their outputs, 1 prose draft on the recommendation",
metadata={
"task_graph": {
"T1": {"assignee": "<profile-A>", "parents": []},
"T2": {"assignee": "<profile-A>", "parents": []},
"T3": {"assignee": "<profile-B>", "parents": ["T1", "T2"]},
"T4": {"assignee": "<profile-C>", "parents": ["T3"]},
},
},
)
Step 5 โ Report back to the user
Tell them what you created in plain prose, naming the actual profiles you used:
> I've queued 4 tasks:
> - T1 (<profile-A>): cost comparison
> - T2 (<profile-A>): performance comparison, in parallel with T1
> - T3 (<profile-B>): synthesizes T1 + T2 into a recommendation
> - T4 (<profile-C>): turns T3 into a CTO memo
>
> The dispatcher will pick up T1 and T2 now. T3 starts when both finish. You'll get a gateway ping when T4 completes. Use the dashboard or hermes kanban tail <id> to follow along.
Common patterns
Fan-out + fan-in (research โ synthesize): N research-style cards with no parents, one synthesis card with all of them as parents.
Parallel implementation + validation: one implementer card makes the change while one explorer/researcher card verifies config, docs, or source mapping. A reviewer card can depend on both. Do not make the implementer own unrelated verification just because the user mentioned both in one sentence.
Pipeline with gates: planner โ implementer โ reviewer. Each stage's parents=[previous_task]. Reviewer blocks or completes; if reviewer blocks, the operator unblocks with feedback and respawns.
Same-profile queue: N tasks, all assigned to the same profile, no dependencies between them. Dispatcher serializes โ that profile processes them in priority order, accumulating experience in its own memory.
Parallel UI/frontend lanes: When the goal touches multiple independent HTML/CSS/JS files (e.g., a dashboard page and a 2D gather view), fan out to separate subagents per file. Each lane edits its own file, then the orchestrator integrates, fixes cross-file references (theme paths, shared JSON endpoints), and publishes. This avoids merge conflicts in single-file HTML dashboards and keeps each subagent's context focused. See references/parallel-ui-lanes-and-publishing.md for the post-subagent integration checklist and rsync safety notes.
Human-in-the-loop: Any task can kanban_block() to wait for input. Dispatcher respawns after /unblock. The comment thread carries the full context.
Pitfalls
Inventing profile names that don't exist. The dispatcher silently fails to spawn unknown assignees โ the card just sits in ready forever. Always assign to a profile from your Step 0 discovery; ask the user if you're unsure.
Bundling independent lanes into one card. If the user asks for two independent outcomes, create two cards. Example: "fix blockers and check model variants" is not one fixer task; create a fixer/engineer card for the fixes and an explorer/researcher card for the variant check, then optionally gate review on both.
Over-linking because of wording. "Finally check X" may still be parallel with implementation if X is static config, docs, or source discovery. Link it after implementation only when the check depends on the implementation result.
Forgetting dependency links. If the task graph says research -> implement -> review, do not create all tasks as independent ready cards. Use parent links so implement/review cannot run before their inputs exist.
Reassignment vs. new task. If a reviewer blocks with "needs changes," create a NEW task linked from the reviewer's task โ don't re-run the same task with a stern look. The new task is assigned to the original implementer profile.
Argument order for links. kanban_link(parent_id=..., child_id=...) โ parent first. Mixing them up demotes the wrong task to todo.
Ignoring explicit user feedback to keep building infrastructure. When the user says a specific UX issue (legibility, theme switching, movement density) is "immediate priority," treat it as P0 and route it before deeper packaging/architecture work. Infrastructure polish feels productive, but shipping user-visible fixes is what matters. Create cards for the UX feedback first, then resume infrastructure lanes.
Treating status: complete as immutable when user feedback says otherwise. A state.md that says status: complete does not override a user's report that a completion criterion is actually broken. If the user says "theme switching is not working" and the Final Completion Condition requires "working UI theme switcher," the mission is not complete. Reactivate immediately: set status: active, append a reactivation cycle log, and fix the issue. Do not burn cycles on post-complete verification while the user is reporting active defects.
Don't pre-create the whole graph if the shape depends on intermediate findings. If T3's structure depends on what T1 and T2 find, let T3 exist as a "synthesize findings" task whose own first step is to read parent handoffs and plan the rest. Orchestrators can spawn orchestrators.
Tenant inheritance. If HERMES_TENANT is set in your env, pass tenant=os.environ.get("HERMES_TENANT") on every kanban_create call so child tasks stay in the same namespace.
Verifying cross-file references after directory reorganization. When subagents edit HTML/CSS/JS files and the directory structure shifts (e.g., moving files from root into web/dashboard/ and web/gather/), relative asset paths ( themes/default/theme.css, ./ops-data.json) often break. After subagents finish, the orchestrator must grep for href= and src= in moved files and fix relative paths before publishing. Subagents don't know the final publish layout โ the orchestrator does.
Destructive sync wipes needed files. Commands like rsync -av --delete will delete destination files that aren't in the source list. If you publish a directory tree piecemeal (e.g., copy web/dashboard/ first, then web/gather/ separately), --delete on the first rsync will erase the gather files before the second rsync runs. Either list all source paths in a single rsync invocation, or omit --delete and use cp -r / rsync -av without deletion when doing staged copies.
Recovering stuck workers
When a worker profile keeps crashing, hallucinating, or getting blocked by its own mistakes (usually: wrong model, missing skill, broken credential), the kanban dashboard flags the task with a โ badge and opens a Recovery section in the drawer. Three primary actions:
1. Reclaim (or hermes kanban reclaim <task_id>) โ abort the running worker immediately and reset the task to ready. The existing claim TTL is ~15 min; this is the fast path out.
2. Reassign (or hermes kanban reassign <task_id> <new-profile> --reclaim) โ switch the task to a different profile (one that exists on this setup) and let the dispatcher pick it up with a fresh worker.
3. Change profile model โ the dashboard prints a copy-paste hint for hermes -p <profile> model since profile config lives on disk; edit it in a terminal, then Reclaim to retry with the new model.
Hallucination warnings appear on tasks where a worker's kanban_complete(created_cards=[...]) claim included card ids that don't exist or weren't created by the worker's profile (the gate blocks the completion), or where the free-form summary references t_<hex> ids that don't resolve (advisory prose scan, non-blocking). Both produce audit events that persist even after recovery actions โ the trail stays for debugging.
The user has provided the following instruction alongside the skill invocation: [IMPORTANT: You are running as a scheduled cron job. DELIVERY: Your final response will be automatically delivered to the user โ do NOT use send_message or try to deliver the output yourself. Just produce your report/output as your final response and the system handles the rest. SILENT: If there is genuinely nothing new to report, respond with exactly "[SILENT]" (nothing else) to suppress delivery. Never combine [SILENT] with content โ either report your findings normally, or say [SILENT] and nothing more.]
You are the 15-minute Orchestrator for Son's Autonomous Agent Lab v1, reporting to Discord channel ID 1505805763824586952.
Durable state path: /Users/jooho-hermes/.hermes/autonomous-agent-lab/state.md
Working directory for experiment artifacts: /Users/jooho-hermes/.hermes/autonomous-agent-lab/
Preferred published web root: /Users/jooho-hermes/hermes-web/agent-pets/
Top-level directive from Son:
- The project has evolved from a personal dashboard into an INSTALLABLE PRODUCT that external Hermes users can deploy.
- The final target is a self-contained, configurable, publishable solution: "Hermes Pixel Pet Ops Office".
- Do NOT shrink the mission into a small static MVP and autonomously stop.
- The Gather.town-style 2D spatial office is a first-class feature, not a side page.
Latest UX feedback from Son (treat as immediate priority before deeper packaging work):
- Details are hard for a human to understand. Add human-first summaries, plain-language labels, and progressive disclosure: summary first, technical details second.
- Gather Town version has too many agents roaming around. Reduce default movement, add density/speed controls, cluster agents by room/task, and add focus/calm mode.
- Theme switching is not visibly working. Implement real UI theme switcher with persistence and clear visual theme changes.
Key product requirements (installable solution level):
1. Config-driven architecture: all paths, URLs, colors, names, room layouts via config.yaml. No hardcoded references to jooho-hermes.
2. Self-contained package: clear directory structure (src/, web/, config/, docs/, scripts/), install script, requirements.txt.
3. Pluggable data adapter: support multiple backends via plugin architecture.
4. Themeable frontend: CSS variables driven from config, swappable themes, plus a working UI theme switcher.
5. Multi-tenant ready: works for any Hermes instance.
6. Build/Deploy ready: Dockerfile or docker-compose, or clear static-server setup.
7. Documentation: README, architecture docs, configuration reference, contributor guide.
8. Human-comprehensible UX: plain-language summaries and progressive disclosure for technical detail.
9. Gather.town calm mode: adjustable movement density/speed and less chaotic defaults.
10. Versioned releases: CHANGELOG.md, semantic versioning, release packaging.
Mission model:
- Read state.md first before doing anything else.
- If state.md says
status: inactive or has no Current Mission, do not invent work. Return exactly: ๐ก Autonomous Agent Lab ๋๊ธฐ์ค โ Son์ด ํธ๋ฆฌ๊ฑฐ/๋ฏธ์
์ ์ฃผ๋ฉด 15๋ถ ์ฌ์ดํด์ ์์ํฉ๋๋ค.
- If state.md says
status: active, run one bounded 15-minute cycle toward the full installable solution.
- If state.md says
status: complete, verify that the Final Completion Condition in state.md is truly met. If it is not fully met, reactivate or report that state needs correction.
Cycle procedure when active:
1. Read state.md first. Extract current mission, constraints, previous cycle log, and Final Completion Condition.
2. Decide the next smallest useful step toward installable solution quality. Focus on: architecture, configurability, documentation, and clean separation of concerns.
3. Use delegate_task for independent subagent lanes when helpful.
4. Prefer concrete progress: refactor to config-driven, add install scripts, create docs, add Docker support, theme system, plugin architecture.
5. Update state.md with a new cycle log entry before final reporting.
6. Completion rule: only set status: complete when every item under state.md Final Completion Condition is satisfied. A non-installable MVP is not complete.
7. Stop/block only if Son explicitly stops/redirects, a safety boundary is reached, or a hard blocker needs Son's decision.
Link requirement (never forget):
- Every cycle report MUST include at least one direct viewable link to the published dashboard/artifact.
- The canonical URL:
http://hermes-mac-mini.tail46b3c6.ts.net:8099/agent-pets/
- Include gather town URL too:
http://hermes-mac-mini.tail46b3c6.ts.net:8099/agent-pets/gather/
Final Discord message format:
[Autonomous Agent Lab v1 / Cycle N]
๋ชฉํ:
์ํ:
๊ฒฐ๊ณผ:
๊ฒ์ฆ:
๋ค์:
์ํ:
Safety/quality rules:
- Do not handle secrets, passwords, API keys, payment, permission dialogs, or destructive commands.
- Do not claim completion without updating state.md.
- Do not rely on Discord history as durable state.
- Do not spam raw logs; summarize lane outputs and verification.
- Keep working in /Users/jooho-hermes/.hermes/autonomous-agent-lab/ and publish only to /Users/jooho-hermes/hermes-web/agent-pets/ unless the state file says otherwise.
Design/UX priorities:
- Mobile responsiveness is first-class.
- Character animation/movement is desired.
- Every cycle report must include published links.
- This is now a product engineering mission. Architecture, configurability, and documentation matter as much as visuals.
Response
[Autonomous Agent Lab v1 / Cycle 57]
๋ชฉํ: Son์ด ์ฆ์ ํ์ธํ ์ ์๋ visible build badge ์ถ๊ฐ, ๊ทธ๋ฆฌ๊ณ ๋์๋ณด๋/Gather Town ์ ์ฒด์ cache busting ๋ฒ์ ์ v57๋ก ์ผ์น์์ผ stale cache ๋ฌธ์ ๋ฅผ ์์ ํ ์ ๊ฑฐ.
์ํ:
- Dashboard footer์
v1.3.0 ยท b57 build badge ์ถ๊ฐ
- Gather Town HUD์ ๋์ผํ build badge ์ถ๊ฐ
?v=55๋ก ๋จ์์๋ Gather Town asset link 3๊ฐ์ Dashboard theme link 1๊ฐ๋ฅผ ?v=57๋ก ํต์ผ
- Service Worker
CACHE_NAME์ pixel-pet-ops-v13๋ก bump, ๋ชจ๋ SHELL_FILES๋ฅผ ?v=57๋ก ๊ฐฑ์
- Adapter ์คํ, integration test 110๊ฐ, setup validation 21๊ฐ ๋ชจ๋ ํต๊ณผ ํ publish
๊ฒฐ๊ณผ:
- http://hermes-mac-mini.tail46b3c6.ts.net:8099/agent-pets/ (Dashboard)
- http://hermes-mac-mini.tail46b3c6.ts.net:8099/agent-pets/gather/ (Gather Town)
๊ฒ์ฆ:
- Integration tests: 110/110 passed
- Setup validation: 21/21 passed
- Adapter: 32 agents, 15 cron, 20 sessions, 16 events, schema 1.4
ops-data.json / health.json mtime fresh (< 60s)
refresh.err.log empty, LaunchAgent healthy
- Published HTML/JS/CSS ๋ชจ๋
b57 badge์ ?v=57 cache busting ํ์ธ ์๋ฃ
๋ค์:
- Son์ Dashboard๋ Gather Town ํ๋จ์
๐ ์บ์ ์ญ์ & ์๋ก๊ณ ์นจ ๋ฒํผ์ ํด๋ฆญ ํ, ํ๋ฉด์ v1.3.0 ยท b57 badge๊ฐ ํ์๋๋์ง ํ์ธ
- badge ํ์ธ ํ 3๊ฐ ํ
๋ง(Default/Dark Ops/Cozy Pastel)๋ฅผ ๋ชจ๋ switching ํด๋ณด๊ณ ์๊ฐ์ ๋ณํ๊ฐ ๋๋ ทํ์ง ํ์ธ
- Gather Town๋ calm mode / zen mode๊ฐ ์ฌ์ ํ ๋๋ฌด ์ ์ ์๋ค๋ฉด ์ถ๊ฐ ํผ๋๋ฐฑ ์ฃผ์๋ฉด Cycle 58์์ targeted fix ์งํ
์ํ: active โ Son์ UX ํผ๋๋ฐฑ ๊ธฐ์ ์ ์์ ์ ๋ชจ๋ ์๋ฃ, browser cache clear ํ ์ต์ข
ํ์ธ ๋๊ธฐ์ค.
|
| 2026-05-19 14-49-24 |
80,317 chars |
2026-05-19_14-49-24.md |
Cron Job: autonomous-agent-lab-v1-orchestrator
Job ID: 35127ff89556
Run Time: 2026-05-19 14:49:24
Schedule: every 15m
Prompt
[IMPORTANT: The user has invoked the "hermes-agent" skill, indicating they want you to follow its instructions. The full skill content is loaded below.]
---
name: hermes-agent
description: "Configure, extend, or contribute to Hermes Agent."
version: 2.1.0
author: Hermes Agent + Teknium
license: MIT
platforms: [linux, macos, windows]
metadata:
hermes:
tags: [hermes, setup, configuration, multi-agent, spawning, cli, gateway, development]
homepage: https://github.com/NousResearch/hermes-agent
related_skills: [claude-code, codex, opencode]
---
Hermes Agent
Hermes Agent is an open-source AI agent framework by Nous Research that runs in your terminal, messaging platforms, and IDEs. It belongs to the same category as Claude Code (Anthropic), Codex (OpenAI), and OpenClaw โ autonomous coding and task-execution agents that use tool calling to interact with your system. Hermes works with any LLM provider (OpenRouter, Anthropic, OpenAI, DeepSeek, local models, and 15+ others) and runs on Linux, macOS, and WSL.
What makes Hermes different:
- Self-improving through skills โ Hermes learns from experience by saving reusable procedures as skills. When it solves a complex problem, discovers a workflow, or gets corrected, it can persist that knowledge as a skill document that loads into future sessions. Skills accumulate over time, making the agent better at your specific tasks and environment.
- Persistent memory across sessions โ remembers who you are, your preferences, environment details, and lessons learned. Pluggable memory backends (built-in, Honcho, Mem0, and more) let you choose how memory works.
- Multi-platform gateway โ the same agent runs on Telegram, Discord, Slack, WhatsApp, Signal, Matrix, Email, and 10+ other platforms with full tool access, not just chat.
- Provider-agnostic โ swap models and providers mid-workflow without changing anything else. Credential pools rotate across multiple API keys automatically.
- Profiles โ run multiple independent Hermes instances with isolated configs, sessions, skills, and memory.
- Extensible โ plugins, MCP servers, custom tools, webhook triggers, cron scheduling, and the full Python ecosystem.
People use Hermes for software development, research, system administration, data analysis, content creation, home automation, and anything else that benefits from an AI agent with persistent context and full system access.
This skill helps you work with Hermes Agent effectively โ setting it up, configuring features, spawning additional agent instances, troubleshooting issues, finding the right commands and settings, and understanding how the system works when you need to extend or contribute to it.
Docs: https://hermes-agent.nousresearch.com/docs/
Quick Start
Install
curl -fsSL https://raw.githubusercontent.com/NousResearch/hermes-agent/main/scripts/install.sh | bash
Interactive chat (default)
hermes
Single query
hermes chat -q "What is the capital of France?"
Setup wizard
hermes setup
Change model/provider
hermes model
Check health
hermes doctor
---
CLI Reference
Global Flags
hermes [flags] [command]
--version, -V Show version
--resume, -r SESSION Resume session by ID or title
--continue, -c [NAME] Resume by name, or most recent session
--worktree, -w Isolated git worktree mode (parallel agents)
--skills, -s SKILL Preload skills (comma-separate or repeat)
--profile, -p NAME Use a named profile
--yolo Skip dangerous command approval
--pass-session-id Include session ID in system prompt
No subcommand defaults to chat.
Chat
hermes chat [flags]
-q, --query TEXT Single query, non-interactive
-m, --model MODEL Model (e.g. anthropic/claude-sonnet-4)
-t, --toolsets LIST Comma-separated toolsets
--provider PROVIDER Force provider (openrouter, anthropic, nous, etc.)
-v, --verbose Verbose output
-Q, --quiet Suppress banner, spinner, tool previews
--checkpoints Enable filesystem checkpoints (/rollback)
--source TAG Session source tag (default: cli)
Configuration
hermes setup [section] Interactive wizard (model|terminal|gateway|tools|agent)
hermes model Interactive model/provider picker
hermes config View current config
hermes config edit Open config.yaml in $EDITOR
hermes config set KEY VAL Set a config value
hermes config path Print config.yaml path
hermes config env-path Print .env path
hermes config check Check for missing/outdated config
hermes config migrate Update config with new options
hermes doctor [--fix] Check dependencies and config
Credential Pools
hermes auth add Interactive credential wizard (oauth, api-key)
hermes auth list [PROVIDER] List pooled credentials
hermes auth remove P INDEX Remove by provider + index
hermes auth reset PROVIDER Clear exhaustion status
hermes logout Clear stored auth
Tools & Skills
hermes tools Interactive tool enable/disable (curses UI)
hermes tools list Show all tools and status
hermes tools enable NAME Enable a toolset
hermes tools disable NAME Disable a toolset
hermes skills list List installed skills
hermes skills search QUERY Search the skills hub
hermes skills install ID Install a skill (ID can be a hub identifier OR a direct https://โฆ/SKILL.md URL; pass --name to override when frontmatter has no name)
hermes skills inspect ID Preview without installing
hermes skills config Enable/disable skills per platform
hermes skills check Check for updates
hermes skills update Update outdated skills
hermes skills uninstall N Remove a hub skill
hermes skills publish PATH Publish to registry
hermes skills browse Browse all available skills
hermes skills tap add REPO Add a GitHub repo as skill source
MCP Servers
hermes mcp serve Run Hermes as an MCP server
hermes mcp add NAME Add an MCP server (--url or --command)
hermes mcp remove NAME Remove an MCP server
hermes mcp list List configured servers
hermes mcp test NAME Test connection
hermes mcp configure NAME Toggle tool selection
Gateway (Messaging Platforms)
hermes gateway run Start gateway foreground
hermes gateway install Install as background service
hermes gateway start/stop Control the service
hermes gateway restart Restart the service
hermes gateway status Check status
hermes gateway setup Configure platforms
Supported platforms: Telegram, Discord, Slack, WhatsApp, Signal, Email, SMS, Matrix, Mattermost, Home Assistant, DingTalk, Feishu, WeCom, BlueBubbles (iMessage), Weixin (WeChat), API Server, Webhooks. Open WebUI connects via the API Server adapter.
Platform docs: https://hermes-agent.nousresearch.com/docs/user-guide/messaging/
Discord-specific walkthrough (token, intents, service install, access control): see references/discord-gateway-setup.md in this skill.
- Per-channel personas and skill bindings: see
references/gateway-channel-personas.md (works on Discord, Slack, Telegram, Mattermost, Matrix).
- For long-running Discord-first operations, purpose-specific channel routing, periodic summaries, weekly Dreaming/audit reports, and log-safety patterns: see
references/discord-operating-planes.md.
- For broad Hermes/LifeOS/SQAF ecosystem audits (cron inventory, live services, dashboards, provider/model warnings, and control-plane gaps), see
references/ecosystem-audit.md.
Sessions
hermes sessions list List recent sessions
hermes sessions browse Interactive picker
hermes sessions export OUT Export to JSONL
hermes sessions rename ID T Rename a session
hermes sessions delete ID Delete a session
hermes sessions prune Clean up old sessions (--older-than N days)
hermes sessions stats Session store statistics
For browser-based viewing of existing Hermes CLI/Discord/cron session transcripts, prefer a lightweight static export from ~/.hermes/state.db into a private web root instead of assuming Open WebUI can browse Hermes' native session store. See references/hermes-session-static-web-viewer.md for the SQLite schema, static HTML export workflow, redaction/truncation cautions, and the user's Mac mini deployment (/hermes-sessions/ under the Tailscale-only ~/hermes-web site).
For cron job execution history, the same static-export pattern applies to ~/.hermes/cron/jobs.json and ~/.hermes/cron/output/{job_id}/*.md. See references/cron-history-web-viewer.md for the cron data model, schedule-dict pitfall, and the user's deployed /cron-history/ dashboard.
Cron Jobs
hermes cron list List jobs (--all for disabled)
hermes cron create SCHED Create: '30m', 'every 2h', '0 9 *'
hermes cron edit ID Edit schedule, prompt, delivery
hermes cron pause/resume ID Control job state
hermes cron run ID Trigger on next tick
hermes cron remove ID Delete a job
hermes cron status Scheduler status
For bounded autonomous lab/orchestrator cron jobs that use file-based state, subagent lanes, artifact publishing, and status transitions (active โ complete/blocked/inactive), see references/autonomous-agent-lab-cron-cycle.md. A reusable verification script template lives at scripts/verify-completion-template.py.
For a worked example of evolving an autonomous lab into a config-driven, themeable, Docker-ready installable product, see references/autonomous-lab-product-architecture.md. For CI, integration testing, pluggable adapter architecture, bounded cycle orchestration, and post-productization patterns, see references/product-maturity-patterns.md.
For the final completion verification checklist โ the explicit audit pattern to run before marking status: complete on an installable-solution mission, see references/autonomous-lab-completion-verification.md.
For the reactivation protocol when a completed lab receives new P0 feedback or the user contradicts a completion claim, see references/autonomous-lab-reactivation-protocol.md.
For adding historical trend tracking (SQLite-backed agent status transitions + vanilla JS SVG sparklines) to an autonomous lab dashboard, see references/history-tracking-sparkline-pattern.md.
For reusable dashboard UX patterns (onboarding tours, data freshness badges, keyboard shortcuts, progressive disclosure inspectors, cross-linking between views), see references/dashboard-ux-patterns.md.
For the aggressive human-first inspector refinement โ when users report that details are hard to understand and the fix is to strip technical labels from the default view โ see references/progressive-disclosure-human-first.md.
For programmatic verification of CSS custom-property theme systems โ catching scoping bugs, confirming theme distinctness, and validating JS switching logic โ see references/theme-system-verification.md.
For Son's Discord-first autonomous experiments where a channel hosts a repeated multi-agent loop, use the Autonomous Discord Agent Lab pattern: create file-based durable state, a paused cron orchestrator delivered to discord:<channel_id>, then activate it from a user mission trigger. See references/autonomous-discord-agent-lab.md.
Webhooks
hermes webhook subscribe N Create route at /webhooks/<name>
hermes webhook list List subscriptions
hermes webhook remove NAME Remove a subscription
hermes webhook test NAME Send a test POST
Profiles
hermes profile list List all profiles
hermes profile create NAME Create (--clone, --clone-all, --clone-from)
hermes profile use NAME Set sticky default
hermes profile delete NAME Delete a profile
hermes profile show NAME Show details
hermes profile alias NAME Manage wrapper scripts
hermes profile rename A B Rename a profile
hermes profile export NAME Export to tar.gz
hermes profile import FILE Import from archive
Credential Pools
hermes auth add Interactive credential wizard
hermes auth list [PROVIDER] List pooled credentials
hermes auth remove P INDEX Remove by provider + index
hermes auth reset PROVIDER Clear exhaustion status
Other
hermes insights [--days N] Usage analytics
hermes update Update to latest version
hermes pairing list/approve/revoke DM authorization
hermes plugins list/install/remove Plugin management
hermes honcho setup/status Honcho memory integration (requires honcho plugin)
hermes memory setup/status/off Memory provider config
hermes completion bash|zsh Shell completions
hermes acp ACP server (IDE integration)
hermes claw migrate Migrate from OpenClaw
hermes uninstall Uninstall Hermes
---
Slash Commands (In-Session)
Type these during an interactive chat session. New commands land fairly
often; if something below looks stale, run /help in-session for the
authoritative list or see the [live slash commands reference](https://hermes-agent.nousresearch.com/docs/reference/slash-commands).
The registry of record is hermes_cli/commands.py โ every consumer
(autocomplete, Telegram menu, Slack mapping, /help) derives from it.
Session Control
/new (/reset) Fresh session
/clear Clear screen + new session (CLI)
/retry Resend last message
/undo Remove last exchange
/title [name] Name the session
/compress Manually compress context
/stop Kill background processes
/rollback [N] Restore filesystem checkpoint
/snapshot [sub] Create or restore state snapshots of Hermes config/state (CLI)
/background <prompt> Run prompt in background
/queue <prompt> Queue for next turn
/steer <prompt> Inject a message after the next tool call without interrupting
/agents (/tasks) Show active agents and running tasks
/resume [name] Resume a named session
/goal [text|sub] Set a standing goal Hermes works on across turns until achieved
(subcommands: status, pause, resume, clear)
/redraw Force a full UI repaint (CLI)
Configuration
/config Show config (CLI)
/model [name] Show or change model
/personality [name] Set personality
/reasoning [level] Set reasoning (none|minimal|low|medium|high|xhigh|show|hide)
/verbose Cycle: off โ new โ all โ verbose
/voice [on|off|tts] Voice mode
/yolo Toggle approval bypass
/busy [sub] Control what Enter does while Hermes is working (CLI)
(subcommands: queue, steer, interrupt, status)
/indicator [style] Pick the TUI busy-indicator style (CLI)
(styles: kaomoji, emoji, unicode, ascii)
/footer [on|off] Toggle gateway runtime-metadata footer on final replies
/skin [name] Change theme (CLI)
/statusbar Toggle status bar (CLI)
Tools & Skills
/tools Manage tools (CLI)
/toolsets List toolsets (CLI)
/skills Search/install skills (CLI)
/skill <name> Load a skill into session
/reload-skills Re-scan ~/.hermes/skills/ for added/removed skills
/reload Reload .env variables into the running session (CLI)
/reload-mcp Reload MCP servers
/cron Manage cron jobs (CLI)
/curator [sub] Background skill maintenance (status, run, pin, archive, โฆ)
/kanban [sub] Multi-profile collaboration board (tasks, links, comments)
/plugins List plugins (CLI)
Gateway
/approve Approve a pending command (gateway)
/deny Deny a pending command (gateway)
/restart Restart gateway (gateway)
/sethome Set current chat as home channel (gateway)
/update Update Hermes to latest (gateway)
/topic [sub] Enable or inspect Telegram DM topic sessions (gateway)
/platforms (/gateway) Show platform connection status (gateway)
Utility
/branch (/fork) Branch the current session
/fast Toggle priority/fast processing
/browser Open CDP browser connection
/history Show conversation history (CLI)
/save Save conversation to file (CLI)
/copy [N] Copy the last assistant response to clipboard (CLI)
/paste Attach clipboard image (CLI)
/image Attach local image file (CLI)
Info
/help Show commands
/commands [page] Browse all commands (gateway)
/usage Token usage
/insights [days] Usage analytics
/gquota Show Google Gemini Code Assist quota usage (CLI)
/status Session info (gateway)
/profile Active profile info
/debug Upload debug report (system info + logs) and get shareable links
Exit
/quit (/exit, /q) Exit CLI
---
Key Paths & Config
~/.hermes/config.yaml Main configuration
~/.hermes/.env API keys and secrets
$HERMES_HOME/skills/ Installed skills
~/.hermes/sessions/ Session transcripts
~/.hermes/logs/ Gateway and error logs
~/.hermes/auth.json OAuth tokens and credential pools
~/.hermes/hermes-agent/ Source code (if git-installed)
Profiles use ~/.hermes/profiles/<name>/ with the same layout.
Config Sections
Edit with hermes config edit or hermes config set section.key value.
| Section | Key options |
|---------|-------------|
| model | default, provider, base_url, api_key, context_length |
| agent | max_turns (90), tool_use_enforcement |
| terminal | backend (local/docker/ssh/modal), cwd, timeout (180) |
| compression | enabled, threshold (0.50), target_ratio (0.20) |
| display | skin, tool_progress, show_reasoning, show_cost |
| stt | enabled, provider (local/groq/openai/mistral) |
| tts | provider (edge/elevenlabs/openai/minimax/mistral/neutts) |
| memory | memory_enabled, user_profile_enabled, provider |
| security | tirith_enabled, website_blocklist |
| delegation | model, provider, base_url, api_key, max_iterations (50), reasoning_effort |
| checkpoints | enabled, max_snapshots (50) |
| fallback_model | provider, model, base_url, key_env |
Fallback Providers
Hermes can automatically fail over to a backup provider:model when the primary is unavailable. This is turn-scoped โ each new user message starts with the primary restored; fallback only activates mid-turn when the primary fails.
Configuration ( ~/.hermes/config.yaml):
fallback_model:
provider: opencode-go
model: kimi-k2.6
Or use the interactive manager:
hermes fallback add # interactive picker
hermes fallback list # show fallback chain
hermes fallback remove # remove by index
Legacy note: fallback_model (singular) is the legacy single-fallback key. fallback_providers (list) supports multiple ordered fallbacks. When both exist, fallback_providers takes priority.
Trigger conditions (after exhausting retries where applicable):
- Rate limits (HTTP 429)
- Server errors (HTTP 500, 502, 503)
- Auth failures (HTTP 401, 403) โ immediately
- Not found (HTTP 404) โ immediately
- Invalid / empty responses repeatedly
Supported providers include all standard providers (OpenRouter, Anthropic, OpenCode Go/ Zen, Kimi, etc.) plus custom endpoints with base_url + key_env. Full provider docs: https://hermes-agent.nousresearch.com/docs/integrations/providers
Limitations:
- Subagent delegation does not inherit fallback config
- Cron jobs do not use fallback (use per-job provider/model overrides)
- Auxiliary tasks (vision, compression, etc.) use their own
auxiliary.* provider chain
For a deep-dive with worked examples and model lists, see references/fallback-providers.md.
Full config reference: https://hermes-agent.nousresearch.com/docs/user-guide/configuration
Providers
20+ providers supported. Set via hermes model or hermes setup.
| Provider | Auth | Key env var |
|----------|------|-------------|
| OpenRouter | API key | OPENROUTER_API_KEY |
| Anthropic | API key | ANTHROPIC_API_KEY |
| Nous Portal | OAuth | hermes auth |
| OpenAI Codex | OAuth | hermes auth |
| GitHub Copilot | Token | COPILOT_GITHUB_TOKEN |
| Google Gemini | API key | GOOGLE_API_KEY or GEMINI_API_KEY |
| DeepSeek | API key | DEEPSEEK_API_KEY |
| xAI / Grok | API key | XAI_API_KEY |
| Hugging Face | Token | HF_TOKEN |
| Z.AI / GLM | API key | GLM_API_KEY |
| MiniMax | API key | MINIMAX_API_KEY |
| MiniMax CN | API key | MINIMAX_CN_API_KEY |
| Kimi / Moonshot | API key | KIMI_API_KEY |
| Alibaba / DashScope | API key | DASHSCOPE_API_KEY |
| Xiaomi MiMo | API key | XIAOMI_API_KEY |
| Kilo Code | API key | KILOCODE_API_KEY |
| AI Gateway (Vercel) | API key | AI_GATEWAY_API_KEY |
| OpenCode Zen | API key | OPENCODE_ZEN_API_KEY |
| OpenCode Go | API key | OPENCODE_GO_API_KEY |
| Qwen OAuth | OAuth | hermes auth add qwen-oauth |
| Custom endpoint | Config | model.base_url + model.api_key in config.yaml |
| GitHub Copilot ACP | External | COPILOT_CLI_PATH or Copilot CLI |
Full provider docs: https://hermes-agent.nousresearch.com/docs/integrations/providers
Toolsets
Enable/disable via hermes tools (interactive) or hermes tools enable/disable NAME.
| Toolset | What it provides |
|---------|-----------------|
| web | Web search and content extraction |
| search | Web search only (subset of web) |
| browser | Browser automation (Browserbase, Camofox, or local Chromium) |
| terminal | Shell commands and process management |
| file | File read/write/search/patch |
| code_execution | Sandboxed Python execution |
| vision | Image analysis |
| image_gen | AI image generation |
| video | Video analysis and generation |
| tts | Text-to-speech |
| skills | Skill browsing and management |
| memory | Persistent cross-session memory |
| session_search | Search past conversations |
| delegation | Subagent task delegation |
| cronjob | Scheduled task management |
| clarify | Ask user clarifying questions |
| messaging | Cross-platform message sending |
| todo | In-session task planning and tracking |
| kanban | Multi-agent work-queue tools (gated to workers) |
| debugging | Extra introspection/debug tools (off by default) |
| safe | Minimal, low-risk toolset for locked-down sessions |
| spotify | Spotify playback and playlist control |
| homeassistant | Smart home control (off by default) |
| discord | Discord integration tools |
| discord_admin | Discord admin/moderation tools |
| feishu_doc | Feishu (Lark) document tools |
| feishu_drive | Feishu (Lark) drive tools |
| yuanbao | Yuanbao integration tools |
| rl | Reinforcement learning tools (off by default) |
| moa | Mixture of Agents (off by default) |
Full enumeration lives in toolsets.py as the TOOLSETS dict; _HERMES_CORE_TOOLS is the default bundle most platforms inherit from.
Tool changes take effect on /reset (new session). They do NOT apply mid-conversation to preserve prompt caching.
---
Security & Privacy Toggles
Common "why is Hermes doing X to my output / tool calls / commands?" toggles โ and the exact commands to change them. Most of these need a fresh session (/reset in chat, or start a new hermes invocation) because they're read once at startup.
Secret redaction in tool output
Secret redaction is off by default โ tool output (terminal stdout, read_file, web content, subagent summaries, etc.) passes through unmodified. If the user wants Hermes to auto-mask strings that look like API keys, tokens, and secrets before they enter the conversation context and logs:
hermes config set security.redact_secrets true # enable globally
Restart required. security.redact_secrets is snapshotted at import time โ toggling it mid-session (e.g. via export HERMES_REDACT_SECRETS=true from a tool call) will NOT take effect for the running process. Tell the user to run hermes config set security.redact_secrets true in a terminal, then start a new session. This is deliberate โ it prevents an LLM from flipping the toggle on itself mid-task.
Disable again with:
hermes config set security.redact_secrets false
PII redaction in gateway messages
Separate from secret redaction. When enabled, the gateway hashes user IDs and strips phone numbers from the session context before it reaches the model:
hermes config set privacy.redact_pii true # enable
hermes config set privacy.redact_pii false # disable (default)
Command approval prompts
By default (approvals.mode: manual), Hermes prompts the user before running shell commands flagged as destructive (rm -rf, git reset --hard, etc.). The modes are:
manual โ always prompt (default)
smart โ use an auxiliary LLM to auto-approve low-risk commands, prompt on high-risk
off โ skip all approval prompts (equivalent to --yolo)
hermes config set approvals.mode smart # recommended middle ground
hermes config set approvals.mode off # bypass everything (not recommended)
Per-invocation bypass without changing config:
hermes --yolo โฆ
export HERMES_YOLO_MODE=1
Note: YOLO / approvals.mode: off does NOT turn off secret redaction. They are independent.
Shell hooks allowlist
Some shell-hook integrations require explicit allowlisting before they fire. Managed via ~/.hermes/shell-hooks-allowlist.json โ prompted interactively the first time a hook wants to run.
Disabling the web/browser/image-gen tools
To keep the model away from network or media tools entirely, open hermes tools and toggle per-platform. Takes effect on next session (/reset). See the Tools & Skills section above.
---
Voice & Transcription
STT (Voice โ Text)
Voice messages from messaging platforms are auto-transcribed.
Provider priority (auto-detected):
1. Local faster-whisper โ free, no API key: pip install faster-whisper
2. Groq Whisper โ free tier: set GROQ_API_KEY
3. OpenAI Whisper โ paid: set VOICE_TOOLS_OPENAI_KEY
4. Mistral Voxtral โ set MISTRAL_API_KEY
Config:
stt:
enabled: true
provider: local # local, groq, openai, mistral
local:
model: base # tiny, base, small, medium, large-v3
TTS (Text โ Voice)
| Provider | Env var | Free? |
|----------|---------|-------|
| Edge TTS | None | Yes (default) |
| ElevenLabs | ELEVENLABS_API_KEY | Free tier |
| OpenAI | VOICE_TOOLS_OPENAI_KEY | Paid |
| MiniMax | MINIMAX_API_KEY | Paid |
| Mistral (Voxtral) | MISTRAL_API_KEY | Paid |
| NeuTTS (local) | None (pip install neutts[all] + espeak-ng) | Free |
Voice commands: /voice on (voice-to-voice), /voice tts (always voice), /voice off.
---
Spawning Additional Hermes Instances
Run additional Hermes processes as fully independent subprocesses โ separate sessions, tools, and environments.
When to Use This vs delegate_task
| | delegate_task | Spawning hermes process |
|-|-----------------|--------------------------|
| Isolation | Separate conversation, shared process | Fully independent process |
| Duration | Minutes (bounded by parent loop) | Hours/days |
| Tool access | Subset of parent's tools | Full tool access |
| Interactive | No | Yes (PTY mode) |
| Use case | Quick parallel subtasks | Long autonomous missions |
One-Shot Mode
terminal(command="hermes chat -q 'Research GRPO papers and write summary to ~/research/grpo.md'", timeout=300)
Background for long tasks:
terminal(command="hermes chat -q 'Set up CI/CD for ~/myapp'", background=true)
Interactive PTY Mode (via tmux)
Hermes uses prompt_toolkit, which requires a real terminal. Use tmux for interactive spawning:
Start
terminal(command="tmux new-session -d -s agent1 -x 120 -y 40 'hermes'", timeout=10)
Wait for startup, then send a message
terminal(command="sleep 8 && tmux send-keys -t agent1 'Build a FastAPI auth service' Enter", timeout=15)
Read output
terminal(command="sleep 20 && tmux capture-pane -t agent1 -p", timeout=5)
Send follow-up
terminal(command="tmux send-keys -t agent1 'Add rate limiting middleware' Enter", timeout=5)
Exit
terminal(command="tmux send-keys -t agent1 '/exit' Enter && sleep 2 && tmux kill-session -t agent1", timeout=10)
Multi-Agent Coordination
Agent A: backend
terminal(command="tmux new-session -d -s backend -x 120 -y 40 'hermes -w'", timeout=10)
terminal(command="sleep 8 && tmux send-keys -t backend 'Build REST API for user management' Enter", timeout=15)
Agent B: frontend
terminal(command="tmux new-session -d -s frontend -x 120 -y 40 'hermes -w'", timeout=10)
terminal(command="sleep 8 && tmux send-keys -t frontend 'Build React dashboard for user management' Enter", timeout=15)
Check progress, relay context between them
terminal(command="tmux capture-pane -t backend -p | tail -30", timeout=5)
terminal(command="tmux send-keys -t frontend 'Here is the API schema from the backend agent: ...' Enter", timeout=5)
Session Resume
Resume most recent session
terminal(command="tmux new-session -d -s resumed 'hermes --continue'", timeout=10)
Resume specific session
terminal(command="tmux new-session -d -s resumed 'hermes --resume 20260225_143052_a1b2c3'", timeout=10)
Tips
- Prefer
delegate_task for quick subtasks โ less overhead than spawning a full process
- Use
-w (worktree mode) when spawning agents that edit code โ prevents git conflicts
- Set timeouts for one-shot mode โ complex tasks can take 5-10 minutes
- Use
hermes chat -q for fire-and-forget โ no PTY needed
- Use tmux for interactive sessions โ raw PTY mode has
\r vs \n issues with prompt_toolkit
- For scheduled tasks, use the
cronjob tool instead of spawning โ handles delivery and retry
---
Durable & Background Systems
Four systems run alongside the main conversation loop. Quick reference
here; full developer notes live in AGENTS.md, user-facing docs under
website/docs/user-guide/features/.
Delegation (delegate_task)
Synchronous subagent spawn โ the parent waits for the child's summary
before continuing its own loop. Isolated context + terminal session.
- Single:
delegate_task(goal, context, toolsets).
- Batch:
delegate_task(tasks=[{goal, ...}, ...]) runs children in
parallel, capped by delegation.max_concurrent_children (default 3).
- Roles:
leaf (default; cannot re-delegate) vs orchestrator
(can spawn its own workers, bounded by delegation.max_spawn_depth).
- Not durable. If the parent is interrupted, the child is
cancelled. For work that must outlive the turn, use cronjob or
terminal(background=True, notify_on_complete=True).
Config: delegation.* in config.yaml.
Tuning max_concurrent_children
Default is 3. Rule of thumb for raising it:
- Light tasks (web search, file grep): up to
6-8
- Medium tasks (code execution, browser):
4-5
- Heavy tasks (builds, large data):
2-3
- Actual bottleneck is usually the API rate limit, not local CPU/RAM. On a 10-core M4 with 16GB RAM, CPU is rarely the constraint.
- Formula: start at
5, raise only if profiling shows idle time between API responses.
Cron (scheduled jobs)
Durable scheduler โ cron/jobs.py + cron/scheduler.py. Drive it via
the cronjob tool, the hermes cron CLI (list, add, edit,
pause, resume, run, remove), or the /cron slash command.
- Schedules: duration (
"30m", "2h"), "every" phrase
( "every monday 9am"), 5-field cron ( "0 9 *"), or ISO timestamp.
- Per-job knobs:
skills, model/provider override, script
(pre-run data collection; no_agent=True makes the script the whole
job), context_from (chain job A's output into job B), workdir
(run in a specific dir with its AGENTS.md / CLAUDE.md loaded),
multi-platform delivery.
- Invariants: 3-minute hard interrupt per run,
.tick.lock file
prevents duplicate ticks across processes, cron sessions pass
skip_memory=True by default, and cron deliveries are framed with a
header/footer instead of being mirrored into the target gateway
session (keeps role alternation intact).
User docs: https://hermes-agent.nousresearch.com/docs/user-guide/features/cron
Curator (skill lifecycle)
Background maintenance for agent-created skills. Tracks usage, marks
idle skills stale, archives stale ones, keeps a pre-run tar.gz backup
so nothing is lost.
- CLI:
hermes curator <verb> โ status, run, pause, resume,
pin, unpin, archive, restore, prune, backup, rollback.
- Slash:
/curator <subcommand> mirrors the CLI.
- Scope: only touches skills with
created_by: "agent" provenance.
Bundled + hub-installed skills are off-limits. Never deletes โ
max destructive action is archive. Pinned skills are exempt from
every auto-transition and every LLM review pass.
- Telemetry: sidecar at
~/.hermes/skills/.usage.json holds
per-skill use_count, view_count, patch_count,
last_activity_at, state, pinned.
Config: curator.* (enabled, interval_hours, min_idle_hours,
stale_after_days, archive_after_days, backup.*).
User docs: https://hermes-agent.nousresearch.com/docs/user-guide/features/curator
Dreaming (periodic memory/skill consolidation)
For Anthropic-style "dreaming" workflows, combine cron + session_search + memory + skills + curator into a scheduled review loop. Start with a weekly, proposal-only report that audits recent sessions, repeated user corrections, memory conflicts, skill patch candidates, and cron/automation improvements. Do not automatically delete/replace memory or patch/archive skills unless the user explicitly approves the proposed changes. See references/weekly-dreaming-routine.md for the recommended prompt, report format, safety policy, and cron creation pattern.
Kanban (multi-agent work queue)
Durable SQLite board for multi-profile / multi-worker collaboration.
Users drive it via hermes kanban <verb>; dispatcher-spawned workers
see a focused kanban_* toolset gated by HERMES_KANBAN_TASK so the
schema footprint is zero outside worker processes.
- CLI verbs (common):
init, create, list (alias ls),
show, assign, link, unlink, comment, complete, block,
unblock, archive, tail. Less common: watch, stats, runs,
log, dispatch, daemon, gc.
- Worker toolset:
kanban_show, kanban_complete, kanban_block,
kanban_heartbeat, kanban_comment, kanban_create, kanban_link.
- Dispatcher runs inside the gateway by default
( kanban.dispatch_in_gateway: true) โ reclaims stale claims,
promotes ready tasks, atomically claims, spawns assigned profiles.
Auto-blocks a task after ~5 consecutive spawn failures.
- Isolation: board is the hard boundary (workers get
HERMES_KANBAN_BOARD pinned in env); tenant is a soft namespace
within a board for workspace-path + memory-key isolation.
User docs: https://hermes-agent.nousresearch.com/docs/user-guide/features/kanban
Log Relay (Hermes โ Discord)
A background Python script that tails ~/.hermes/logs/*.log and batches lines to a Discord channel. Includes session-ID extraction, rate-limit handling, and auto-restart via launchd/systemd. Useful for remote monitoring and audit trails.
- Reference:
references/discord-log-relay.md โ full setup, tuning, macOS/Linux service install, pitfalls.
- Template:
templates/discord-log-relay.py โ copy, set CHANNEL_ID, and deploy.
- Discord operations:
references/discord-operating-planes.md โ channel-purpose routing, periodic-summary vs Dreaming report formats, and safety/cost notes for Discord-first Hermes deployments.
Key pitfall: ask the user about batch frequency upfront rather than defaulting to real-time streaming. Most users prefer 10-minute or hourly batches. High-volume raw logs should be batched, summarized, or stored out-of-band; avoid Discord message storms during error loops.
Weekly Dreaming / Memory Curation
For long-running Hermes deployments, users may want an Anthropic-style "Dreaming" loop: a scheduled review that consolidates experience, proposes memory/skill/cron changes, and identifies what to keep, weaken, archive, or delete. Hermes has the building blocks (sessions, session_search, memory, skills, curator, cron), but the safe default is proposal mode:
1. Inspect recent usage and sessions.
2. Extract repeated success patterns, failure patterns, and user corrections.
3. Propose memory updates/removals without applying them silently.
4. Propose skill patches/archive candidates and cron/reporting improvements.
5. End with explicit approval checkboxes.
Do not silently rewrite or delete memory/skills from a Dreaming report unless the user explicitly authorized automatic application. See references/discord-operating-planes.md for a report template and routing heuristics.
---
Windows-Specific Quirks
Hermes runs natively on Windows (PowerShell, cmd, Windows Terminal, git-bash
mintty, VS Code integrated terminal). Most of it just works, but a handful
of differences between Win32 and POSIX have bitten us โ document new ones
here as you hit them so the next person (or the next session) doesn't
rediscover them from scratch.
Input / Keybindings
Alt+Enter doesn't insert a newline. Windows Terminal intercepts Alt+Enter
at the terminal layer to toggle fullscreen โ the keystroke never reaches
prompt_toolkit. Use Ctrl+Enter instead. Windows Terminal delivers
Ctrl+Enter as LF ( c-j), distinct from plain Enter ( c-m / CR), and the
CLI binds c-j to newline insertion on win32 only (see
_bind_prompt_submit_keys + the Windows-only c-j binding in cli.py).
Side effect: the raw Ctrl+J keystroke also inserts a newline on Windows โ
unavoidable, because Windows Terminal collapses Ctrl+Enter and Ctrl+J to
the same keycode at the Win32 console API layer. No conflicting binding
existed for Ctrl+J on Windows, so this is a harmless side effect.
mintty / git-bash behaves the same (fullscreen on Alt+Enter) unless you
disable Alt+Fn shortcuts in Options โ Keys. Easier to just use Ctrl+Enter.
Diagnosing keybindings. Run python scripts/keystroke_diagnostic.py
(repo root) to see exactly how prompt_toolkit identifies each keystroke
in the current terminal. Answers questions like "does Shift+Enter come
through as a distinct key?" (almost never โ most terminals collapse it
to plain Enter) or "what byte sequence is my terminal sending for
Ctrl+Enter?" This is how the Ctrl+Enter = c-j fact was established.
Config / Files
HTTP 400 "No models provided" on first run. config.yaml was saved
with a UTF-8 BOM (common when Windows apps write it). Re-save as UTF-8
without BOM. hermes config edit writes without BOM; manual edits in
Notepad are the usual culprit.
execute_code / Sandbox
WinError 10106 ("The requested service provider could not be loaded
or initialized") from the sandbox child process โ it can't create an
AF_INET socket, so the loopback-TCP RPC fallback fails before
connect(). Root cause is usually not a broken Winsock LSP; it's
Hermes's own env scrubber dropping SYSTEMROOT / WINDIR / COMSPEC
from the child env. Python's socket module needs SYSTEMROOT to locate
mswsock.dll. Fixed via the _WINDOWS_ESSENTIAL_ENV_VARS allowlist in
tools/code_execution_tool.py. If you still hit it, echo os.environ
inside an execute_code block to confirm SYSTEMROOT is set. Full
diagnostic recipe in references/execute-code-sandbox-env-windows.md.
Testing / Contributing
scripts/run_tests.sh doesn't work as-is on Windows โ it looks for
POSIX venv layouts ( .venv/bin/activate). The Hermes-installed venv at
venv/Scripts/ has no pip or pytest either (stripped for install size).
Workaround: install pytest + pytest-xdist + pyyaml into a system Python
3.11 user site, then invoke pytest directly with PYTHONPATH set:
"/c/Program Files/Python311/python" -m pip install --user pytest pytest-xdist pyyaml
export PYTHONPATH="$(pwd)"
"/c/Program Files/Python311/python" -m pytest tests/foo/test_bar.py -v --tb=short -n 0
Use -n 0, not -n 4 โ pyproject.toml's default addopts already
includes -n, and the wrapper's CI-parity guarantees don't apply off POSIX.
POSIX-only tests need skip guards. Common markers already in the codebase:
- Symlinks โ elevated privileges on Windows
0o600 file modes โ POSIX mode bits not enforced on NTFS by default
signal.SIGALRM โ Unix-only (see tests/conftest.py::_enforce_test_timeout)
- Winsock / Windows-specific regressions โ
@pytest.mark.skipif(sys.platform != "win32", ...)
Use the existing skip-pattern style (sys.platform == "win32" or
sys.platform.startswith("win")) to stay consistent with the rest of the
suite.
Path / Filesystem
Line endings. Git may warn LF will be replaced by CRLF the next time
Git touches it. Cosmetic โ the repo's .gitattributes normalizes. Don't
let editors auto-convert committed POSIX-newline files to CRLF.
Forward slashes work almost everywhere. C:/Users/... is accepted by
every Hermes tool and most Windows APIs. Prefer forward slashes in code
and logs โ avoids shell-escaping backslashes in bash.
---
Troubleshooting
Voice not working
1. Check stt.enabled: true in config.yaml
2. Verify provider: pip install faster-whisper or set API key
3. In gateway: /restart. In CLI: exit and relaunch.
Tool not available
1. hermes tools โ check if toolset is enabled for your platform
2. Some tools need env vars (check .env)
3. /reset after enabling tools
Model/provider issues
1. hermes doctor โ check config and dependencies
2. hermes auth add <provider> โ re-authenticate OAuth providers (use --type oauth)
3. Check .env has the right API key
4. Copilot 403: gh auth login tokens do NOT work for Copilot API. You must use the Copilot-specific OAuth device code flow via hermes model โ GitHub Copilot.
Changes not taking effect
- Tools/skills:
/reset starts a new session with updated toolset
- Config changes: In gateway:
/restart. In CLI: exit and relaunch.
- Code changes: Restart the CLI or gateway process
Deployed web dashboard shows stale CSS or theme changes
- Browser cache: Add
?v=N cache-busting query strings to CSS/JS/theme links in HTML.
- Service Worker cache: Bump
CACHE_NAME in sw.js to invalidate old shell caches.
- Data freshness: Use
fetch(url, {cache:'no-store'}) for live JSON feeds.
- See
references/static-site-cache-invalidation.md for the full diagnostic recipe.
Dashboard inspector feels too technical
- The default inspector view should contain only plain-language sentences: headline, "what they're doing now", "why it matters", and a silent visual progress bar (no text label).
- Move all technical fields (source IDs, confidence scores, progress labels, status slugs, badges) behind a "Show technical details" toggle.
- If users say "details are hard to understand," the fix is to remove more fields from the default view, not to add explanations. Explanations of technical fields are still technical.
- See
references/progressive-disclosure-human-first.md for the aggressive simplification pattern.
Skills not showing
1. hermes skills list โ verify installed
2. hermes skills config โ check platform enablement
3. Load explicitly: /skill name or hermes -s name
Gateway issues
Check logs first:
grep -i "failed to send\|error" ~/.hermes/logs/gateway.log | tail -20
Common gateway problems:
- Gateway dies on SSH logout: Enable linger:
sudo loginctl enable-linger $USER
- Gateway dies on WSL2 close: WSL2 requires
systemd=true in /etc/wsl.conf for systemd services to work. Without it, gateway falls back to nohup (dies when session closes).
- Gateway crash loop: Reset the failed state:
systemctl --user reset-failed hermes-gateway
- macOS: bot shows offline after idle time: The gateway runs as a user agent (
LimitLoadToSessionType=Aqua), so macOS suspends it when the system sleeps. The platform websocket drops and the bot appears offline until the network returns. Fix: keep the Mac awake (System Settings -> Energy -> Prevent automatic sleeping, or caffeinate -d -i -s -u &). Low Power Mode makes this worse, not better. See references/macos-gateway-sleep-disconnect.md for the full diagnostic recipe.
Platform-specific issues
- Discord bot silent: Must enable Message Content Intent in Bot โ Privileged Gateway Intents. See full Discord setup reference:
references/discord-gateway-setup.md.
- Slack bot only works in DMs: Must subscribe to
message.channels event. Without it, the bot ignores public channels.
- Windows-specific issues (
Alt+Enter newline, WinError 10106, UTF-8 BOM config, test suite, line endings): see the dedicated Windows-Specific Quirks section above.
Auxiliary models not working
If auxiliary tasks (vision, compression, session_search) fail silently, the auto provider can't find a backend. Either set OPENROUTER_API_KEY or GOOGLE_API_KEY, or explicitly configure each auxiliary task's provider:
hermes config set auxiliary.vision.provider <your_provider>
hermes config set auxiliary.vision.model <model_name>
Full system auth provisioning
For a one-shot workflow to maximize available credentials โ installing gh, generating SSH keys, configuring git, enabling all Hermes toolsets, and auditing current auth state โ see references/system-auth-setup.md.
Editing large files with patch
When a file is read with read_file(offset=...) (pagination), the tool warns that the view is partial. If you attempt patch without re-reading the full file first, you will likely hit non-unique match errors or corrupt the file. Fix: always call read_file without offset to load the whole file before patching. For append-only updates (e.g., adding a cycle log entry to state.md), terminal(command="cat >> file << 'EOF'...EOF") is a safer fallback that bypasses match-uniqueness issues entirely.
---
Windows-Specific Quirks
| Looking for... | Location |
|----------------|----------|
| Config options | hermes config edit or [Configuration docs](https://hermes-agent.nousresearch.com/docs/user-guide/configuration) |
| Available tools | hermes tools list or [Tools reference](https://hermes-agent.nousresearch.com/docs/reference/tools-reference) |
| Slash commands | /help in session or [Slash commands reference](https://hermes-agent.nousresearch.com/docs/reference/slash-commands) |
| Skills catalog | hermes skills browse or [Skills catalog](https://hermes-agent.nousresearch.com/docs/reference/skills-catalog) |
| Provider setup | hermes model or [Providers guide](https://hermes-agent.nousresearch.com/docs/integrations/providers) |
| Platform setup | hermes gateway setup or [Messaging docs](https://hermes-agent.nousresearch.com/docs/user-guide/messaging/) |
| MCP servers | hermes mcp list or [MCP guide](https://hermes-agent.nousresearch.com/docs/user-guide/features/mcp) |
| Profiles | hermes profile list or [Profiles docs](https://hermes-agent.nousresearch.com/docs/user-guide/profiles) |
| Cron jobs | hermes cron list or [Cron docs](https://hermes-agent.nousresearch.com/docs/user-guide/features/cron) |
| Memory | hermes memory status or [Memory docs](https://hermes-agent.nousresearch.com/docs/user-guide/features/memory) |
| Env variables | hermes config env-path or [Env vars reference](https://hermes-agent.nousresearch.com/docs/reference/environment-variables) |
| CLI commands | hermes --help or [CLI reference](https://hermes-agent.nousresearch.com/docs/reference/cli-commands) |
| Gateway logs | ~/.hermes/logs/gateway.log |
| Session files | ~/.hermes/sessions/ or hermes sessions browse |
| Source code | ~/.hermes/hermes-agent/ |
---
Contributor Quick Reference
For occasional contributors and PR authors. Full developer docs: https://hermes-agent.nousresearch.com/docs/developer-guide/
Project Layout
hermes-agent/
โโโ run_agent.py # AIAgent โ core conversation loop
โโโ model_tools.py # Tool discovery and dispatch
โโโ toolsets.py # Toolset definitions
โโโ cli.py # Interactive CLI (HermesCLI)
โโโ hermes_state.py # SQLite session store
โโโ agent/ # Prompt builder, context compression, memory, model routing, credential pooling, skill dispatch
โโโ hermes_cli/ # CLI subcommands, config, setup, commands
โ โโโ commands.py # Slash command registry (CommandDef)
โ โโโ config.py # DEFAULT_CONFIG, env var definitions
โ โโโ main.py # CLI entry point and argparse
โโโ tools/ # One file per tool
โ โโโ registry.py # Central tool registry
โโโ gateway/ # Messaging gateway
โ โโโ platforms/ # Platform adapters (telegram, discord, etc.)
โโโ cron/ # Job scheduler
โโโ tests/ # ~3000 pytest tests
โโโ website/ # Docusaurus docs site
Config: ~/.hermes/config.yaml (settings), ~/.hermes/.env (API keys).
Adding a Tool (3 files)
1. Create tools/your_tool.py:
import json, os
from tools.registry import registry
def check_requirements() -> bool:
return bool(os.getenv("EXAMPLE_API_KEY"))
def example_tool(param: str, task_id: str = None) -> str:
return json.dumps({"success": True, "data": "..."})
registry.register(
name="example_tool",
toolset="example",
schema={"name": "example_tool", "description": "...", "parameters": {...}},
handler=lambda args, **kw: example_tool(
param=args.get("param", ""), task_id=kw.get("task_id")),
check_fn=check_requirements,
requires_env=["EXAMPLE_API_KEY"],
)
2. Add to toolsets.py โ _HERMES_CORE_TOOLS list.
Auto-discovery: any tools/*.py file with a top-level registry.register() call is imported automatically โ no manual list needed.
All handlers must return JSON strings. Use get_hermes_home() for paths, never hardcode ~/.hermes.
Adding a Slash Command
1. Add CommandDef to COMMAND_REGISTRY in hermes_cli/commands.py
2. Add handler in cli.py โ process_command()
3. (Optional) Add gateway handler in gateway/run.py
All consumers (help text, autocomplete, Telegram menu, Slack mapping) derive from the central registry automatically.
Agent Loop (High Level)
run_conversation():
1. Build system prompt
2. Loop while iterations < max:
a. Call LLM (OpenAI-format messages + tool schemas)
b. If tool_calls โ dispatch each via handle_function_call() โ append results โ continue
c. If text response โ return
3. Context compression triggers automatically near token limit
Testing
python -m pytest tests/ -o 'addopts=' -q # Full suite
python -m pytest tests/tools/ -q # Specific area
- Tests auto-redirect
HERMES_HOME to temp dirs โ never touch real ~/.hermes/
- Run full suite before pushing any change
- Use
-o 'addopts=' to clear any baked-in pytest flags
Windows contributors: scripts/run_tests.sh currently looks for POSIX venvs ( .venv/bin/activate / venv/bin/activate) and will error out on Windows where the layout is venv/Scripts/activate + python.exe. The Hermes-installed venv at venv/Scripts/ also has no pip or pytest โ it's stripped for end-user install size. Workaround: install pytest + pytest-xdist + pyyaml into a system Python 3.11 user site ( /c/Program Files/Python311/python -m pip install --user pytest pytest-xdist pyyaml), then run tests directly:
export PYTHONPATH="$(pwd)"
"/c/Program Files/Python311/python" -m pytest tests/tools/test_foo.py -v --tb=short -n 0
Use -n 0 (not -n 4) because pyproject.toml's default addopts already includes -n, and the wrapper's CI-parity story doesn't apply off-POSIX.
Cross-platform test guards: tests that use POSIX-only syscalls need a skip marker. Common ones already in the codebase:
- Symlink creation โ
@pytest.mark.skipif(sys.platform == "win32", reason="Symlinks require elevated privileges on Windows") (see tests/cron/test_cron_script.py)
- POSIX file modes (0o600, etc.) โ
@pytest.mark.skipif(sys.platform.startswith("win"), reason="POSIX mode bits not enforced on Windows") (see tests/hermes_cli/test_auth_toctou_file_modes.py)
signal.SIGALRM โ Unix-only (see tests/conftest.py::_enforce_test_timeout)
- Live Winsock / Windows-specific regression tests โ
@pytest.mark.skipif(sys.platform != "win32", reason="Windows-specific regression")
Monkeypatching sys.platform is not enough when the code under test also calls platform.system() / platform.release() / platform.mac_ver(). Those functions re-read the real OS independently, so a test that sets sys.platform = "linux" on a Windows runner will still see platform.system() == "Windows" and route through the Windows branch. Patch all three together:
monkeypatch.setattr(sys, "platform", "linux")
monkeypatch.setattr(platform, "system", lambda: "Linux")
monkeypatch.setattr(platform, "release", lambda: "6.8.0-generic")
See tests/agent/test_prompt_builder.py::TestEnvironmentHints for a worked example.
Extending the system prompt's execution-environment block
Factual guidance about the host OS, user home, cwd, terminal backend, and shell (bash vs. PowerShell on Windows) is emitted from agent/prompt_builder.py::build_environment_hints(). This is also where the WSL hint and per-backend probe logic live. The convention:
- Local terminal backend โ emit host info (OS,
$HOME, cwd) + Windows-specific notes (hostname โ username, terminal uses bash not PowerShell).
- Remote terminal backend (anything in
_REMOTE_TERMINAL_BACKENDS: docker, singularity, modal, daytona, ssh, vercel_sandbox, managed_modal) โ suppress host info entirely and describe only the backend. A live uname/whoami/pwd probe runs inside the backend via tools.environments.get_environment(...).execute(...), cached per process in _BACKEND_PROBE_CACHE, with a static fallback if the probe times out.
- Key fact for prompt authoring: when
TERMINAL_ENV != "local", every file tool (read_file, write_file, patch, search_files) runs inside the backend container, not on the host. The system prompt must never describe the host in that case โ the agent can't touch it.
Full design notes, the exact emitted strings, and testing pitfalls:
references/prompt-builder-environment-hints.md.
Refactor-safety pattern (POSIX-equivalence guard): when you extract inline logic into a helper that adds Windows/platform-specific behavior, keep a _legacy_<name> oracle function in the test file that's a verbatim copy of the old code, then parametrize-diff against it. Example: tests/tools/test_code_execution_windows_env.py::TestPosixEquivalence. This locks in the invariant that POSIX behavior is bit-for-bit identical and makes any future drift fail loudly with a clear diff.
Commit Conventions
type: concise subject line
Optional body.
Types: fix:, feat:, refactor:, docs:, chore:
Key Rules
- Never break prompt caching โ don't change context, tools, or system prompt mid-conversation
- Message role alternation โ never two assistant or two user messages in a row
- Use
get_hermes_home() from hermes_constants for all paths (profile-safe)
- Config values go in
config.yaml, secrets go in .env
- New tools need a
check_fn so they only appear when requirements are met
[IMPORTANT: The user has invoked the "kanban-orchestrator" skill, indicating they want you to follow its instructions. The full skill content is loaded below.]
---
name: kanban-orchestrator
description: Decomposition playbook + anti-temptation rules for an orchestrator profile routing work through Kanban. The "don't do the work yourself" rule and the basic lifecycle are auto-injected into every kanban worker's system prompt; this skill is the deeper playbook when you're specifically playing the orchestrator role.
version: 3.0.0
platforms: [linux, macos, windows]
metadata:
hermes:
tags: [kanban, multi-agent, orchestration, routing]
related_skills: [kanban-worker]
---
Kanban Orchestrator โ Decomposition Playbook
> The core worker lifecycle (including the kanban_create fan-out pattern and the "decompose, don't execute" rule) is auto-injected into every kanban process via the KANBAN_GUIDANCE system-prompt block. This skill is the deeper playbook when you're an orchestrator profile whose whole job is routing.
Profiles are user-configured โ not a fixed roster
Hermes setups vary widely. Some users run a single profile that does everything; some run a small fleet (docker-worker, cron-worker); some run a curated specialist team they've named themselves. There is no default specialist roster โ the orchestrator skill does not know what profiles exist on this machine.
Before fanning out, you must ground the decomposition in the profiles that actually exist. The dispatcher silently fails to spawn unknown assignee names โ it doesn't autocorrect, doesn't suggest, doesn't fall back. So a card assigned to researcher on a setup that only has docker-worker just sits in ready forever.
Step 0: discover available profiles before planning.
Use one of these:
hermes profile list โ prints the table of profiles configured on this machine. Run it through your terminal tool if you have one; otherwise ask the user.
kanban_list(assignee="<some-name>") โ sanity-check a single name. Returns an empty list (rather than an error) for an unknown assignee, so this only confirms a name you're already considering.
- Just ask the user. "What profiles do you have set up?" is a fine first turn when the goal needs more than one specialist.
Cache the result in your working memory for the rest of the conversation. Re-asking every turn wastes a tool call.
When to use the board (vs. just doing the work)
Create Kanban tasks when any of these are true:
1. Multiple specialists are needed. Research + analysis + writing is three profiles.
2. The work should survive a crash or restart. Long-running, recurring, or important.
3. The user might want to interject. Human-in-the-loop at any step.
4. Multiple subtasks can run in parallel. Fan-out for speed.
5. Review / iteration is expected. A reviewer profile loops on drafter output.
6. The audit trail matters. Board rows persist in SQLite forever.
If none of those apply โ it's a small one-shot reasoning task โ use delegate_task instead or answer the user directly.
The anti-temptation rules
Your job description says "route, don't execute." The rules that enforce that:
- Do not execute the work yourself. Your restricted toolset usually doesn't even include terminal/file/code/web for implementation. If you find yourself "just fixing this quickly" โ stop and create a task for the right specialist.
- For any concrete task, create a Kanban task and assign it. Every single time.
- Split multi-lane requests before creating cards. A user prompt can contain several independent workstreams. Extract those lanes first, then create one card per lane instead of bundling unrelated work into a single implementer card.
- Run independent lanes in parallel. If two cards do not need each other's output, leave them unlinked so the dispatcher can fan them out. Link only true data dependencies.
- If no specialist fits the available profiles, ask the user which profile to create or which existing profile to use. Do not invent profile names; the dispatcher will silently drop unknown assignees.
- Decompose, route, and summarize โ that's the whole job.
Exception: micro-UI polish cycles
There is one narrow exception where the orchestrator may execute directly instead of creating Kanban cards: tiny UI-only polish cycles (e.g., adding a CSS class, a theme preview dot, a hover state, a cross-link, or a HUD button) that are purely presentational, require no cross-file logic changes, and fit comfortably inside a single bounded cycle with no need for review or parallel work. If the change is limited to HTML/CSS/JS cosmetics, no other profile has a stake in it, and the user did not ask for a design review, the orchestrator should just edit and publish rather than paying the kanban-overhead tax. This exception does NOT apply to architecture changes, adapter logic, plugin interfaces, or anything that touches the data layer.
Decomposition playbook
Step 1 โ Understand the goal
Ask clarifying questions if the goal is ambiguous. Cheap to ask; expensive to spawn the wrong fleet.
Step 2 โ Sketch the task graph
Before creating anything, draft the graph out loud (in your response to the user). Treat every concrete workstream as a candidate card:
1. Extract the lanes from the request.
2. Map each lane to one of the profiles you discovered in Step 0. If a lane doesn't fit any existing profile, ask the user which to use or create.
3. Decide whether each lane is independent or gated by another lane.
4. Create independent lanes as parallel cards with no parent links.
5. Create synthesis/review/integration cards with parent links to the lanes they depend on.
Examples of prompts that should fan out (using placeholder profile names โ substitute whatever exists on the user's setup):
- "Build an app" โ one card to a design-oriented profile for product/UI direction, one or two cards to engineering profiles for implementation, plus a later integration/review card if the user has a reviewer profile.
- "Fix blockers and check model variants" โ one implementation card for the blocker fixes plus one discovery/research card for config/source verification. A final reviewer card can depend on both.
- "Research docs and implement" โ a docs-research card can run in parallel with a codebase-discovery card; implementation waits only if it truly needs those findings.
- "Analyze this screenshot and find the related code" โ one card to a vision-capable profile for the visual analysis while another searches the codebase.
Words like "also," "finally," or "and" do not automatically imply a dependency. They often mean "make sure this is covered before reporting back." Only link tasks when one card cannot start until another card's output exists.
Show the graph to the user before creating cards. Let them correct it โ including which actual profile name should own each lane.
Step 3 โ Create tasks and link
Use the profile names from Step 0. The example below uses placeholders <profile-A>, <profile-B>, <profile-C> โ replace them with what the user actually has.
t1 = kanban_create(
title="research: Postgres cost vs current",
assignee="<profile-A>", # whichever profile handles research on this setup
body="Compare estimated infrastructure costs, migration costs, and ongoing ops costs over a 3-year window. Sources: AWS/GCP pricing, team time estimates, current Postgres bills from peers.",
tenant=os.environ.get("HERMES_TENANT"),
)["task_id"]
t2 = kanban_create(
title="research: Postgres performance vs current",
assignee="<profile-A>", # same profile, run in parallel
body="Compare query latency, throughput, and scaling characteristics at our expected data volume (~500GB, 10k QPS peak). Sources: benchmark papers, public case studies, pgbench results if easy.",
)["task_id"]
t3 = kanban_create(
title="synthesize migration recommendation",
assignee="<profile-B>", # whichever profile does synthesis/analysis
body="Read the findings from T1 (cost) and T2 (performance). Produce a 1-page recommendation with explicit trade-offs and a go/no-go call.",
parents=[t1, t2],
)["task_id"]
t4 = kanban_create(
title="draft decision memo",
assignee="<profile-C>", # whichever profile drafts user-facing prose
body="Turn the analyst's recommendation into a 2-page memo for the CTO. Match the tone of previous decision memos in the team's knowledge base.",
parents=[t3],
)["task_id"]
parents=[...] gates promotion โ children stay in todo until every parent reaches done, then auto-promote to ready. No manual coordination needed; the dispatcher and dependency engine handle it.
Step 4 โ Complete your own task
If you were spawned as a task yourself (e.g. a planner profile was assigned T0: "investigate Postgres migration"), mark it done with a summary of what you created:
kanban_complete(
summary="decomposed into T1-T4: 2 research lanes in parallel, 1 synthesis on their outputs, 1 prose draft on the recommendation",
metadata={
"task_graph": {
"T1": {"assignee": "<profile-A>", "parents": []},
"T2": {"assignee": "<profile-A>", "parents": []},
"T3": {"assignee": "<profile-B>", "parents": ["T1", "T2"]},
"T4": {"assignee": "<profile-C>", "parents": ["T3"]},
},
},
)
Step 5 โ Report back to the user
Tell them what you created in plain prose, naming the actual profiles you used:
> I've queued 4 tasks:
> - T1 (<profile-A>): cost comparison
> - T2 (<profile-A>): performance comparison, in parallel with T1
> - T3 (<profile-B>): synthesizes T1 + T2 into a recommendation
> - T4 (<profile-C>): turns T3 into a CTO memo
>
> The dispatcher will pick up T1 and T2 now. T3 starts when both finish. You'll get a gateway ping when T4 completes. Use the dashboard or hermes kanban tail <id> to follow along.
Common patterns
Fan-out + fan-in (research โ synthesize): N research-style cards with no parents, one synthesis card with all of them as parents.
Parallel implementation + validation: one implementer card makes the change while one explorer/researcher card verifies config, docs, or source mapping. A reviewer card can depend on both. Do not make the implementer own unrelated verification just because the user mentioned both in one sentence.
Pipeline with gates: planner โ implementer โ reviewer. Each stage's parents=[previous_task]. Reviewer blocks or completes; if reviewer blocks, the operator unblocks with feedback and respawns.
Same-profile queue: N tasks, all assigned to the same profile, no dependencies between them. Dispatcher serializes โ that profile processes them in priority order, accumulating experience in its own memory.
Parallel UI/frontend lanes: When the goal touches multiple independent HTML/CSS/JS files (e.g., a dashboard page and a 2D gather view), fan out to separate subagents per file. Each lane edits its own file, then the orchestrator integrates, fixes cross-file references (theme paths, shared JSON endpoints), and publishes. This avoids merge conflicts in single-file HTML dashboards and keeps each subagent's context focused. See references/parallel-ui-lanes-and-publishing.md for the post-subagent integration checklist and rsync safety notes.
Human-in-the-loop: Any task can kanban_block() to wait for input. Dispatcher respawns after /unblock. The comment thread carries the full context.
Pitfalls
Inventing profile names that don't exist. The dispatcher silently fails to spawn unknown assignees โ the card just sits in ready forever. Always assign to a profile from your Step 0 discovery; ask the user if you're unsure.
Bundling independent lanes into one card. If the user asks for two independent outcomes, create two cards. Example: "fix blockers and check model variants" is not one fixer task; create a fixer/engineer card for the fixes and an explorer/researcher card for the variant check, then optionally gate review on both.
Over-linking because of wording. "Finally check X" may still be parallel with implementation if X is static config, docs, or source discovery. Link it after implementation only when the check depends on the implementation result.
Forgetting dependency links. If the task graph says research -> implement -> review, do not create all tasks as independent ready cards. Use parent links so implement/review cannot run before their inputs exist.
Reassignment vs. new task. If a reviewer blocks with "needs changes," create a NEW task linked from the reviewer's task โ don't re-run the same task with a stern look. The new task is assigned to the original implementer profile.
Argument order for links. kanban_link(parent_id=..., child_id=...) โ parent first. Mixing them up demotes the wrong task to todo.
Ignoring explicit user feedback to keep building infrastructure. When the user says a specific UX issue (legibility, theme switching, movement density) is "immediate priority," treat it as P0 and route it before deeper packaging/architecture work. Infrastructure polish feels productive, but shipping user-visible fixes is what matters. Create cards for the UX feedback first, then resume infrastructure lanes.
Treating status: complete as immutable when user feedback says otherwise. A state.md that says status: complete does not override a user's report that a completion criterion is actually broken. If the user says "theme switching is not working" and the Final Completion Condition requires "working UI theme switcher," the mission is not complete. Reactivate immediately: set status: active, append a reactivation cycle log, and fix the issue. Do not burn cycles on post-complete verification while the user is reporting active defects.
Don't pre-create the whole graph if the shape depends on intermediate findings. If T3's structure depends on what T1 and T2 find, let T3 exist as a "synthesize findings" task whose own first step is to read parent handoffs and plan the rest. Orchestrators can spawn orchestrators.
Tenant inheritance. If HERMES_TENANT is set in your env, pass tenant=os.environ.get("HERMES_TENANT") on every kanban_create call so child tasks stay in the same namespace.
Verifying cross-file references after directory reorganization. When subagents edit HTML/CSS/JS files and the directory structure shifts (e.g., moving files from root into web/dashboard/ and web/gather/), relative asset paths ( themes/default/theme.css, ./ops-data.json) often break. After subagents finish, the orchestrator must grep for href= and src= in moved files and fix relative paths before publishing. Subagents don't know the final publish layout โ the orchestrator does.
Destructive sync wipes needed files. Commands like rsync -av --delete will delete destination files that aren't in the source list. If you publish a directory tree piecemeal (e.g., copy web/dashboard/ first, then web/gather/ separately), --delete on the first rsync will erase the gather files before the second rsync runs. Either list all source paths in a single rsync invocation, or omit --delete and use cp -r / rsync -av without deletion when doing staged copies.
Recovering stuck workers
When a worker profile keeps crashing, hallucinating, or getting blocked by its own mistakes (usually: wrong model, missing skill, broken credential), the kanban dashboard flags the task with a โ badge and opens a Recovery section in the drawer. Three primary actions:
1. Reclaim (or hermes kanban reclaim <task_id>) โ abort the running worker immediately and reset the task to ready. The existing claim TTL is ~15 min; this is the fast path out.
2. Reassign (or hermes kanban reassign <task_id> <new-profile> --reclaim) โ switch the task to a different profile (one that exists on this setup) and let the dispatcher pick it up with a fresh worker.
3. Change profile model โ the dashboard prints a copy-paste hint for hermes -p <profile> model since profile config lives on disk; edit it in a terminal, then Reclaim to retry with the new model.
Hallucination warnings appear on tasks where a worker's kanban_complete(created_cards=[...]) claim included card ids that don't exist or weren't created by the worker's profile (the gate blocks the completion), or where the free-form summary references t_<hex> ids that don't resolve (advisory prose scan, non-blocking). Both produce audit events that persist even after recovery actions โ the trail stays for debugging.
The user has provided the following instruction alongside the skill invocation: [IMPORTANT: You are running as a scheduled cron job. DELIVERY: Your final response will be automatically delivered to the user โ do NOT use send_message or try to deliver the output yourself. Just produce your report/output as your final response and the system handles the rest. SILENT: If there is genuinely nothing new to report, respond with exactly "[SILENT]" (nothing else) to suppress delivery. Never combine [SILENT] with content โ either report your findings normally, or say [SILENT] and nothing more.]
You are the 15-minute Orchestrator for Son's Autonomous Agent Lab v1, reporting to Discord channel ID 1505805763824586952.
Durable state path: /Users/jooho-hermes/.hermes/autonomous-agent-lab/state.md
Working directory for experiment artifacts: /Users/jooho-hermes/.hermes/autonomous-agent-lab/
Preferred published web root: /Users/jooho-hermes/hermes-web/agent-pets/
Top-level directive from Son:
- The project has evolved from a personal dashboard into an INSTALLABLE PRODUCT that external Hermes users can deploy.
- The final target is a self-contained, configurable, publishable solution: "Hermes Pixel Pet Ops Office".
- Do NOT shrink the mission into a small static MVP and autonomously stop.
- The Gather.town-style 2D spatial office is a first-class feature, not a side page.
Latest UX feedback from Son (treat as immediate priority before deeper packaging work):
- Details are hard for a human to understand. Add human-first summaries, plain-language labels, and progressive disclosure: summary first, technical details second.
- Gather Town version has too many agents roaming around. Reduce default movement, add density/speed controls, cluster agents by room/task, and add focus/calm mode.
- Theme switching is not visibly working. Implement real UI theme switcher with persistence and clear visual theme changes.
Key product requirements (installable solution level):
1. Config-driven architecture: all paths, URLs, colors, names, room layouts via config.yaml. No hardcoded references to jooho-hermes.
2. Self-contained package: clear directory structure (src/, web/, config/, docs/, scripts/), install script, requirements.txt.
3. Pluggable data adapter: support multiple backends via plugin architecture.
4. Themeable frontend: CSS variables driven from config, swappable themes, plus a working UI theme switcher.
5. Multi-tenant ready: works for any Hermes instance.
6. Build/Deploy ready: Dockerfile or docker-compose, or clear static-server setup.
7. Documentation: README, architecture docs, configuration reference, contributor guide.
8. Human-comprehensible UX: plain-language summaries and progressive disclosure for technical detail.
9. Gather.town calm mode: adjustable movement density/speed and less chaotic defaults.
10. Versioned releases: CHANGELOG.md, semantic versioning, release packaging.
Mission model:
- Read state.md first before doing anything else.
- If state.md says
status: inactive or has no Current Mission, do not invent work. Return exactly: ๐ก Autonomous Agent Lab ๋๊ธฐ์ค โ Son์ด ํธ๋ฆฌ๊ฑฐ/๋ฏธ์
์ ์ฃผ๋ฉด 15๋ถ ์ฌ์ดํด์ ์์ํฉ๋๋ค.
- If state.md says
status: active, run one bounded 15-minute cycle toward the full installable solution.
- If state.md says
status: complete, verify that the Final Completion Condition in state.md is truly met. If it is not fully met, reactivate or report that state needs correction.
Cycle procedure when active:
1. Read state.md first. Extract current mission, constraints, previous cycle log, and Final Completion Condition.
2. Decide the next smallest useful step toward installable solution quality. Focus on: architecture, configurability, documentation, and clean separation of concerns.
3. Use delegate_task for independent subagent lanes when helpful.
4. Prefer concrete progress: refactor to config-driven, add install scripts, create docs, add Docker support, theme system, plugin architecture.
5. Update state.md with a new cycle log entry before final reporting.
6. Completion rule: only set status: complete when every item under state.md Final Completion Condition is satisfied. A non-installable MVP is not complete.
7. Stop/block only if Son explicitly stops/redirects, a safety boundary is reached, or a hard blocker needs Son's decision.
Link requirement (never forget):
- Every cycle report MUST include at least one direct viewable link to the published dashboard/artifact.
- The canonical URL:
http://hermes-mac-mini.tail46b3c6.ts.net:8099/agent-pets/
- Include gather town URL too:
http://hermes-mac-mini.tail46b3c6.ts.net:8099/agent-pets/gather/
Final Discord message format:
[Autonomous Agent Lab v1 / Cycle N]
๋ชฉํ:
์ํ:
๊ฒฐ๊ณผ:
๊ฒ์ฆ:
๋ค์:
์ํ:
Safety/quality rules:
- Do not handle secrets, passwords, API keys, payment, permission dialogs, or destructive commands.
- Do not claim completion without updating state.md.
- Do not rely on Discord history as durable state.
- Do not spam raw logs; summarize lane outputs and verification.
- Keep working in /Users/jooho-hermes/.hermes/autonomous-agent-lab/ and publish only to /Users/jooho-hermes/hermes-web/agent-pets/ unless the state file says otherwise.
Design/UX priorities:
- Mobile responsiveness is first-class.
- Character animation/movement is desired.
- Every cycle report must include published links.
- This is now a product engineering mission. Architecture, configurability, and documentation matter as much as visuals.
Response
[Autonomous Agent Lab v1 / Cycle 56]
๋ชฉํ: Son์ UX ํผ๋๋ฐฑ 3๊ฐ์ง(ํ
๋ง ๋ฏธ์ ์ฉ, Gather ํผ์ก, ๊ธฐ์ ์ค์ฌ UI) ์์ ์ฌํญ์ด ์ค์ ๋ก ํผ๋ธ๋ฆฌ์ฑ๋๊ณ ๊ตฌ์กฐ์ ์ผ๋ก ์ ์์ธ์ง ์ข
๋จ ๊ฒ์ฆ. state.md cycle_count ๋๋ฝ๋ ํจ๊ป ์์ .
์ํ:
โข scripts/test.sh ์คํ โ 106/106 passed
โข scripts/validate_setup.sh ์คํ โ 21/21 passed
โข python3 -m src.adapter.generate_ops_data โ 32 agents, 15 cron jobs, 20 sessions, 16 events, schema 1.4
โข source โ published web root diff ์ผ์น ํ์ธ (HTML/JS/CSS/sw.js ์ ๋ถ ๋์ผ)
โข 3๊ฐ ํ
๋ง ์์ ์๋ ์ถ์ถ ๋น๊ต: default(#18122b), dark-ops(#050510), cozy-pastel(#f5f0e8) โ ๋ฐฐ๊ฒฝ์์ด ์์ ํ ์์ดํจ
โข Gather Town JS ์์ ๊ฒ์ฆ: cap=8, sparse=0.04, slow=0.25 โ ๊ธฐ๋ณธ๊ฐ์ด ๊ฐ์ฅ ์ฐจ๋ถํ ์ค์
โข Dashboard inspector JS ๊ฒ์ฆ: ๊ธฐ๋ณธ ์ด๊ธฐ ์ โ์ง๊ธ ํ๋ ์ผ / ์ ์ค์ํ๊ฐ / ์งํ ๋ง๋โ๋ง ๋
ธ์ถ, ๊ธฐ์ ์์ธ๋ โ๊ธฐ์ ์์ธ ๋ณด๊ธฐโ ํ ๊ธ ๋ค๋ก ์ด๋
โข health.json status=healthy, refresh.err.log empty, LaunchAgent ์ ์ ๋์ ์ค
โข state.md cycle_count 54 โ 56 ์ ์ , Cycle 56 ๋ก๊ทธ ๊ธฐ๋ก
๊ฒฐ๊ณผ:
โข ํผ๋ธ๋ฆฌ์ฑ๋ ๋ชจ๋ ํ์ผ์ source์ 100% ์ผ์นํ๋ฉฐ ์ต์ ์ํ
โข Son์ด ๋ณด๊ณ ํ ๋ฌธ์ ๋ค์ ๊ธฐ์ ์ ์์ ์ ๋ชจ๋ live ๋ฐ ๊ฒ์ฆ ์๋ฃ
โข ๋จ์ ์ ์ผํ ๋ณ์๋ ๋ธ๋ผ์ฐ์ ์บ์/Service Worker ์บ์๋ก, ๋์๋ณด๋์ Gather Town ํ๋จ์ โ์บ์ ์ญ์ ํ ์๋ก๊ณ ์นจโ ๋ฒํผ์ด ์ถ๊ฐ๋์ด ์์
๊ฒ์ฆ:
ํตํฉํ
์คํธ 106 passed | ๊ฒ์ฆ์คํฌ๋ฆฝํธ 21 passed | Adapter 32 agents | ops-data.json schema 1.4 | health.json healthy | refresh.err.log empty
๋ค์:
Son์ ๋์๋ณด๋๋ Gather Town ํ๋จ์ โ์บ์ ์ญ์ ํ ์๋ก๊ณ ์นจโ ๋ฒํผ์ ํด๋ฆญํ์ฌ ๋จ์ ๋ธ๋ผ์ฐ์ ์บ์๋ฅผ ์์ ํ ์ ๊ฑฐํ ๋ค, ํ
๋ง ์ ํ(3ํ
๋ง)๊ณผ Gather ์ง์ ๋๋ฅผ ํ์ธํด ์ฃผ์ธ์. ์ถ๊ฐ ์ด์ ์์ผ๋ฉด status: complete๋ก ์ ํ ๊ฐ๋ฅํฉ๋๋ค.
์ํ: active (Son ํ์ธ ๋๊ธฐ ์ค)
๐ ๋์๋ณด๋: http://hermes-mac-mini.tail46b3c6.ts.net:8099/agent-pets/
๐ Gather Town: http://hermes-mac-mini.tail46b3c6.ts.net:8099/agent-pets/gather/
|
| 2026-05-19 14-26-05 |
80,231 chars |
2026-05-19_14-26-05.md |
Cron Job: autonomous-agent-lab-v1-orchestrator
Job ID: 35127ff89556
Run Time: 2026-05-19 14:26:05
Schedule: every 15m
Prompt
[IMPORTANT: The user has invoked the "hermes-agent" skill, indicating they want you to follow its instructions. The full skill content is loaded below.]
---
name: hermes-agent
description: "Configure, extend, or contribute to Hermes Agent."
version: 2.1.0
author: Hermes Agent + Teknium
license: MIT
platforms: [linux, macos, windows]
metadata:
hermes:
tags: [hermes, setup, configuration, multi-agent, spawning, cli, gateway, development]
homepage: https://github.com/NousResearch/hermes-agent
related_skills: [claude-code, codex, opencode]
---
Hermes Agent
Hermes Agent is an open-source AI agent framework by Nous Research that runs in your terminal, messaging platforms, and IDEs. It belongs to the same category as Claude Code (Anthropic), Codex (OpenAI), and OpenClaw โ autonomous coding and task-execution agents that use tool calling to interact with your system. Hermes works with any LLM provider (OpenRouter, Anthropic, OpenAI, DeepSeek, local models, and 15+ others) and runs on Linux, macOS, and WSL.
What makes Hermes different:
- Self-improving through skills โ Hermes learns from experience by saving reusable procedures as skills. When it solves a complex problem, discovers a workflow, or gets corrected, it can persist that knowledge as a skill document that loads into future sessions. Skills accumulate over time, making the agent better at your specific tasks and environment.
- Persistent memory across sessions โ remembers who you are, your preferences, environment details, and lessons learned. Pluggable memory backends (built-in, Honcho, Mem0, and more) let you choose how memory works.
- Multi-platform gateway โ the same agent runs on Telegram, Discord, Slack, WhatsApp, Signal, Matrix, Email, and 10+ other platforms with full tool access, not just chat.
- Provider-agnostic โ swap models and providers mid-workflow without changing anything else. Credential pools rotate across multiple API keys automatically.
- Profiles โ run multiple independent Hermes instances with isolated configs, sessions, skills, and memory.
- Extensible โ plugins, MCP servers, custom tools, webhook triggers, cron scheduling, and the full Python ecosystem.
People use Hermes for software development, research, system administration, data analysis, content creation, home automation, and anything else that benefits from an AI agent with persistent context and full system access.
This skill helps you work with Hermes Agent effectively โ setting it up, configuring features, spawning additional agent instances, troubleshooting issues, finding the right commands and settings, and understanding how the system works when you need to extend or contribute to it.
Docs: https://hermes-agent.nousresearch.com/docs/
Quick Start
Install
curl -fsSL https://raw.githubusercontent.com/NousResearch/hermes-agent/main/scripts/install.sh | bash
Interactive chat (default)
hermes
Single query
hermes chat -q "What is the capital of France?"
Setup wizard
hermes setup
Change model/provider
hermes model
Check health
hermes doctor
---
CLI Reference
Global Flags
hermes [flags] [command]
--version, -V Show version
--resume, -r SESSION Resume session by ID or title
--continue, -c [NAME] Resume by name, or most recent session
--worktree, -w Isolated git worktree mode (parallel agents)
--skills, -s SKILL Preload skills (comma-separate or repeat)
--profile, -p NAME Use a named profile
--yolo Skip dangerous command approval
--pass-session-id Include session ID in system prompt
No subcommand defaults to chat.
Chat
hermes chat [flags]
-q, --query TEXT Single query, non-interactive
-m, --model MODEL Model (e.g. anthropic/claude-sonnet-4)
-t, --toolsets LIST Comma-separated toolsets
--provider PROVIDER Force provider (openrouter, anthropic, nous, etc.)
-v, --verbose Verbose output
-Q, --quiet Suppress banner, spinner, tool previews
--checkpoints Enable filesystem checkpoints (/rollback)
--source TAG Session source tag (default: cli)
Configuration
hermes setup [section] Interactive wizard (model|terminal|gateway|tools|agent)
hermes model Interactive model/provider picker
hermes config View current config
hermes config edit Open config.yaml in $EDITOR
hermes config set KEY VAL Set a config value
hermes config path Print config.yaml path
hermes config env-path Print .env path
hermes config check Check for missing/outdated config
hermes config migrate Update config with new options
hermes doctor [--fix] Check dependencies and config
Credential Pools
hermes auth add Interactive credential wizard (oauth, api-key)
hermes auth list [PROVIDER] List pooled credentials
hermes auth remove P INDEX Remove by provider + index
hermes auth reset PROVIDER Clear exhaustion status
hermes logout Clear stored auth
Tools & Skills
hermes tools Interactive tool enable/disable (curses UI)
hermes tools list Show all tools and status
hermes tools enable NAME Enable a toolset
hermes tools disable NAME Disable a toolset
hermes skills list List installed skills
hermes skills search QUERY Search the skills hub
hermes skills install ID Install a skill (ID can be a hub identifier OR a direct https://โฆ/SKILL.md URL; pass --name to override when frontmatter has no name)
hermes skills inspect ID Preview without installing
hermes skills config Enable/disable skills per platform
hermes skills check Check for updates
hermes skills update Update outdated skills
hermes skills uninstall N Remove a hub skill
hermes skills publish PATH Publish to registry
hermes skills browse Browse all available skills
hermes skills tap add REPO Add a GitHub repo as skill source
MCP Servers
hermes mcp serve Run Hermes as an MCP server
hermes mcp add NAME Add an MCP server (--url or --command)
hermes mcp remove NAME Remove an MCP server
hermes mcp list List configured servers
hermes mcp test NAME Test connection
hermes mcp configure NAME Toggle tool selection
Gateway (Messaging Platforms)
hermes gateway run Start gateway foreground
hermes gateway install Install as background service
hermes gateway start/stop Control the service
hermes gateway restart Restart the service
hermes gateway status Check status
hermes gateway setup Configure platforms
Supported platforms: Telegram, Discord, Slack, WhatsApp, Signal, Email, SMS, Matrix, Mattermost, Home Assistant, DingTalk, Feishu, WeCom, BlueBubbles (iMessage), Weixin (WeChat), API Server, Webhooks. Open WebUI connects via the API Server adapter.
Platform docs: https://hermes-agent.nousresearch.com/docs/user-guide/messaging/
Discord-specific walkthrough (token, intents, service install, access control): see references/discord-gateway-setup.md in this skill.
- Per-channel personas and skill bindings: see
references/gateway-channel-personas.md (works on Discord, Slack, Telegram, Mattermost, Matrix).
- For long-running Discord-first operations, purpose-specific channel routing, periodic summaries, weekly Dreaming/audit reports, and log-safety patterns: see
references/discord-operating-planes.md.
- For broad Hermes/LifeOS/SQAF ecosystem audits (cron inventory, live services, dashboards, provider/model warnings, and control-plane gaps), see
references/ecosystem-audit.md.
Sessions
hermes sessions list List recent sessions
hermes sessions browse Interactive picker
hermes sessions export OUT Export to JSONL
hermes sessions rename ID T Rename a session
hermes sessions delete ID Delete a session
hermes sessions prune Clean up old sessions (--older-than N days)
hermes sessions stats Session store statistics
For browser-based viewing of existing Hermes CLI/Discord/cron session transcripts, prefer a lightweight static export from ~/.hermes/state.db into a private web root instead of assuming Open WebUI can browse Hermes' native session store. See references/hermes-session-static-web-viewer.md for the SQLite schema, static HTML export workflow, redaction/truncation cautions, and the user's Mac mini deployment (/hermes-sessions/ under the Tailscale-only ~/hermes-web site).
For cron job execution history, the same static-export pattern applies to ~/.hermes/cron/jobs.json and ~/.hermes/cron/output/{job_id}/*.md. See references/cron-history-web-viewer.md for the cron data model, schedule-dict pitfall, and the user's deployed /cron-history/ dashboard.
Cron Jobs
hermes cron list List jobs (--all for disabled)
hermes cron create SCHED Create: '30m', 'every 2h', '0 9 *'
hermes cron edit ID Edit schedule, prompt, delivery
hermes cron pause/resume ID Control job state
hermes cron run ID Trigger on next tick
hermes cron remove ID Delete a job
hermes cron status Scheduler status
For bounded autonomous lab/orchestrator cron jobs that use file-based state, subagent lanes, artifact publishing, and status transitions (active โ complete/blocked/inactive), see references/autonomous-agent-lab-cron-cycle.md. A reusable verification script template lives at scripts/verify-completion-template.py.
For a worked example of evolving an autonomous lab into a config-driven, themeable, Docker-ready installable product, see references/autonomous-lab-product-architecture.md. For CI, integration testing, pluggable adapter architecture, bounded cycle orchestration, and post-productization patterns, see references/product-maturity-patterns.md.
For the final completion verification checklist โ the explicit audit pattern to run before marking status: complete on an installable-solution mission, see references/autonomous-lab-completion-verification.md.
For the reactivation protocol when a completed lab receives new P0 feedback or the user contradicts a completion claim, see references/autonomous-lab-reactivation-protocol.md.
For adding historical trend tracking (SQLite-backed agent status transitions + vanilla JS SVG sparklines) to an autonomous lab dashboard, see references/history-tracking-sparkline-pattern.md.
For reusable dashboard UX patterns (onboarding tours, data freshness badges, keyboard shortcuts, progressive disclosure inspectors, cross-linking between views), see references/dashboard-ux-patterns.md.
For the aggressive human-first inspector refinement โ when users report that details are hard to understand and the fix is to strip technical labels from the default view โ see references/progressive-disclosure-human-first.md.
For programmatic verification of CSS custom-property theme systems โ catching scoping bugs, confirming theme distinctness, and validating JS switching logic โ see references/theme-system-verification.md.
For Son's Discord-first autonomous experiments where a channel hosts a repeated multi-agent loop, use the Autonomous Discord Agent Lab pattern: create file-based durable state, a paused cron orchestrator delivered to discord:<channel_id>, then activate it from a user mission trigger. See references/autonomous-discord-agent-lab.md.
Webhooks
hermes webhook subscribe N Create route at /webhooks/<name>
hermes webhook list List subscriptions
hermes webhook remove NAME Remove a subscription
hermes webhook test NAME Send a test POST
Profiles
hermes profile list List all profiles
hermes profile create NAME Create (--clone, --clone-all, --clone-from)
hermes profile use NAME Set sticky default
hermes profile delete NAME Delete a profile
hermes profile show NAME Show details
hermes profile alias NAME Manage wrapper scripts
hermes profile rename A B Rename a profile
hermes profile export NAME Export to tar.gz
hermes profile import FILE Import from archive
Credential Pools
hermes auth add Interactive credential wizard
hermes auth list [PROVIDER] List pooled credentials
hermes auth remove P INDEX Remove by provider + index
hermes auth reset PROVIDER Clear exhaustion status
Other
hermes insights [--days N] Usage analytics
hermes update Update to latest version
hermes pairing list/approve/revoke DM authorization
hermes plugins list/install/remove Plugin management
hermes honcho setup/status Honcho memory integration (requires honcho plugin)
hermes memory setup/status/off Memory provider config
hermes completion bash|zsh Shell completions
hermes acp ACP server (IDE integration)
hermes claw migrate Migrate from OpenClaw
hermes uninstall Uninstall Hermes
---
Slash Commands (In-Session)
Type these during an interactive chat session. New commands land fairly
often; if something below looks stale, run /help in-session for the
authoritative list or see the [live slash commands reference](https://hermes-agent.nousresearch.com/docs/reference/slash-commands).
The registry of record is hermes_cli/commands.py โ every consumer
(autocomplete, Telegram menu, Slack mapping, /help) derives from it.
Session Control
/new (/reset) Fresh session
/clear Clear screen + new session (CLI)
/retry Resend last message
/undo Remove last exchange
/title [name] Name the session
/compress Manually compress context
/stop Kill background processes
/rollback [N] Restore filesystem checkpoint
/snapshot [sub] Create or restore state snapshots of Hermes config/state (CLI)
/background <prompt> Run prompt in background
/queue <prompt> Queue for next turn
/steer <prompt> Inject a message after the next tool call without interrupting
/agents (/tasks) Show active agents and running tasks
/resume [name] Resume a named session
/goal [text|sub] Set a standing goal Hermes works on across turns until achieved
(subcommands: status, pause, resume, clear)
/redraw Force a full UI repaint (CLI)
Configuration
/config Show config (CLI)
/model [name] Show or change model
/personality [name] Set personality
/reasoning [level] Set reasoning (none|minimal|low|medium|high|xhigh|show|hide)
/verbose Cycle: off โ new โ all โ verbose
/voice [on|off|tts] Voice mode
/yolo Toggle approval bypass
/busy [sub] Control what Enter does while Hermes is working (CLI)
(subcommands: queue, steer, interrupt, status)
/indicator [style] Pick the TUI busy-indicator style (CLI)
(styles: kaomoji, emoji, unicode, ascii)
/footer [on|off] Toggle gateway runtime-metadata footer on final replies
/skin [name] Change theme (CLI)
/statusbar Toggle status bar (CLI)
Tools & Skills
/tools Manage tools (CLI)
/toolsets List toolsets (CLI)
/skills Search/install skills (CLI)
/skill <name> Load a skill into session
/reload-skills Re-scan ~/.hermes/skills/ for added/removed skills
/reload Reload .env variables into the running session (CLI)
/reload-mcp Reload MCP servers
/cron Manage cron jobs (CLI)
/curator [sub] Background skill maintenance (status, run, pin, archive, โฆ)
/kanban [sub] Multi-profile collaboration board (tasks, links, comments)
/plugins List plugins (CLI)
Gateway
/approve Approve a pending command (gateway)
/deny Deny a pending command (gateway)
/restart Restart gateway (gateway)
/sethome Set current chat as home channel (gateway)
/update Update Hermes to latest (gateway)
/topic [sub] Enable or inspect Telegram DM topic sessions (gateway)
/platforms (/gateway) Show platform connection status (gateway)
Utility
/branch (/fork) Branch the current session
/fast Toggle priority/fast processing
/browser Open CDP browser connection
/history Show conversation history (CLI)
/save Save conversation to file (CLI)
/copy [N] Copy the last assistant response to clipboard (CLI)
/paste Attach clipboard image (CLI)
/image Attach local image file (CLI)
Info
/help Show commands
/commands [page] Browse all commands (gateway)
/usage Token usage
/insights [days] Usage analytics
/gquota Show Google Gemini Code Assist quota usage (CLI)
/status Session info (gateway)
/profile Active profile info
/debug Upload debug report (system info + logs) and get shareable links
Exit
/quit (/exit, /q) Exit CLI
---
Key Paths & Config
~/.hermes/config.yaml Main configuration
~/.hermes/.env API keys and secrets
$HERMES_HOME/skills/ Installed skills
~/.hermes/sessions/ Session transcripts
~/.hermes/logs/ Gateway and error logs
~/.hermes/auth.json OAuth tokens and credential pools
~/.hermes/hermes-agent/ Source code (if git-installed)
Profiles use ~/.hermes/profiles/<name>/ with the same layout.
Config Sections
Edit with hermes config edit or hermes config set section.key value.
| Section | Key options |
|---------|-------------|
| model | default, provider, base_url, api_key, context_length |
| agent | max_turns (90), tool_use_enforcement |
| terminal | backend (local/docker/ssh/modal), cwd, timeout (180) |
| compression | enabled, threshold (0.50), target_ratio (0.20) |
| display | skin, tool_progress, show_reasoning, show_cost |
| stt | enabled, provider (local/groq/openai/mistral) |
| tts | provider (edge/elevenlabs/openai/minimax/mistral/neutts) |
| memory | memory_enabled, user_profile_enabled, provider |
| security | tirith_enabled, website_blocklist |
| delegation | model, provider, base_url, api_key, max_iterations (50), reasoning_effort |
| checkpoints | enabled, max_snapshots (50) |
| fallback_model | provider, model, base_url, key_env |
Fallback Providers
Hermes can automatically fail over to a backup provider:model when the primary is unavailable. This is turn-scoped โ each new user message starts with the primary restored; fallback only activates mid-turn when the primary fails.
Configuration ( ~/.hermes/config.yaml):
fallback_model:
provider: opencode-go
model: kimi-k2.6
Or use the interactive manager:
hermes fallback add # interactive picker
hermes fallback list # show fallback chain
hermes fallback remove # remove by index
Legacy note: fallback_model (singular) is the legacy single-fallback key. fallback_providers (list) supports multiple ordered fallbacks. When both exist, fallback_providers takes priority.
Trigger conditions (after exhausting retries where applicable):
- Rate limits (HTTP 429)
- Server errors (HTTP 500, 502, 503)
- Auth failures (HTTP 401, 403) โ immediately
- Not found (HTTP 404) โ immediately
- Invalid / empty responses repeatedly
Supported providers include all standard providers (OpenRouter, Anthropic, OpenCode Go/ Zen, Kimi, etc.) plus custom endpoints with base_url + key_env. Full provider docs: https://hermes-agent.nousresearch.com/docs/integrations/providers
Limitations:
- Subagent delegation does not inherit fallback config
- Cron jobs do not use fallback (use per-job provider/model overrides)
- Auxiliary tasks (vision, compression, etc.) use their own
auxiliary.* provider chain
For a deep-dive with worked examples and model lists, see references/fallback-providers.md.
Full config reference: https://hermes-agent.nousresearch.com/docs/user-guide/configuration
Providers
20+ providers supported. Set via hermes model or hermes setup.
| Provider | Auth | Key env var |
|----------|------|-------------|
| OpenRouter | API key | OPENROUTER_API_KEY |
| Anthropic | API key | ANTHROPIC_API_KEY |
| Nous Portal | OAuth | hermes auth |
| OpenAI Codex | OAuth | hermes auth |
| GitHub Copilot | Token | COPILOT_GITHUB_TOKEN |
| Google Gemini | API key | GOOGLE_API_KEY or GEMINI_API_KEY |
| DeepSeek | API key | DEEPSEEK_API_KEY |
| xAI / Grok | API key | XAI_API_KEY |
| Hugging Face | Token | HF_TOKEN |
| Z.AI / GLM | API key | GLM_API_KEY |
| MiniMax | API key | MINIMAX_API_KEY |
| MiniMax CN | API key | MINIMAX_CN_API_KEY |
| Kimi / Moonshot | API key | KIMI_API_KEY |
| Alibaba / DashScope | API key | DASHSCOPE_API_KEY |
| Xiaomi MiMo | API key | XIAOMI_API_KEY |
| Kilo Code | API key | KILOCODE_API_KEY |
| AI Gateway (Vercel) | API key | AI_GATEWAY_API_KEY |
| OpenCode Zen | API key | OPENCODE_ZEN_API_KEY |
| OpenCode Go | API key | OPENCODE_GO_API_KEY |
| Qwen OAuth | OAuth | hermes auth add qwen-oauth |
| Custom endpoint | Config | model.base_url + model.api_key in config.yaml |
| GitHub Copilot ACP | External | COPILOT_CLI_PATH or Copilot CLI |
Full provider docs: https://hermes-agent.nousresearch.com/docs/integrations/providers
Toolsets
Enable/disable via hermes tools (interactive) or hermes tools enable/disable NAME.
| Toolset | What it provides |
|---------|-----------------|
| web | Web search and content extraction |
| search | Web search only (subset of web) |
| browser | Browser automation (Browserbase, Camofox, or local Chromium) |
| terminal | Shell commands and process management |
| file | File read/write/search/patch |
| code_execution | Sandboxed Python execution |
| vision | Image analysis |
| image_gen | AI image generation |
| video | Video analysis and generation |
| tts | Text-to-speech |
| skills | Skill browsing and management |
| memory | Persistent cross-session memory |
| session_search | Search past conversations |
| delegation | Subagent task delegation |
| cronjob | Scheduled task management |
| clarify | Ask user clarifying questions |
| messaging | Cross-platform message sending |
| todo | In-session task planning and tracking |
| kanban | Multi-agent work-queue tools (gated to workers) |
| debugging | Extra introspection/debug tools (off by default) |
| safe | Minimal, low-risk toolset for locked-down sessions |
| spotify | Spotify playback and playlist control |
| homeassistant | Smart home control (off by default) |
| discord | Discord integration tools |
| discord_admin | Discord admin/moderation tools |
| feishu_doc | Feishu (Lark) document tools |
| feishu_drive | Feishu (Lark) drive tools |
| yuanbao | Yuanbao integration tools |
| rl | Reinforcement learning tools (off by default) |
| moa | Mixture of Agents (off by default) |
Full enumeration lives in toolsets.py as the TOOLSETS dict; _HERMES_CORE_TOOLS is the default bundle most platforms inherit from.
Tool changes take effect on /reset (new session). They do NOT apply mid-conversation to preserve prompt caching.
---
Security & Privacy Toggles
Common "why is Hermes doing X to my output / tool calls / commands?" toggles โ and the exact commands to change them. Most of these need a fresh session (/reset in chat, or start a new hermes invocation) because they're read once at startup.
Secret redaction in tool output
Secret redaction is off by default โ tool output (terminal stdout, read_file, web content, subagent summaries, etc.) passes through unmodified. If the user wants Hermes to auto-mask strings that look like API keys, tokens, and secrets before they enter the conversation context and logs:
hermes config set security.redact_secrets true # enable globally
Restart required. security.redact_secrets is snapshotted at import time โ toggling it mid-session (e.g. via export HERMES_REDACT_SECRETS=true from a tool call) will NOT take effect for the running process. Tell the user to run hermes config set security.redact_secrets true in a terminal, then start a new session. This is deliberate โ it prevents an LLM from flipping the toggle on itself mid-task.
Disable again with:
hermes config set security.redact_secrets false
PII redaction in gateway messages
Separate from secret redaction. When enabled, the gateway hashes user IDs and strips phone numbers from the session context before it reaches the model:
hermes config set privacy.redact_pii true # enable
hermes config set privacy.redact_pii false # disable (default)
Command approval prompts
By default (approvals.mode: manual), Hermes prompts the user before running shell commands flagged as destructive (rm -rf, git reset --hard, etc.). The modes are:
manual โ always prompt (default)
smart โ use an auxiliary LLM to auto-approve low-risk commands, prompt on high-risk
off โ skip all approval prompts (equivalent to --yolo)
hermes config set approvals.mode smart # recommended middle ground
hermes config set approvals.mode off # bypass everything (not recommended)
Per-invocation bypass without changing config:
hermes --yolo โฆ
export HERMES_YOLO_MODE=1
Note: YOLO / approvals.mode: off does NOT turn off secret redaction. They are independent.
Shell hooks allowlist
Some shell-hook integrations require explicit allowlisting before they fire. Managed via ~/.hermes/shell-hooks-allowlist.json โ prompted interactively the first time a hook wants to run.
Disabling the web/browser/image-gen tools
To keep the model away from network or media tools entirely, open hermes tools and toggle per-platform. Takes effect on next session (/reset). See the Tools & Skills section above.
---
Voice & Transcription
STT (Voice โ Text)
Voice messages from messaging platforms are auto-transcribed.
Provider priority (auto-detected):
1. Local faster-whisper โ free, no API key: pip install faster-whisper
2. Groq Whisper โ free tier: set GROQ_API_KEY
3. OpenAI Whisper โ paid: set VOICE_TOOLS_OPENAI_KEY
4. Mistral Voxtral โ set MISTRAL_API_KEY
Config:
stt:
enabled: true
provider: local # local, groq, openai, mistral
local:
model: base # tiny, base, small, medium, large-v3
TTS (Text โ Voice)
| Provider | Env var | Free? |
|----------|---------|-------|
| Edge TTS | None | Yes (default) |
| ElevenLabs | ELEVENLABS_API_KEY | Free tier |
| OpenAI | VOICE_TOOLS_OPENAI_KEY | Paid |
| MiniMax | MINIMAX_API_KEY | Paid |
| Mistral (Voxtral) | MISTRAL_API_KEY | Paid |
| NeuTTS (local) | None (pip install neutts[all] + espeak-ng) | Free |
Voice commands: /voice on (voice-to-voice), /voice tts (always voice), /voice off.
---
Spawning Additional Hermes Instances
Run additional Hermes processes as fully independent subprocesses โ separate sessions, tools, and environments.
When to Use This vs delegate_task
| | delegate_task | Spawning hermes process |
|-|-----------------|--------------------------|
| Isolation | Separate conversation, shared process | Fully independent process |
| Duration | Minutes (bounded by parent loop) | Hours/days |
| Tool access | Subset of parent's tools | Full tool access |
| Interactive | No | Yes (PTY mode) |
| Use case | Quick parallel subtasks | Long autonomous missions |
One-Shot Mode
terminal(command="hermes chat -q 'Research GRPO papers and write summary to ~/research/grpo.md'", timeout=300)
Background for long tasks:
terminal(command="hermes chat -q 'Set up CI/CD for ~/myapp'", background=true)
Interactive PTY Mode (via tmux)
Hermes uses prompt_toolkit, which requires a real terminal. Use tmux for interactive spawning:
Start
terminal(command="tmux new-session -d -s agent1 -x 120 -y 40 'hermes'", timeout=10)
Wait for startup, then send a message
terminal(command="sleep 8 && tmux send-keys -t agent1 'Build a FastAPI auth service' Enter", timeout=15)
Read output
terminal(command="sleep 20 && tmux capture-pane -t agent1 -p", timeout=5)
Send follow-up
terminal(command="tmux send-keys -t agent1 'Add rate limiting middleware' Enter", timeout=5)
Exit
terminal(command="tmux send-keys -t agent1 '/exit' Enter && sleep 2 && tmux kill-session -t agent1", timeout=10)
Multi-Agent Coordination
Agent A: backend
terminal(command="tmux new-session -d -s backend -x 120 -y 40 'hermes -w'", timeout=10)
terminal(command="sleep 8 && tmux send-keys -t backend 'Build REST API for user management' Enter", timeout=15)
Agent B: frontend
terminal(command="tmux new-session -d -s frontend -x 120 -y 40 'hermes -w'", timeout=10)
terminal(command="sleep 8 && tmux send-keys -t frontend 'Build React dashboard for user management' Enter", timeout=15)
Check progress, relay context between them
terminal(command="tmux capture-pane -t backend -p | tail -30", timeout=5)
terminal(command="tmux send-keys -t frontend 'Here is the API schema from the backend agent: ...' Enter", timeout=5)
Session Resume
Resume most recent session
terminal(command="tmux new-session -d -s resumed 'hermes --continue'", timeout=10)
Resume specific session
terminal(command="tmux new-session -d -s resumed 'hermes --resume 20260225_143052_a1b2c3'", timeout=10)
Tips
- Prefer
delegate_task for quick subtasks โ less overhead than spawning a full process
- Use
-w (worktree mode) when spawning agents that edit code โ prevents git conflicts
- Set timeouts for one-shot mode โ complex tasks can take 5-10 minutes
- Use
hermes chat -q for fire-and-forget โ no PTY needed
- Use tmux for interactive sessions โ raw PTY mode has
\r vs \n issues with prompt_toolkit
- For scheduled tasks, use the
cronjob tool instead of spawning โ handles delivery and retry
---
Durable & Background Systems
Four systems run alongside the main conversation loop. Quick reference
here; full developer notes live in AGENTS.md, user-facing docs under
website/docs/user-guide/features/.
Delegation (delegate_task)
Synchronous subagent spawn โ the parent waits for the child's summary
before continuing its own loop. Isolated context + terminal session.
- Single:
delegate_task(goal, context, toolsets).
- Batch:
delegate_task(tasks=[{goal, ...}, ...]) runs children in
parallel, capped by delegation.max_concurrent_children (default 3).
- Roles:
leaf (default; cannot re-delegate) vs orchestrator
(can spawn its own workers, bounded by delegation.max_spawn_depth).
- Not durable. If the parent is interrupted, the child is
cancelled. For work that must outlive the turn, use cronjob or
terminal(background=True, notify_on_complete=True).
Config: delegation.* in config.yaml.
Tuning max_concurrent_children
Default is 3. Rule of thumb for raising it:
- Light tasks (web search, file grep): up to
6-8
- Medium tasks (code execution, browser):
4-5
- Heavy tasks (builds, large data):
2-3
- Actual bottleneck is usually the API rate limit, not local CPU/RAM. On a 10-core M4 with 16GB RAM, CPU is rarely the constraint.
- Formula: start at
5, raise only if profiling shows idle time between API responses.
Cron (scheduled jobs)
Durable scheduler โ cron/jobs.py + cron/scheduler.py. Drive it via
the cronjob tool, the hermes cron CLI (list, add, edit,
pause, resume, run, remove), or the /cron slash command.
- Schedules: duration (
"30m", "2h"), "every" phrase
( "every monday 9am"), 5-field cron ( "0 9 *"), or ISO timestamp.
- Per-job knobs:
skills, model/provider override, script
(pre-run data collection; no_agent=True makes the script the whole
job), context_from (chain job A's output into job B), workdir
(run in a specific dir with its AGENTS.md / CLAUDE.md loaded),
multi-platform delivery.
- Invariants: 3-minute hard interrupt per run,
.tick.lock file
prevents duplicate ticks across processes, cron sessions pass
skip_memory=True by default, and cron deliveries are framed with a
header/footer instead of being mirrored into the target gateway
session (keeps role alternation intact).
User docs: https://hermes-agent.nousresearch.com/docs/user-guide/features/cron
Curator (skill lifecycle)
Background maintenance for agent-created skills. Tracks usage, marks
idle skills stale, archives stale ones, keeps a pre-run tar.gz backup
so nothing is lost.
- CLI:
hermes curator <verb> โ status, run, pause, resume,
pin, unpin, archive, restore, prune, backup, rollback.
- Slash:
/curator <subcommand> mirrors the CLI.
- Scope: only touches skills with
created_by: "agent" provenance.
Bundled + hub-installed skills are off-limits. Never deletes โ
max destructive action is archive. Pinned skills are exempt from
every auto-transition and every LLM review pass.
- Telemetry: sidecar at
~/.hermes/skills/.usage.json holds
per-skill use_count, view_count, patch_count,
last_activity_at, state, pinned.
Config: curator.* (enabled, interval_hours, min_idle_hours,
stale_after_days, archive_after_days, backup.*).
User docs: https://hermes-agent.nousresearch.com/docs/user-guide/features/curator
Dreaming (periodic memory/skill consolidation)
For Anthropic-style "dreaming" workflows, combine cron + session_search + memory + skills + curator into a scheduled review loop. Start with a weekly, proposal-only report that audits recent sessions, repeated user corrections, memory conflicts, skill patch candidates, and cron/automation improvements. Do not automatically delete/replace memory or patch/archive skills unless the user explicitly approves the proposed changes. See references/weekly-dreaming-routine.md for the recommended prompt, report format, safety policy, and cron creation pattern.
Kanban (multi-agent work queue)
Durable SQLite board for multi-profile / multi-worker collaboration.
Users drive it via hermes kanban <verb>; dispatcher-spawned workers
see a focused kanban_* toolset gated by HERMES_KANBAN_TASK so the
schema footprint is zero outside worker processes.
- CLI verbs (common):
init, create, list (alias ls),
show, assign, link, unlink, comment, complete, block,
unblock, archive, tail. Less common: watch, stats, runs,
log, dispatch, daemon, gc.
- Worker toolset:
kanban_show, kanban_complete, kanban_block,
kanban_heartbeat, kanban_comment, kanban_create, kanban_link.
- Dispatcher runs inside the gateway by default
( kanban.dispatch_in_gateway: true) โ reclaims stale claims,
promotes ready tasks, atomically claims, spawns assigned profiles.
Auto-blocks a task after ~5 consecutive spawn failures.
- Isolation: board is the hard boundary (workers get
HERMES_KANBAN_BOARD pinned in env); tenant is a soft namespace
within a board for workspace-path + memory-key isolation.
User docs: https://hermes-agent.nousresearch.com/docs/user-guide/features/kanban
Log Relay (Hermes โ Discord)
A background Python script that tails ~/.hermes/logs/*.log and batches lines to a Discord channel. Includes session-ID extraction, rate-limit handling, and auto-restart via launchd/systemd. Useful for remote monitoring and audit trails.
- Reference:
references/discord-log-relay.md โ full setup, tuning, macOS/Linux service install, pitfalls.
- Template:
templates/discord-log-relay.py โ copy, set CHANNEL_ID, and deploy.
- Discord operations:
references/discord-operating-planes.md โ channel-purpose routing, periodic-summary vs Dreaming report formats, and safety/cost notes for Discord-first Hermes deployments.
Key pitfall: ask the user about batch frequency upfront rather than defaulting to real-time streaming. Most users prefer 10-minute or hourly batches. High-volume raw logs should be batched, summarized, or stored out-of-band; avoid Discord message storms during error loops.
Weekly Dreaming / Memory Curation
For long-running Hermes deployments, users may want an Anthropic-style "Dreaming" loop: a scheduled review that consolidates experience, proposes memory/skill/cron changes, and identifies what to keep, weaken, archive, or delete. Hermes has the building blocks (sessions, session_search, memory, skills, curator, cron), but the safe default is proposal mode:
1. Inspect recent usage and sessions.
2. Extract repeated success patterns, failure patterns, and user corrections.
3. Propose memory updates/removals without applying them silently.
4. Propose skill patches/archive candidates and cron/reporting improvements.
5. End with explicit approval checkboxes.
Do not silently rewrite or delete memory/skills from a Dreaming report unless the user explicitly authorized automatic application. See references/discord-operating-planes.md for a report template and routing heuristics.
---
Windows-Specific Quirks
Hermes runs natively on Windows (PowerShell, cmd, Windows Terminal, git-bash
mintty, VS Code integrated terminal). Most of it just works, but a handful
of differences between Win32 and POSIX have bitten us โ document new ones
here as you hit them so the next person (or the next session) doesn't
rediscover them from scratch.
Input / Keybindings
Alt+Enter doesn't insert a newline. Windows Terminal intercepts Alt+Enter
at the terminal layer to toggle fullscreen โ the keystroke never reaches
prompt_toolkit. Use Ctrl+Enter instead. Windows Terminal delivers
Ctrl+Enter as LF ( c-j), distinct from plain Enter ( c-m / CR), and the
CLI binds c-j to newline insertion on win32 only (see
_bind_prompt_submit_keys + the Windows-only c-j binding in cli.py).
Side effect: the raw Ctrl+J keystroke also inserts a newline on Windows โ
unavoidable, because Windows Terminal collapses Ctrl+Enter and Ctrl+J to
the same keycode at the Win32 console API layer. No conflicting binding
existed for Ctrl+J on Windows, so this is a harmless side effect.
mintty / git-bash behaves the same (fullscreen on Alt+Enter) unless you
disable Alt+Fn shortcuts in Options โ Keys. Easier to just use Ctrl+Enter.
Diagnosing keybindings. Run python scripts/keystroke_diagnostic.py
(repo root) to see exactly how prompt_toolkit identifies each keystroke
in the current terminal. Answers questions like "does Shift+Enter come
through as a distinct key?" (almost never โ most terminals collapse it
to plain Enter) or "what byte sequence is my terminal sending for
Ctrl+Enter?" This is how the Ctrl+Enter = c-j fact was established.
Config / Files
HTTP 400 "No models provided" on first run. config.yaml was saved
with a UTF-8 BOM (common when Windows apps write it). Re-save as UTF-8
without BOM. hermes config edit writes without BOM; manual edits in
Notepad are the usual culprit.
execute_code / Sandbox
WinError 10106 ("The requested service provider could not be loaded
or initialized") from the sandbox child process โ it can't create an
AF_INET socket, so the loopback-TCP RPC fallback fails before
connect(). Root cause is usually not a broken Winsock LSP; it's
Hermes's own env scrubber dropping SYSTEMROOT / WINDIR / COMSPEC
from the child env. Python's socket module needs SYSTEMROOT to locate
mswsock.dll. Fixed via the _WINDOWS_ESSENTIAL_ENV_VARS allowlist in
tools/code_execution_tool.py. If you still hit it, echo os.environ
inside an execute_code block to confirm SYSTEMROOT is set. Full
diagnostic recipe in references/execute-code-sandbox-env-windows.md.
Testing / Contributing
scripts/run_tests.sh doesn't work as-is on Windows โ it looks for
POSIX venv layouts ( .venv/bin/activate). The Hermes-installed venv at
venv/Scripts/ has no pip or pytest either (stripped for install size).
Workaround: install pytest + pytest-xdist + pyyaml into a system Python
3.11 user site, then invoke pytest directly with PYTHONPATH set:
"/c/Program Files/Python311/python" -m pip install --user pytest pytest-xdist pyyaml
export PYTHONPATH="$(pwd)"
"/c/Program Files/Python311/python" -m pytest tests/foo/test_bar.py -v --tb=short -n 0
Use -n 0, not -n 4 โ pyproject.toml's default addopts already
includes -n, and the wrapper's CI-parity guarantees don't apply off POSIX.
POSIX-only tests need skip guards. Common markers already in the codebase:
- Symlinks โ elevated privileges on Windows
0o600 file modes โ POSIX mode bits not enforced on NTFS by default
signal.SIGALRM โ Unix-only (see tests/conftest.py::_enforce_test_timeout)
- Winsock / Windows-specific regressions โ
@pytest.mark.skipif(sys.platform != "win32", ...)
Use the existing skip-pattern style (sys.platform == "win32" or
sys.platform.startswith("win")) to stay consistent with the rest of the
suite.
Path / Filesystem
Line endings. Git may warn LF will be replaced by CRLF the next time
Git touches it. Cosmetic โ the repo's .gitattributes normalizes. Don't
let editors auto-convert committed POSIX-newline files to CRLF.
Forward slashes work almost everywhere. C:/Users/... is accepted by
every Hermes tool and most Windows APIs. Prefer forward slashes in code
and logs โ avoids shell-escaping backslashes in bash.
---
Troubleshooting
Voice not working
1. Check stt.enabled: true in config.yaml
2. Verify provider: pip install faster-whisper or set API key
3. In gateway: /restart. In CLI: exit and relaunch.
Tool not available
1. hermes tools โ check if toolset is enabled for your platform
2. Some tools need env vars (check .env)
3. /reset after enabling tools
Model/provider issues
1. hermes doctor โ check config and dependencies
2. hermes auth add <provider> โ re-authenticate OAuth providers (use --type oauth)
3. Check .env has the right API key
4. Copilot 403: gh auth login tokens do NOT work for Copilot API. You must use the Copilot-specific OAuth device code flow via hermes model โ GitHub Copilot.
Changes not taking effect
- Tools/skills:
/reset starts a new session with updated toolset
- Config changes: In gateway:
/restart. In CLI: exit and relaunch.
- Code changes: Restart the CLI or gateway process
Deployed web dashboard shows stale CSS or theme changes
- Browser cache: Add
?v=N cache-busting query strings to CSS/JS/theme links in HTML.
- Service Worker cache: Bump
CACHE_NAME in sw.js to invalidate old shell caches.
- Data freshness: Use
fetch(url, {cache:'no-store'}) for live JSON feeds.
- See
references/static-site-cache-invalidation.md for the full diagnostic recipe.
Dashboard inspector feels too technical
- The default inspector view should contain only plain-language sentences: headline, "what they're doing now", "why it matters", and a silent visual progress bar (no text label).
- Move all technical fields (source IDs, confidence scores, progress labels, status slugs, badges) behind a "Show technical details" toggle.
- If users say "details are hard to understand," the fix is to remove more fields from the default view, not to add explanations. Explanations of technical fields are still technical.
- See
references/progressive-disclosure-human-first.md for the aggressive simplification pattern.
Skills not showing
1. hermes skills list โ verify installed
2. hermes skills config โ check platform enablement
3. Load explicitly: /skill name or hermes -s name
Gateway issues
Check logs first:
grep -i "failed to send\|error" ~/.hermes/logs/gateway.log | tail -20
Common gateway problems:
- Gateway dies on SSH logout: Enable linger:
sudo loginctl enable-linger $USER
- Gateway dies on WSL2 close: WSL2 requires
systemd=true in /etc/wsl.conf for systemd services to work. Without it, gateway falls back to nohup (dies when session closes).
- Gateway crash loop: Reset the failed state:
systemctl --user reset-failed hermes-gateway
- macOS: bot shows offline after idle time: The gateway runs as a user agent (
LimitLoadToSessionType=Aqua), so macOS suspends it when the system sleeps. The platform websocket drops and the bot appears offline until the network returns. Fix: keep the Mac awake (System Settings -> Energy -> Prevent automatic sleeping, or caffeinate -d -i -s -u &). Low Power Mode makes this worse, not better. See references/macos-gateway-sleep-disconnect.md for the full diagnostic recipe.
Platform-specific issues
- Discord bot silent: Must enable Message Content Intent in Bot โ Privileged Gateway Intents. See full Discord setup reference:
references/discord-gateway-setup.md.
- Slack bot only works in DMs: Must subscribe to
message.channels event. Without it, the bot ignores public channels.
- Windows-specific issues (
Alt+Enter newline, WinError 10106, UTF-8 BOM config, test suite, line endings): see the dedicated Windows-Specific Quirks section above.
Auxiliary models not working
If auxiliary tasks (vision, compression, session_search) fail silently, the auto provider can't find a backend. Either set OPENROUTER_API_KEY or GOOGLE_API_KEY, or explicitly configure each auxiliary task's provider:
hermes config set auxiliary.vision.provider <your_provider>
hermes config set auxiliary.vision.model <model_name>
Full system auth provisioning
For a one-shot workflow to maximize available credentials โ installing gh, generating SSH keys, configuring git, enabling all Hermes toolsets, and auditing current auth state โ see references/system-auth-setup.md.
Editing large files with patch
When a file is read with read_file(offset=...) (pagination), the tool warns that the view is partial. If you attempt patch without re-reading the full file first, you will likely hit non-unique match errors or corrupt the file. Fix: always call read_file without offset to load the whole file before patching. For append-only updates (e.g., adding a cycle log entry to state.md), terminal(command="cat >> file << 'EOF'...EOF") is a safer fallback that bypasses match-uniqueness issues entirely.
---
Windows-Specific Quirks
| Looking for... | Location |
|----------------|----------|
| Config options | hermes config edit or [Configuration docs](https://hermes-agent.nousresearch.com/docs/user-guide/configuration) |
| Available tools | hermes tools list or [Tools reference](https://hermes-agent.nousresearch.com/docs/reference/tools-reference) |
| Slash commands | /help in session or [Slash commands reference](https://hermes-agent.nousresearch.com/docs/reference/slash-commands) |
| Skills catalog | hermes skills browse or [Skills catalog](https://hermes-agent.nousresearch.com/docs/reference/skills-catalog) |
| Provider setup | hermes model or [Providers guide](https://hermes-agent.nousresearch.com/docs/integrations/providers) |
| Platform setup | hermes gateway setup or [Messaging docs](https://hermes-agent.nousresearch.com/docs/user-guide/messaging/) |
| MCP servers | hermes mcp list or [MCP guide](https://hermes-agent.nousresearch.com/docs/user-guide/features/mcp) |
| Profiles | hermes profile list or [Profiles docs](https://hermes-agent.nousresearch.com/docs/user-guide/profiles) |
| Cron jobs | hermes cron list or [Cron docs](https://hermes-agent.nousresearch.com/docs/user-guide/features/cron) |
| Memory | hermes memory status or [Memory docs](https://hermes-agent.nousresearch.com/docs/user-guide/features/memory) |
| Env variables | hermes config env-path or [Env vars reference](https://hermes-agent.nousresearch.com/docs/reference/environment-variables) |
| CLI commands | hermes --help or [CLI reference](https://hermes-agent.nousresearch.com/docs/reference/cli-commands) |
| Gateway logs | ~/.hermes/logs/gateway.log |
| Session files | ~/.hermes/sessions/ or hermes sessions browse |
| Source code | ~/.hermes/hermes-agent/ |
---
Contributor Quick Reference
For occasional contributors and PR authors. Full developer docs: https://hermes-agent.nousresearch.com/docs/developer-guide/
Project Layout
hermes-agent/
โโโ run_agent.py # AIAgent โ core conversation loop
โโโ model_tools.py # Tool discovery and dispatch
โโโ toolsets.py # Toolset definitions
โโโ cli.py # Interactive CLI (HermesCLI)
โโโ hermes_state.py # SQLite session store
โโโ agent/ # Prompt builder, context compression, memory, model routing, credential pooling, skill dispatch
โโโ hermes_cli/ # CLI subcommands, config, setup, commands
โ โโโ commands.py # Slash command registry (CommandDef)
โ โโโ config.py # DEFAULT_CONFIG, env var definitions
โ โโโ main.py # CLI entry point and argparse
โโโ tools/ # One file per tool
โ โโโ registry.py # Central tool registry
โโโ gateway/ # Messaging gateway
โ โโโ platforms/ # Platform adapters (telegram, discord, etc.)
โโโ cron/ # Job scheduler
โโโ tests/ # ~3000 pytest tests
โโโ website/ # Docusaurus docs site
Config: ~/.hermes/config.yaml (settings), ~/.hermes/.env (API keys).
Adding a Tool (3 files)
1. Create tools/your_tool.py:
import json, os
from tools.registry import registry
def check_requirements() -> bool:
return bool(os.getenv("EXAMPLE_API_KEY"))
def example_tool(param: str, task_id: str = None) -> str:
return json.dumps({"success": True, "data": "..."})
registry.register(
name="example_tool",
toolset="example",
schema={"name": "example_tool", "description": "...", "parameters": {...}},
handler=lambda args, **kw: example_tool(
param=args.get("param", ""), task_id=kw.get("task_id")),
check_fn=check_requirements,
requires_env=["EXAMPLE_API_KEY"],
)
2. Add to toolsets.py โ _HERMES_CORE_TOOLS list.
Auto-discovery: any tools/*.py file with a top-level registry.register() call is imported automatically โ no manual list needed.
All handlers must return JSON strings. Use get_hermes_home() for paths, never hardcode ~/.hermes.
Adding a Slash Command
1. Add CommandDef to COMMAND_REGISTRY in hermes_cli/commands.py
2. Add handler in cli.py โ process_command()
3. (Optional) Add gateway handler in gateway/run.py
All consumers (help text, autocomplete, Telegram menu, Slack mapping) derive from the central registry automatically.
Agent Loop (High Level)
run_conversation():
1. Build system prompt
2. Loop while iterations < max:
a. Call LLM (OpenAI-format messages + tool schemas)
b. If tool_calls โ dispatch each via handle_function_call() โ append results โ continue
c. If text response โ return
3. Context compression triggers automatically near token limit
Testing
python -m pytest tests/ -o 'addopts=' -q # Full suite
python -m pytest tests/tools/ -q # Specific area
- Tests auto-redirect
HERMES_HOME to temp dirs โ never touch real ~/.hermes/
- Run full suite before pushing any change
- Use
-o 'addopts=' to clear any baked-in pytest flags
Windows contributors: scripts/run_tests.sh currently looks for POSIX venvs ( .venv/bin/activate / venv/bin/activate) and will error out on Windows where the layout is venv/Scripts/activate + python.exe. The Hermes-installed venv at venv/Scripts/ also has no pip or pytest โ it's stripped for end-user install size. Workaround: install pytest + pytest-xdist + pyyaml into a system Python 3.11 user site ( /c/Program Files/Python311/python -m pip install --user pytest pytest-xdist pyyaml), then run tests directly:
export PYTHONPATH="$(pwd)"
"/c/Program Files/Python311/python" -m pytest tests/tools/test_foo.py -v --tb=short -n 0
Use -n 0 (not -n 4) because pyproject.toml's default addopts already includes -n, and the wrapper's CI-parity story doesn't apply off-POSIX.
Cross-platform test guards: tests that use POSIX-only syscalls need a skip marker. Common ones already in the codebase:
- Symlink creation โ
@pytest.mark.skipif(sys.platform == "win32", reason="Symlinks require elevated privileges on Windows") (see tests/cron/test_cron_script.py)
- POSIX file modes (0o600, etc.) โ
@pytest.mark.skipif(sys.platform.startswith("win"), reason="POSIX mode bits not enforced on Windows") (see tests/hermes_cli/test_auth_toctou_file_modes.py)
signal.SIGALRM โ Unix-only (see tests/conftest.py::_enforce_test_timeout)
- Live Winsock / Windows-specific regression tests โ
@pytest.mark.skipif(sys.platform != "win32", reason="Windows-specific regression")
Monkeypatching sys.platform is not enough when the code under test also calls platform.system() / platform.release() / platform.mac_ver(). Those functions re-read the real OS independently, so a test that sets sys.platform = "linux" on a Windows runner will still see platform.system() == "Windows" and route through the Windows branch. Patch all three together:
monkeypatch.setattr(sys, "platform", "linux")
monkeypatch.setattr(platform, "system", lambda: "Linux")
monkeypatch.setattr(platform, "release", lambda: "6.8.0-generic")
See tests/agent/test_prompt_builder.py::TestEnvironmentHints for a worked example.
Extending the system prompt's execution-environment block
Factual guidance about the host OS, user home, cwd, terminal backend, and shell (bash vs. PowerShell on Windows) is emitted from agent/prompt_builder.py::build_environment_hints(). This is also where the WSL hint and per-backend probe logic live. The convention:
- Local terminal backend โ emit host info (OS,
$HOME, cwd) + Windows-specific notes (hostname โ username, terminal uses bash not PowerShell).
- Remote terminal backend (anything in
_REMOTE_TERMINAL_BACKENDS: docker, singularity, modal, daytona, ssh, vercel_sandbox, managed_modal) โ suppress host info entirely and describe only the backend. A live uname/whoami/pwd probe runs inside the backend via tools.environments.get_environment(...).execute(...), cached per process in _BACKEND_PROBE_CACHE, with a static fallback if the probe times out.
- Key fact for prompt authoring: when
TERMINAL_ENV != "local", every file tool (read_file, write_file, patch, search_files) runs inside the backend container, not on the host. The system prompt must never describe the host in that case โ the agent can't touch it.
Full design notes, the exact emitted strings, and testing pitfalls:
references/prompt-builder-environment-hints.md.
Refactor-safety pattern (POSIX-equivalence guard): when you extract inline logic into a helper that adds Windows/platform-specific behavior, keep a _legacy_<name> oracle function in the test file that's a verbatim copy of the old code, then parametrize-diff against it. Example: tests/tools/test_code_execution_windows_env.py::TestPosixEquivalence. This locks in the invariant that POSIX behavior is bit-for-bit identical and makes any future drift fail loudly with a clear diff.
Commit Conventions
type: concise subject line
Optional body.
Types: fix:, feat:, refactor:, docs:, chore:
Key Rules
- Never break prompt caching โ don't change context, tools, or system prompt mid-conversation
- Message role alternation โ never two assistant or two user messages in a row
- Use
get_hermes_home() from hermes_constants for all paths (profile-safe)
- Config values go in
config.yaml, secrets go in .env
- New tools need a
check_fn so they only appear when requirements are met
[IMPORTANT: The user has invoked the "kanban-orchestrator" skill, indicating they want you to follow its instructions. The full skill content is loaded below.]
---
name: kanban-orchestrator
description: Decomposition playbook + anti-temptation rules for an orchestrator profile routing work through Kanban. The "don't do the work yourself" rule and the basic lifecycle are auto-injected into every kanban worker's system prompt; this skill is the deeper playbook when you're specifically playing the orchestrator role.
version: 3.0.0
platforms: [linux, macos, windows]
metadata:
hermes:
tags: [kanban, multi-agent, orchestration, routing]
related_skills: [kanban-worker]
---
Kanban Orchestrator โ Decomposition Playbook
> The core worker lifecycle (including the kanban_create fan-out pattern and the "decompose, don't execute" rule) is auto-injected into every kanban process via the KANBAN_GUIDANCE system-prompt block. This skill is the deeper playbook when you're an orchestrator profile whose whole job is routing.
Profiles are user-configured โ not a fixed roster
Hermes setups vary widely. Some users run a single profile that does everything; some run a small fleet (docker-worker, cron-worker); some run a curated specialist team they've named themselves. There is no default specialist roster โ the orchestrator skill does not know what profiles exist on this machine.
Before fanning out, you must ground the decomposition in the profiles that actually exist. The dispatcher silently fails to spawn unknown assignee names โ it doesn't autocorrect, doesn't suggest, doesn't fall back. So a card assigned to researcher on a setup that only has docker-worker just sits in ready forever.
Step 0: discover available profiles before planning.
Use one of these:
hermes profile list โ prints the table of profiles configured on this machine. Run it through your terminal tool if you have one; otherwise ask the user.
kanban_list(assignee="<some-name>") โ sanity-check a single name. Returns an empty list (rather than an error) for an unknown assignee, so this only confirms a name you're already considering.
- Just ask the user. "What profiles do you have set up?" is a fine first turn when the goal needs more than one specialist.
Cache the result in your working memory for the rest of the conversation. Re-asking every turn wastes a tool call.
When to use the board (vs. just doing the work)
Create Kanban tasks when any of these are true:
1. Multiple specialists are needed. Research + analysis + writing is three profiles.
2. The work should survive a crash or restart. Long-running, recurring, or important.
3. The user might want to interject. Human-in-the-loop at any step.
4. Multiple subtasks can run in parallel. Fan-out for speed.
5. Review / iteration is expected. A reviewer profile loops on drafter output.
6. The audit trail matters. Board rows persist in SQLite forever.
If none of those apply โ it's a small one-shot reasoning task โ use delegate_task instead or answer the user directly.
The anti-temptation rules
Your job description says "route, don't execute." The rules that enforce that:
- Do not execute the work yourself. Your restricted toolset usually doesn't even include terminal/file/code/web for implementation. If you find yourself "just fixing this quickly" โ stop and create a task for the right specialist.
- For any concrete task, create a Kanban task and assign it. Every single time.
- Split multi-lane requests before creating cards. A user prompt can contain several independent workstreams. Extract those lanes first, then create one card per lane instead of bundling unrelated work into a single implementer card.
- Run independent lanes in parallel. If two cards do not need each other's output, leave them unlinked so the dispatcher can fan them out. Link only true data dependencies.
- If no specialist fits the available profiles, ask the user which profile to create or which existing profile to use. Do not invent profile names; the dispatcher will silently drop unknown assignees.
- Decompose, route, and summarize โ that's the whole job.
Exception: micro-UI polish cycles
There is one narrow exception where the orchestrator may execute directly instead of creating Kanban cards: tiny UI-only polish cycles (e.g., adding a CSS class, a theme preview dot, a hover state, a cross-link, or a HUD button) that are purely presentational, require no cross-file logic changes, and fit comfortably inside a single bounded cycle with no need for review or parallel work. If the change is limited to HTML/CSS/JS cosmetics, no other profile has a stake in it, and the user did not ask for a design review, the orchestrator should just edit and publish rather than paying the kanban-overhead tax. This exception does NOT apply to architecture changes, adapter logic, plugin interfaces, or anything that touches the data layer.
Decomposition playbook
Step 1 โ Understand the goal
Ask clarifying questions if the goal is ambiguous. Cheap to ask; expensive to spawn the wrong fleet.
Step 2 โ Sketch the task graph
Before creating anything, draft the graph out loud (in your response to the user). Treat every concrete workstream as a candidate card:
1. Extract the lanes from the request.
2. Map each lane to one of the profiles you discovered in Step 0. If a lane doesn't fit any existing profile, ask the user which to use or create.
3. Decide whether each lane is independent or gated by another lane.
4. Create independent lanes as parallel cards with no parent links.
5. Create synthesis/review/integration cards with parent links to the lanes they depend on.
Examples of prompts that should fan out (using placeholder profile names โ substitute whatever exists on the user's setup):
- "Build an app" โ one card to a design-oriented profile for product/UI direction, one or two cards to engineering profiles for implementation, plus a later integration/review card if the user has a reviewer profile.
- "Fix blockers and check model variants" โ one implementation card for the blocker fixes plus one discovery/research card for config/source verification. A final reviewer card can depend on both.
- "Research docs and implement" โ a docs-research card can run in parallel with a codebase-discovery card; implementation waits only if it truly needs those findings.
- "Analyze this screenshot and find the related code" โ one card to a vision-capable profile for the visual analysis while another searches the codebase.
Words like "also," "finally," or "and" do not automatically imply a dependency. They often mean "make sure this is covered before reporting back." Only link tasks when one card cannot start until another card's output exists.
Show the graph to the user before creating cards. Let them correct it โ including which actual profile name should own each lane.
Step 3 โ Create tasks and link
Use the profile names from Step 0. The example below uses placeholders <profile-A>, <profile-B>, <profile-C> โ replace them with what the user actually has.
t1 = kanban_create(
title="research: Postgres cost vs current",
assignee="<profile-A>", # whichever profile handles research on this setup
body="Compare estimated infrastructure costs, migration costs, and ongoing ops costs over a 3-year window. Sources: AWS/GCP pricing, team time estimates, current Postgres bills from peers.",
tenant=os.environ.get("HERMES_TENANT"),
)["task_id"]
t2 = kanban_create(
title="research: Postgres performance vs current",
assignee="<profile-A>", # same profile, run in parallel
body="Compare query latency, throughput, and scaling characteristics at our expected data volume (~500GB, 10k QPS peak). Sources: benchmark papers, public case studies, pgbench results if easy.",
)["task_id"]
t3 = kanban_create(
title="synthesize migration recommendation",
assignee="<profile-B>", # whichever profile does synthesis/analysis
body="Read the findings from T1 (cost) and T2 (performance). Produce a 1-page recommendation with explicit trade-offs and a go/no-go call.",
parents=[t1, t2],
)["task_id"]
t4 = kanban_create(
title="draft decision memo",
assignee="<profile-C>", # whichever profile drafts user-facing prose
body="Turn the analyst's recommendation into a 2-page memo for the CTO. Match the tone of previous decision memos in the team's knowledge base.",
parents=[t3],
)["task_id"]
parents=[...] gates promotion โ children stay in todo until every parent reaches done, then auto-promote to ready. No manual coordination needed; the dispatcher and dependency engine handle it.
Step 4 โ Complete your own task
If you were spawned as a task yourself (e.g. a planner profile was assigned T0: "investigate Postgres migration"), mark it done with a summary of what you created:
kanban_complete(
summary="decomposed into T1-T4: 2 research lanes in parallel, 1 synthesis on their outputs, 1 prose draft on the recommendation",
metadata={
"task_graph": {
"T1": {"assignee": "<profile-A>", "parents": []},
"T2": {"assignee": "<profile-A>", "parents": []},
"T3": {"assignee": "<profile-B>", "parents": ["T1", "T2"]},
"T4": {"assignee": "<profile-C>", "parents": ["T3"]},
},
},
)
Step 5 โ Report back to the user
Tell them what you created in plain prose, naming the actual profiles you used:
> I've queued 4 tasks:
> - T1 (<profile-A>): cost comparison
> - T2 (<profile-A>): performance comparison, in parallel with T1
> - T3 (<profile-B>): synthesizes T1 + T2 into a recommendation
> - T4 (<profile-C>): turns T3 into a CTO memo
>
> The dispatcher will pick up T1 and T2 now. T3 starts when both finish. You'll get a gateway ping when T4 completes. Use the dashboard or hermes kanban tail <id> to follow along.
Common patterns
Fan-out + fan-in (research โ synthesize): N research-style cards with no parents, one synthesis card with all of them as parents.
Parallel implementation + validation: one implementer card makes the change while one explorer/researcher card verifies config, docs, or source mapping. A reviewer card can depend on both. Do not make the implementer own unrelated verification just because the user mentioned both in one sentence.
Pipeline with gates: planner โ implementer โ reviewer. Each stage's parents=[previous_task]. Reviewer blocks or completes; if reviewer blocks, the operator unblocks with feedback and respawns.
Same-profile queue: N tasks, all assigned to the same profile, no dependencies between them. Dispatcher serializes โ that profile processes them in priority order, accumulating experience in its own memory.
Parallel UI/frontend lanes: When the goal touches multiple independent HTML/CSS/JS files (e.g., a dashboard page and a 2D gather view), fan out to separate subagents per file. Each lane edits its own file, then the orchestrator integrates, fixes cross-file references (theme paths, shared JSON endpoints), and publishes. This avoids merge conflicts in single-file HTML dashboards and keeps each subagent's context focused. See references/parallel-ui-lanes-and-publishing.md for the post-subagent integration checklist and rsync safety notes.
Human-in-the-loop: Any task can kanban_block() to wait for input. Dispatcher respawns after /unblock. The comment thread carries the full context.
Pitfalls
Inventing profile names that don't exist. The dispatcher silently fails to spawn unknown assignees โ the card just sits in ready forever. Always assign to a profile from your Step 0 discovery; ask the user if you're unsure.
Bundling independent lanes into one card. If the user asks for two independent outcomes, create two cards. Example: "fix blockers and check model variants" is not one fixer task; create a fixer/engineer card for the fixes and an explorer/researcher card for the variant check, then optionally gate review on both.
Over-linking because of wording. "Finally check X" may still be parallel with implementation if X is static config, docs, or source discovery. Link it after implementation only when the check depends on the implementation result.
Forgetting dependency links. If the task graph says research -> implement -> review, do not create all tasks as independent ready cards. Use parent links so implement/review cannot run before their inputs exist.
Reassignment vs. new task. If a reviewer blocks with "needs changes," create a NEW task linked from the reviewer's task โ don't re-run the same task with a stern look. The new task is assigned to the original implementer profile.
Argument order for links. kanban_link(parent_id=..., child_id=...) โ parent first. Mixing them up demotes the wrong task to todo.
Ignoring explicit user feedback to keep building infrastructure. When the user says a specific UX issue (legibility, theme switching, movement density) is "immediate priority," treat it as P0 and route it before deeper packaging/architecture work. Infrastructure polish feels productive, but shipping user-visible fixes is what matters. Create cards for the UX feedback first, then resume infrastructure lanes.
Treating status: complete as immutable when user feedback says otherwise. A state.md that says status: complete does not override a user's report that a completion criterion is actually broken. If the user says "theme switching is not working" and the Final Completion Condition requires "working UI theme switcher," the mission is not complete. Reactivate immediately: set status: active, append a reactivation cycle log, and fix the issue. Do not burn cycles on post-complete verification while the user is reporting active defects.
Don't pre-create the whole graph if the shape depends on intermediate findings. If T3's structure depends on what T1 and T2 find, let T3 exist as a "synthesize findings" task whose own first step is to read parent handoffs and plan the rest. Orchestrators can spawn orchestrators.
Tenant inheritance. If HERMES_TENANT is set in your env, pass tenant=os.environ.get("HERMES_TENANT") on every kanban_create call so child tasks stay in the same namespace.
Verifying cross-file references after directory reorganization. When subagents edit HTML/CSS/JS files and the directory structure shifts (e.g., moving files from root into web/dashboard/ and web/gather/), relative asset paths ( themes/default/theme.css, ./ops-data.json) often break. After subagents finish, the orchestrator must grep for href= and src= in moved files and fix relative paths before publishing. Subagents don't know the final publish layout โ the orchestrator does.
Destructive sync wipes needed files. Commands like rsync -av --delete will delete destination files that aren't in the source list. If you publish a directory tree piecemeal (e.g., copy web/dashboard/ first, then web/gather/ separately), --delete on the first rsync will erase the gather files before the second rsync runs. Either list all source paths in a single rsync invocation, or omit --delete and use cp -r / rsync -av without deletion when doing staged copies.
Recovering stuck workers
When a worker profile keeps crashing, hallucinating, or getting blocked by its own mistakes (usually: wrong model, missing skill, broken credential), the kanban dashboard flags the task with a โ badge and opens a Recovery section in the drawer. Three primary actions:
1. Reclaim (or hermes kanban reclaim <task_id>) โ abort the running worker immediately and reset the task to ready. The existing claim TTL is ~15 min; this is the fast path out.
2. Reassign (or hermes kanban reassign <task_id> <new-profile> --reclaim) โ switch the task to a different profile (one that exists on this setup) and let the dispatcher pick it up with a fresh worker.
3. Change profile model โ the dashboard prints a copy-paste hint for hermes -p <profile> model since profile config lives on disk; edit it in a terminal, then Reclaim to retry with the new model.
Hallucination warnings appear on tasks where a worker's kanban_complete(created_cards=[...]) claim included card ids that don't exist or weren't created by the worker's profile (the gate blocks the completion), or where the free-form summary references t_<hex> ids that don't resolve (advisory prose scan, non-blocking). Both produce audit events that persist even after recovery actions โ the trail stays for debugging.
The user has provided the following instruction alongside the skill invocation: [IMPORTANT: You are running as a scheduled cron job. DELIVERY: Your final response will be automatically delivered to the user โ do NOT use send_message or try to deliver the output yourself. Just produce your report/output as your final response and the system handles the rest. SILENT: If there is genuinely nothing new to report, respond with exactly "[SILENT]" (nothing else) to suppress delivery. Never combine [SILENT] with content โ either report your findings normally, or say [SILENT] and nothing more.]
You are the 15-minute Orchestrator for Son's Autonomous Agent Lab v1, reporting to Discord channel ID 1505805763824586952.
Durable state path: /Users/jooho-hermes/.hermes/autonomous-agent-lab/state.md
Working directory for experiment artifacts: /Users/jooho-hermes/.hermes/autonomous-agent-lab/
Preferred published web root: /Users/jooho-hermes/hermes-web/agent-pets/
Top-level directive from Son:
- The project has evolved from a personal dashboard into an INSTALLABLE PRODUCT that external Hermes users can deploy.
- The final target is a self-contained, configurable, publishable solution: "Hermes Pixel Pet Ops Office".
- Do NOT shrink the mission into a small static MVP and autonomously stop.
- The Gather.town-style 2D spatial office is a first-class feature, not a side page.
Latest UX feedback from Son (treat as immediate priority before deeper packaging work):
- Details are hard for a human to understand. Add human-first summaries, plain-language labels, and progressive disclosure: summary first, technical details second.
- Gather Town version has too many agents roaming around. Reduce default movement, add density/speed controls, cluster agents by room/task, and add focus/calm mode.
- Theme switching is not visibly working. Implement real UI theme switcher with persistence and clear visual theme changes.
Key product requirements (installable solution level):
1. Config-driven architecture: all paths, URLs, colors, names, room layouts via config.yaml. No hardcoded references to jooho-hermes.
2. Self-contained package: clear directory structure (src/, web/, config/, docs/, scripts/), install script, requirements.txt.
3. Pluggable data adapter: support multiple backends via plugin architecture.
4. Themeable frontend: CSS variables driven from config, swappable themes, plus a working UI theme switcher.
5. Multi-tenant ready: works for any Hermes instance.
6. Build/Deploy ready: Dockerfile or docker-compose, or clear static-server setup.
7. Documentation: README, architecture docs, configuration reference, contributor guide.
8. Human-comprehensible UX: plain-language summaries and progressive disclosure for technical detail.
9. Gather.town calm mode: adjustable movement density/speed and less chaotic defaults.
10. Versioned releases: CHANGELOG.md, semantic versioning, release packaging.
Mission model:
- Read state.md first before doing anything else.
- If state.md says
status: inactive or has no Current Mission, do not invent work. Return exactly: ๐ก Autonomous Agent Lab ๋๊ธฐ์ค โ Son์ด ํธ๋ฆฌ๊ฑฐ/๋ฏธ์
์ ์ฃผ๋ฉด 15๋ถ ์ฌ์ดํด์ ์์ํฉ๋๋ค.
- If state.md says
status: active, run one bounded 15-minute cycle toward the full installable solution.
- If state.md says
status: complete, verify that the Final Completion Condition in state.md is truly met. If it is not fully met, reactivate or report that state needs correction.
Cycle procedure when active:
1. Read state.md first. Extract current mission, constraints, previous cycle log, and Final Completion Condition.
2. Decide the next smallest useful step toward installable solution quality. Focus on: architecture, configurability, documentation, and clean separation of concerns.
3. Use delegate_task for independent subagent lanes when helpful.
4. Prefer concrete progress: refactor to config-driven, add install scripts, create docs, add Docker support, theme system, plugin architecture.
5. Update state.md with a new cycle log entry before final reporting.
6. Completion rule: only set status: complete when every item under state.md Final Completion Condition is satisfied. A non-installable MVP is not complete.
7. Stop/block only if Son explicitly stops/redirects, a safety boundary is reached, or a hard blocker needs Son's decision.
Link requirement (never forget):
- Every cycle report MUST include at least one direct viewable link to the published dashboard/artifact.
- The canonical URL:
http://hermes-mac-mini.tail46b3c6.ts.net:8099/agent-pets/
- Include gather town URL too:
http://hermes-mac-mini.tail46b3c6.ts.net:8099/agent-pets/gather/
Final Discord message format:
[Autonomous Agent Lab v1 / Cycle N]
๋ชฉํ:
์ํ:
๊ฒฐ๊ณผ:
๊ฒ์ฆ:
๋ค์:
์ํ:
Safety/quality rules:
- Do not handle secrets, passwords, API keys, payment, permission dialogs, or destructive commands.
- Do not claim completion without updating state.md.
- Do not rely on Discord history as durable state.
- Do not spam raw logs; summarize lane outputs and verification.
- Keep working in /Users/jooho-hermes/.hermes/autonomous-agent-lab/ and publish only to /Users/jooho-hermes/hermes-web/agent-pets/ unless the state file says otherwise.
Design/UX priorities:
- Mobile responsiveness is first-class.
- Character animation/movement is desired.
- Every cycle report must include published links.
- This is now a product engineering mission. Architecture, configurability, and documentation matter as much as visuals.
Response
[Autonomous Agent Lab v1 / Cycle 55]
๋ชฉํ: Son์ UX ํผ๋๋ฐฑ(ํ
๋ง ์ ํ ๋ฏธ๋์, Gather Town ํผ์ก, ์ธ๋ถ ๋ด์ฉ ๊ฐ๋
์ฑ)์ ์ถ๊ฐ๋ก ํด๊ฒฐํ๊ธฐ ์ํด ์บ์ ๊ฐ์ ์ญ์ ๋ฒํผ๊ณผ Gather Town Zen ๋ชจ๋๋ฅผ ๊ตฌํํฉ๋๋ค.
์ํ:
- ๋์๋ณด๋์ Gather Town ์์ชฝ์ "๐ ์บ์ ์ญ์ & ์๋ก๊ณ ์นจ" ๋ฒํผ ์ถ๊ฐ โ Service Worker unregister + Cache ์ญ์ + hard reload
- Gather Town์ "๐ง Zen ๋ชจ๋" ์ถ๊ฐ โ ์ค๋(Son) + ์์
์ค์ธ ์์ด์ ํธ๋ง ํ์, ๋๋จธ์ง๋ ์์ ํ ์จ๊น
- Focus ๋ชจ๋์ Zen ๋ชจ๋๋ ์ํธ ๋ฐฐํ (ํ๋ ์ผ๋ฉด ๋ค๋ฅธ ํ๋ ์๋ ํด์ )
- ์์ฐ ๋งํฌ ๋ฒ์ ์ ?v=54 โ ?v=55๋ก ์ผ๊ด ์
๊ทธ๋ ์ด๋, Service Worker CACHE_NAME์ v7 โ v8๋ก ๊ฐฑ์
- ํตํฉ ํ
์คํธ 7๊ฐ ์ ๊ท ํญ๋ชฉ ์ถ๊ฐ (์ด 106๊ฐ)
๊ฒฐ๊ณผ:
- ๋์๋ณด๋ ํ๋จ์ ์บ์ ์ญ์ ๋ฒํผ ๋ฐฐ์น ์๋ฃ
- Gather Town HUD์ Zen ๋ชจ๋ ๋ฒํผ + ์บ์ ์ญ์ ๋ฒํผ ๋ฐฐ์น ์๋ฃ
- Zen ๋ชจ๋ ํ์ฑ ์ ๋น์์
์์ด์ ํธ๋ opacity:0 + pointer-events:none ์ฒ๋ฆฌ
- ๋ชจ๋ ๋ณ๊ฒฝ์ฌํญ ์น ๋ฃจํธ์ ๊ฒ์ ์๋ฃ
๊ฒ์ฆ:
- ํตํฉ ํ
์คํธ: 106/106 passed, 0 failed
- ์ค์ ๊ฒ์ฆ: 21/21 passed
- Adapter ์ ์ ์คํ: 32 agents, 15 cron jobs, 20 sessions, 16 events, schema 1.4
- ๊ฒ์๋ HTML/JS/CSS๊ฐ ?v=55 ์ฐธ์กฐ ํ์ธ
- sw.js CACHE_NAME = pixel-pet-ops-v8 ํ์ธ
- ops-data.json / health.json mtime 60์ด ์ด๋ด ์ ์
- refresh.err.log ๊ณ์ ๋น ์ํ
๋ค์:
- Son์ด ๋์๋ณด๋๋ Gather Town ํ๋จ์ "๐ ์บ์ ์ญ์ & ์๋ก๊ณ ์นจ" ๋ฒํผ์ ํด๋ฆญํ๋ฉด ๋ธ๋ผ์ฐ์ ์บ์์ Service Worker๊ฐ ์์ ํ ์ ๊ฑฐ๋ฉ๋๋ค.
- ์บ์ ์ญ์ ํ ํ
๋ง ์ ํ(๐
Default / ๐ Dark Ops / ๐ธ Cozy Pastel)์ด ๋์ ๋๊ฒ ๋์ํ๋์ง ํ์ธ ๋ถํ๋๋ฆฝ๋๋ค.
- Gather Town์ด ์ฌ์ ํ ํผ์กํ๋ค๋ฉด ๐ง Zen ๋ชจ๋๋ฅผ ์ผ๋ณด์ธ์: ์ค๋ + ์์
์ค์ธ ์์ด์ ํธ๋ง ๋ณด์
๋๋ค.
์ํ: ๐ข active โ Son์ ํ์ธ์ ๊ธฐ๋ค๋ฆฌ๋ ์ค. cache-busting v55์ Zen ๋ชจ๋๊ฐ ๋ฐฐํฌ๋์์ต๋๋ค.
๐ ๋์๋ณด๋: http://hermes-mac-mini.tail46b3c6.ts.net:8099/agent-pets/
๐ Gather Town: http://hermes-mac-mini.tail46b3c6.ts.net:8099/agent-pets/gather/
|
| 2026-05-19 14-02-26 |
79,695 chars |
2026-05-19_14-02-26.md |
Cron Job: autonomous-agent-lab-v1-orchestrator
Job ID: 35127ff89556
Run Time: 2026-05-19 14:02:26
Schedule: every 15m
Prompt
[IMPORTANT: The user has invoked the "hermes-agent" skill, indicating they want you to follow its instructions. The full skill content is loaded below.]
---
name: hermes-agent
description: "Configure, extend, or contribute to Hermes Agent."
version: 2.1.0
author: Hermes Agent + Teknium
license: MIT
platforms: [linux, macos, windows]
metadata:
hermes:
tags: [hermes, setup, configuration, multi-agent, spawning, cli, gateway, development]
homepage: https://github.com/NousResearch/hermes-agent
related_skills: [claude-code, codex, opencode]
---
Hermes Agent
Hermes Agent is an open-source AI agent framework by Nous Research that runs in your terminal, messaging platforms, and IDEs. It belongs to the same category as Claude Code (Anthropic), Codex (OpenAI), and OpenClaw โ autonomous coding and task-execution agents that use tool calling to interact with your system. Hermes works with any LLM provider (OpenRouter, Anthropic, OpenAI, DeepSeek, local models, and 15+ others) and runs on Linux, macOS, and WSL.
What makes Hermes different:
- Self-improving through skills โ Hermes learns from experience by saving reusable procedures as skills. When it solves a complex problem, discovers a workflow, or gets corrected, it can persist that knowledge as a skill document that loads into future sessions. Skills accumulate over time, making the agent better at your specific tasks and environment.
- Persistent memory across sessions โ remembers who you are, your preferences, environment details, and lessons learned. Pluggable memory backends (built-in, Honcho, Mem0, and more) let you choose how memory works.
- Multi-platform gateway โ the same agent runs on Telegram, Discord, Slack, WhatsApp, Signal, Matrix, Email, and 10+ other platforms with full tool access, not just chat.
- Provider-agnostic โ swap models and providers mid-workflow without changing anything else. Credential pools rotate across multiple API keys automatically.
- Profiles โ run multiple independent Hermes instances with isolated configs, sessions, skills, and memory.
- Extensible โ plugins, MCP servers, custom tools, webhook triggers, cron scheduling, and the full Python ecosystem.
People use Hermes for software development, research, system administration, data analysis, content creation, home automation, and anything else that benefits from an AI agent with persistent context and full system access.
This skill helps you work with Hermes Agent effectively โ setting it up, configuring features, spawning additional agent instances, troubleshooting issues, finding the right commands and settings, and understanding how the system works when you need to extend or contribute to it.
Docs: https://hermes-agent.nousresearch.com/docs/
Quick Start
Install
curl -fsSL https://raw.githubusercontent.com/NousResearch/hermes-agent/main/scripts/install.sh | bash
Interactive chat (default)
hermes
Single query
hermes chat -q "What is the capital of France?"
Setup wizard
hermes setup
Change model/provider
hermes model
Check health
hermes doctor
---
CLI Reference
Global Flags
hermes [flags] [command]
--version, -V Show version
--resume, -r SESSION Resume session by ID or title
--continue, -c [NAME] Resume by name, or most recent session
--worktree, -w Isolated git worktree mode (parallel agents)
--skills, -s SKILL Preload skills (comma-separate or repeat)
--profile, -p NAME Use a named profile
--yolo Skip dangerous command approval
--pass-session-id Include session ID in system prompt
No subcommand defaults to chat.
Chat
hermes chat [flags]
-q, --query TEXT Single query, non-interactive
-m, --model MODEL Model (e.g. anthropic/claude-sonnet-4)
-t, --toolsets LIST Comma-separated toolsets
--provider PROVIDER Force provider (openrouter, anthropic, nous, etc.)
-v, --verbose Verbose output
-Q, --quiet Suppress banner, spinner, tool previews
--checkpoints Enable filesystem checkpoints (/rollback)
--source TAG Session source tag (default: cli)
Configuration
hermes setup [section] Interactive wizard (model|terminal|gateway|tools|agent)
hermes model Interactive model/provider picker
hermes config View current config
hermes config edit Open config.yaml in $EDITOR
hermes config set KEY VAL Set a config value
hermes config path Print config.yaml path
hermes config env-path Print .env path
hermes config check Check for missing/outdated config
hermes config migrate Update config with new options
hermes doctor [--fix] Check dependencies and config
Credential Pools
hermes auth add Interactive credential wizard (oauth, api-key)
hermes auth list [PROVIDER] List pooled credentials
hermes auth remove P INDEX Remove by provider + index
hermes auth reset PROVIDER Clear exhaustion status
hermes logout Clear stored auth
Tools & Skills
hermes tools Interactive tool enable/disable (curses UI)
hermes tools list Show all tools and status
hermes tools enable NAME Enable a toolset
hermes tools disable NAME Disable a toolset
hermes skills list List installed skills
hermes skills search QUERY Search the skills hub
hermes skills install ID Install a skill (ID can be a hub identifier OR a direct https://โฆ/SKILL.md URL; pass --name to override when frontmatter has no name)
hermes skills inspect ID Preview without installing
hermes skills config Enable/disable skills per platform
hermes skills check Check for updates
hermes skills update Update outdated skills
hermes skills uninstall N Remove a hub skill
hermes skills publish PATH Publish to registry
hermes skills browse Browse all available skills
hermes skills tap add REPO Add a GitHub repo as skill source
MCP Servers
hermes mcp serve Run Hermes as an MCP server
hermes mcp add NAME Add an MCP server (--url or --command)
hermes mcp remove NAME Remove an MCP server
hermes mcp list List configured servers
hermes mcp test NAME Test connection
hermes mcp configure NAME Toggle tool selection
Gateway (Messaging Platforms)
hermes gateway run Start gateway foreground
hermes gateway install Install as background service
hermes gateway start/stop Control the service
hermes gateway restart Restart the service
hermes gateway status Check status
hermes gateway setup Configure platforms
Supported platforms: Telegram, Discord, Slack, WhatsApp, Signal, Email, SMS, Matrix, Mattermost, Home Assistant, DingTalk, Feishu, WeCom, BlueBubbles (iMessage), Weixin (WeChat), API Server, Webhooks. Open WebUI connects via the API Server adapter.
Platform docs: https://hermes-agent.nousresearch.com/docs/user-guide/messaging/
Discord-specific walkthrough (token, intents, service install, access control): see references/discord-gateway-setup.md in this skill.
- Per-channel personas and skill bindings: see
references/gateway-channel-personas.md (works on Discord, Slack, Telegram, Mattermost, Matrix).
- For long-running Discord-first operations, purpose-specific channel routing, periodic summaries, weekly Dreaming/audit reports, and log-safety patterns: see
references/discord-operating-planes.md.
- For broad Hermes/LifeOS/SQAF ecosystem audits (cron inventory, live services, dashboards, provider/model warnings, and control-plane gaps), see
references/ecosystem-audit.md.
Sessions
hermes sessions list List recent sessions
hermes sessions browse Interactive picker
hermes sessions export OUT Export to JSONL
hermes sessions rename ID T Rename a session
hermes sessions delete ID Delete a session
hermes sessions prune Clean up old sessions (--older-than N days)
hermes sessions stats Session store statistics
For browser-based viewing of existing Hermes CLI/Discord/cron session transcripts, prefer a lightweight static export from ~/.hermes/state.db into a private web root instead of assuming Open WebUI can browse Hermes' native session store. See references/hermes-session-static-web-viewer.md for the SQLite schema, static HTML export workflow, redaction/truncation cautions, and the user's Mac mini deployment (/hermes-sessions/ under the Tailscale-only ~/hermes-web site).
For cron job execution history, the same static-export pattern applies to ~/.hermes/cron/jobs.json and ~/.hermes/cron/output/{job_id}/*.md. See references/cron-history-web-viewer.md for the cron data model, schedule-dict pitfall, and the user's deployed /cron-history/ dashboard.
Cron Jobs
hermes cron list List jobs (--all for disabled)
hermes cron create SCHED Create: '30m', 'every 2h', '0 9 *'
hermes cron edit ID Edit schedule, prompt, delivery
hermes cron pause/resume ID Control job state
hermes cron run ID Trigger on next tick
hermes cron remove ID Delete a job
hermes cron status Scheduler status
For bounded autonomous lab/orchestrator cron jobs that use file-based state, subagent lanes, artifact publishing, and status transitions (active โ complete/blocked/inactive), see references/autonomous-agent-lab-cron-cycle.md. A reusable verification script template lives at scripts/verify-completion-template.py.
For a worked example of evolving an autonomous lab into a config-driven, themeable, Docker-ready installable product, see references/autonomous-lab-product-architecture.md. For CI, integration testing, pluggable adapter architecture, bounded cycle orchestration, and post-productization patterns, see references/product-maturity-patterns.md.
For the final completion verification checklist โ the explicit audit pattern to run before marking status: complete on an installable-solution mission, see references/autonomous-lab-completion-verification.md.
For the reactivation protocol when a completed lab receives new P0 feedback or the user contradicts a completion claim, see references/autonomous-lab-reactivation-protocol.md.
For adding historical trend tracking (SQLite-backed agent status transitions + vanilla JS SVG sparklines) to an autonomous lab dashboard, see references/history-tracking-sparkline-pattern.md.
For reusable dashboard UX patterns (onboarding tours, data freshness badges, keyboard shortcuts, progressive disclosure inspectors, cross-linking between views), see references/dashboard-ux-patterns.md.
For programmatic verification of CSS custom-property theme systems โ catching scoping bugs, confirming theme distinctness, and validating JS switching logic โ see references/theme-system-verification.md.
For Son's Discord-first autonomous experiments where a channel hosts a repeated multi-agent loop, use the Autonomous Discord Agent Lab pattern: create file-based durable state, a paused cron orchestrator delivered to discord:<channel_id>, then activate it from a user mission trigger. See references/autonomous-discord-agent-lab.md.
Webhooks
hermes webhook subscribe N Create route at /webhooks/<name>
hermes webhook list List subscriptions
hermes webhook remove NAME Remove a subscription
hermes webhook test NAME Send a test POST
Profiles
hermes profile list List all profiles
hermes profile create NAME Create (--clone, --clone-all, --clone-from)
hermes profile use NAME Set sticky default
hermes profile delete NAME Delete a profile
hermes profile show NAME Show details
hermes profile alias NAME Manage wrapper scripts
hermes profile rename A B Rename a profile
hermes profile export NAME Export to tar.gz
hermes profile import FILE Import from archive
Credential Pools
hermes auth add Interactive credential wizard
hermes auth list [PROVIDER] List pooled credentials
hermes auth remove P INDEX Remove by provider + index
hermes auth reset PROVIDER Clear exhaustion status
Other
hermes insights [--days N] Usage analytics
hermes update Update to latest version
hermes pairing list/approve/revoke DM authorization
hermes plugins list/install/remove Plugin management
hermes honcho setup/status Honcho memory integration (requires honcho plugin)
hermes memory setup/status/off Memory provider config
hermes completion bash|zsh Shell completions
hermes acp ACP server (IDE integration)
hermes claw migrate Migrate from OpenClaw
hermes uninstall Uninstall Hermes
---
Slash Commands (In-Session)
Type these during an interactive chat session. New commands land fairly
often; if something below looks stale, run /help in-session for the
authoritative list or see the [live slash commands reference](https://hermes-agent.nousresearch.com/docs/reference/slash-commands).
The registry of record is hermes_cli/commands.py โ every consumer
(autocomplete, Telegram menu, Slack mapping, /help) derives from it.
Session Control
/new (/reset) Fresh session
/clear Clear screen + new session (CLI)
/retry Resend last message
/undo Remove last exchange
/title [name] Name the session
/compress Manually compress context
/stop Kill background processes
/rollback [N] Restore filesystem checkpoint
/snapshot [sub] Create or restore state snapshots of Hermes config/state (CLI)
/background <prompt> Run prompt in background
/queue <prompt> Queue for next turn
/steer <prompt> Inject a message after the next tool call without interrupting
/agents (/tasks) Show active agents and running tasks
/resume [name] Resume a named session
/goal [text|sub] Set a standing goal Hermes works on across turns until achieved
(subcommands: status, pause, resume, clear)
/redraw Force a full UI repaint (CLI)
Configuration
/config Show config (CLI)
/model [name] Show or change model
/personality [name] Set personality
/reasoning [level] Set reasoning (none|minimal|low|medium|high|xhigh|show|hide)
/verbose Cycle: off โ new โ all โ verbose
/voice [on|off|tts] Voice mode
/yolo Toggle approval bypass
/busy [sub] Control what Enter does while Hermes is working (CLI)
(subcommands: queue, steer, interrupt, status)
/indicator [style] Pick the TUI busy-indicator style (CLI)
(styles: kaomoji, emoji, unicode, ascii)
/footer [on|off] Toggle gateway runtime-metadata footer on final replies
/skin [name] Change theme (CLI)
/statusbar Toggle status bar (CLI)
Tools & Skills
/tools Manage tools (CLI)
/toolsets List toolsets (CLI)
/skills Search/install skills (CLI)
/skill <name> Load a skill into session
/reload-skills Re-scan ~/.hermes/skills/ for added/removed skills
/reload Reload .env variables into the running session (CLI)
/reload-mcp Reload MCP servers
/cron Manage cron jobs (CLI)
/curator [sub] Background skill maintenance (status, run, pin, archive, โฆ)
/kanban [sub] Multi-profile collaboration board (tasks, links, comments)
/plugins List plugins (CLI)
Gateway
/approve Approve a pending command (gateway)
/deny Deny a pending command (gateway)
/restart Restart gateway (gateway)
/sethome Set current chat as home channel (gateway)
/update Update Hermes to latest (gateway)
/topic [sub] Enable or inspect Telegram DM topic sessions (gateway)
/platforms (/gateway) Show platform connection status (gateway)
Utility
/branch (/fork) Branch the current session
/fast Toggle priority/fast processing
/browser Open CDP browser connection
/history Show conversation history (CLI)
/save Save conversation to file (CLI)
/copy [N] Copy the last assistant response to clipboard (CLI)
/paste Attach clipboard image (CLI)
/image Attach local image file (CLI)
Info
/help Show commands
/commands [page] Browse all commands (gateway)
/usage Token usage
/insights [days] Usage analytics
/gquota Show Google Gemini Code Assist quota usage (CLI)
/status Session info (gateway)
/profile Active profile info
/debug Upload debug report (system info + logs) and get shareable links
Exit
/quit (/exit, /q) Exit CLI
---
Key Paths & Config
~/.hermes/config.yaml Main configuration
~/.hermes/.env API keys and secrets
$HERMES_HOME/skills/ Installed skills
~/.hermes/sessions/ Session transcripts
~/.hermes/logs/ Gateway and error logs
~/.hermes/auth.json OAuth tokens and credential pools
~/.hermes/hermes-agent/ Source code (if git-installed)
Profiles use ~/.hermes/profiles/<name>/ with the same layout.
Config Sections
Edit with hermes config edit or hermes config set section.key value.
| Section | Key options |
|---------|-------------|
| model | default, provider, base_url, api_key, context_length |
| agent | max_turns (90), tool_use_enforcement |
| terminal | backend (local/docker/ssh/modal), cwd, timeout (180) |
| compression | enabled, threshold (0.50), target_ratio (0.20) |
| display | skin, tool_progress, show_reasoning, show_cost |
| stt | enabled, provider (local/groq/openai/mistral) |
| tts | provider (edge/elevenlabs/openai/minimax/mistral/neutts) |
| memory | memory_enabled, user_profile_enabled, provider |
| security | tirith_enabled, website_blocklist |
| delegation | model, provider, base_url, api_key, max_iterations (50), reasoning_effort |
| checkpoints | enabled, max_snapshots (50) |
| fallback_model | provider, model, base_url, key_env |
Fallback Providers
Hermes can automatically fail over to a backup provider:model when the primary is unavailable. This is turn-scoped โ each new user message starts with the primary restored; fallback only activates mid-turn when the primary fails.
Configuration ( ~/.hermes/config.yaml):
fallback_model:
provider: opencode-go
model: kimi-k2.6
Or use the interactive manager:
hermes fallback add # interactive picker
hermes fallback list # show fallback chain
hermes fallback remove # remove by index
Legacy note: fallback_model (singular) is the legacy single-fallback key. fallback_providers (list) supports multiple ordered fallbacks. When both exist, fallback_providers takes priority.
Trigger conditions (after exhausting retries where applicable):
- Rate limits (HTTP 429)
- Server errors (HTTP 500, 502, 503)
- Auth failures (HTTP 401, 403) โ immediately
- Not found (HTTP 404) โ immediately
- Invalid / empty responses repeatedly
Supported providers include all standard providers (OpenRouter, Anthropic, OpenCode Go/ Zen, Kimi, etc.) plus custom endpoints with base_url + key_env. Full provider docs: https://hermes-agent.nousresearch.com/docs/integrations/providers
Limitations:
- Subagent delegation does not inherit fallback config
- Cron jobs do not use fallback (use per-job provider/model overrides)
- Auxiliary tasks (vision, compression, etc.) use their own
auxiliary.* provider chain
For a deep-dive with worked examples and model lists, see references/fallback-providers.md.
Full config reference: https://hermes-agent.nousresearch.com/docs/user-guide/configuration
Providers
20+ providers supported. Set via hermes model or hermes setup.
| Provider | Auth | Key env var |
|----------|------|-------------|
| OpenRouter | API key | OPENROUTER_API_KEY |
| Anthropic | API key | ANTHROPIC_API_KEY |
| Nous Portal | OAuth | hermes auth |
| OpenAI Codex | OAuth | hermes auth |
| GitHub Copilot | Token | COPILOT_GITHUB_TOKEN |
| Google Gemini | API key | GOOGLE_API_KEY or GEMINI_API_KEY |
| DeepSeek | API key | DEEPSEEK_API_KEY |
| xAI / Grok | API key | XAI_API_KEY |
| Hugging Face | Token | HF_TOKEN |
| Z.AI / GLM | API key | GLM_API_KEY |
| MiniMax | API key | MINIMAX_API_KEY |
| MiniMax CN | API key | MINIMAX_CN_API_KEY |
| Kimi / Moonshot | API key | KIMI_API_KEY |
| Alibaba / DashScope | API key | DASHSCOPE_API_KEY |
| Xiaomi MiMo | API key | XIAOMI_API_KEY |
| Kilo Code | API key | KILOCODE_API_KEY |
| AI Gateway (Vercel) | API key | AI_GATEWAY_API_KEY |
| OpenCode Zen | API key | OPENCODE_ZEN_API_KEY |
| OpenCode Go | API key | OPENCODE_GO_API_KEY |
| Qwen OAuth | OAuth | hermes auth add qwen-oauth |
| Custom endpoint | Config | model.base_url + model.api_key in config.yaml |
| GitHub Copilot ACP | External | COPILOT_CLI_PATH or Copilot CLI |
Full provider docs: https://hermes-agent.nousresearch.com/docs/integrations/providers
Toolsets
Enable/disable via hermes tools (interactive) or hermes tools enable/disable NAME.
| Toolset | What it provides |
|---------|-----------------|
| web | Web search and content extraction |
| search | Web search only (subset of web) |
| browser | Browser automation (Browserbase, Camofox, or local Chromium) |
| terminal | Shell commands and process management |
| file | File read/write/search/patch |
| code_execution | Sandboxed Python execution |
| vision | Image analysis |
| image_gen | AI image generation |
| video | Video analysis and generation |
| tts | Text-to-speech |
| skills | Skill browsing and management |
| memory | Persistent cross-session memory |
| session_search | Search past conversations |
| delegation | Subagent task delegation |
| cronjob | Scheduled task management |
| clarify | Ask user clarifying questions |
| messaging | Cross-platform message sending |
| todo | In-session task planning and tracking |
| kanban | Multi-agent work-queue tools (gated to workers) |
| debugging | Extra introspection/debug tools (off by default) |
| safe | Minimal, low-risk toolset for locked-down sessions |
| spotify | Spotify playback and playlist control |
| homeassistant | Smart home control (off by default) |
| discord | Discord integration tools |
| discord_admin | Discord admin/moderation tools |
| feishu_doc | Feishu (Lark) document tools |
| feishu_drive | Feishu (Lark) drive tools |
| yuanbao | Yuanbao integration tools |
| rl | Reinforcement learning tools (off by default) |
| moa | Mixture of Agents (off by default) |
Full enumeration lives in toolsets.py as the TOOLSETS dict; _HERMES_CORE_TOOLS is the default bundle most platforms inherit from.
Tool changes take effect on /reset (new session). They do NOT apply mid-conversation to preserve prompt caching.
---
Security & Privacy Toggles
Common "why is Hermes doing X to my output / tool calls / commands?" toggles โ and the exact commands to change them. Most of these need a fresh session (/reset in chat, or start a new hermes invocation) because they're read once at startup.
Secret redaction in tool output
Secret redaction is off by default โ tool output (terminal stdout, read_file, web content, subagent summaries, etc.) passes through unmodified. If the user wants Hermes to auto-mask strings that look like API keys, tokens, and secrets before they enter the conversation context and logs:
hermes config set security.redact_secrets true # enable globally
Restart required. security.redact_secrets is snapshotted at import time โ toggling it mid-session (e.g. via export HERMES_REDACT_SECRETS=true from a tool call) will NOT take effect for the running process. Tell the user to run hermes config set security.redact_secrets true in a terminal, then start a new session. This is deliberate โ it prevents an LLM from flipping the toggle on itself mid-task.
Disable again with:
hermes config set security.redact_secrets false
PII redaction in gateway messages
Separate from secret redaction. When enabled, the gateway hashes user IDs and strips phone numbers from the session context before it reaches the model:
hermes config set privacy.redact_pii true # enable
hermes config set privacy.redact_pii false # disable (default)
Command approval prompts
By default (approvals.mode: manual), Hermes prompts the user before running shell commands flagged as destructive (rm -rf, git reset --hard, etc.). The modes are:
manual โ always prompt (default)
smart โ use an auxiliary LLM to auto-approve low-risk commands, prompt on high-risk
off โ skip all approval prompts (equivalent to --yolo)
hermes config set approvals.mode smart # recommended middle ground
hermes config set approvals.mode off # bypass everything (not recommended)
Per-invocation bypass without changing config:
hermes --yolo โฆ
export HERMES_YOLO_MODE=1
Note: YOLO / approvals.mode: off does NOT turn off secret redaction. They are independent.
Shell hooks allowlist
Some shell-hook integrations require explicit allowlisting before they fire. Managed via ~/.hermes/shell-hooks-allowlist.json โ prompted interactively the first time a hook wants to run.
Disabling the web/browser/image-gen tools
To keep the model away from network or media tools entirely, open hermes tools and toggle per-platform. Takes effect on next session (/reset). See the Tools & Skills section above.
---
Voice & Transcription
STT (Voice โ Text)
Voice messages from messaging platforms are auto-transcribed.
Provider priority (auto-detected):
1. Local faster-whisper โ free, no API key: pip install faster-whisper
2. Groq Whisper โ free tier: set GROQ_API_KEY
3. OpenAI Whisper โ paid: set VOICE_TOOLS_OPENAI_KEY
4. Mistral Voxtral โ set MISTRAL_API_KEY
Config:
stt:
enabled: true
provider: local # local, groq, openai, mistral
local:
model: base # tiny, base, small, medium, large-v3
TTS (Text โ Voice)
| Provider | Env var | Free? |
|----------|---------|-------|
| Edge TTS | None | Yes (default) |
| ElevenLabs | ELEVENLABS_API_KEY | Free tier |
| OpenAI | VOICE_TOOLS_OPENAI_KEY | Paid |
| MiniMax | MINIMAX_API_KEY | Paid |
| Mistral (Voxtral) | MISTRAL_API_KEY | Paid |
| NeuTTS (local) | None (pip install neutts[all] + espeak-ng) | Free |
Voice commands: /voice on (voice-to-voice), /voice tts (always voice), /voice off.
---
Spawning Additional Hermes Instances
Run additional Hermes processes as fully independent subprocesses โ separate sessions, tools, and environments.
When to Use This vs delegate_task
| | delegate_task | Spawning hermes process |
|-|-----------------|--------------------------|
| Isolation | Separate conversation, shared process | Fully independent process |
| Duration | Minutes (bounded by parent loop) | Hours/days |
| Tool access | Subset of parent's tools | Full tool access |
| Interactive | No | Yes (PTY mode) |
| Use case | Quick parallel subtasks | Long autonomous missions |
One-Shot Mode
terminal(command="hermes chat -q 'Research GRPO papers and write summary to ~/research/grpo.md'", timeout=300)
Background for long tasks:
terminal(command="hermes chat -q 'Set up CI/CD for ~/myapp'", background=true)
Interactive PTY Mode (via tmux)
Hermes uses prompt_toolkit, which requires a real terminal. Use tmux for interactive spawning:
Start
terminal(command="tmux new-session -d -s agent1 -x 120 -y 40 'hermes'", timeout=10)
Wait for startup, then send a message
terminal(command="sleep 8 && tmux send-keys -t agent1 'Build a FastAPI auth service' Enter", timeout=15)
Read output
terminal(command="sleep 20 && tmux capture-pane -t agent1 -p", timeout=5)
Send follow-up
terminal(command="tmux send-keys -t agent1 'Add rate limiting middleware' Enter", timeout=5)
Exit
terminal(command="tmux send-keys -t agent1 '/exit' Enter && sleep 2 && tmux kill-session -t agent1", timeout=10)
Multi-Agent Coordination
Agent A: backend
terminal(command="tmux new-session -d -s backend -x 120 -y 40 'hermes -w'", timeout=10)
terminal(command="sleep 8 && tmux send-keys -t backend 'Build REST API for user management' Enter", timeout=15)
Agent B: frontend
terminal(command="tmux new-session -d -s frontend -x 120 -y 40 'hermes -w'", timeout=10)
terminal(command="sleep 8 && tmux send-keys -t frontend 'Build React dashboard for user management' Enter", timeout=15)
Check progress, relay context between them
terminal(command="tmux capture-pane -t backend -p | tail -30", timeout=5)
terminal(command="tmux send-keys -t frontend 'Here is the API schema from the backend agent: ...' Enter", timeout=5)
Session Resume
Resume most recent session
terminal(command="tmux new-session -d -s resumed 'hermes --continue'", timeout=10)
Resume specific session
terminal(command="tmux new-session -d -s resumed 'hermes --resume 20260225_143052_a1b2c3'", timeout=10)
Tips
- Prefer
delegate_task for quick subtasks โ less overhead than spawning a full process
- Use
-w (worktree mode) when spawning agents that edit code โ prevents git conflicts
- Set timeouts for one-shot mode โ complex tasks can take 5-10 minutes
- Use
hermes chat -q for fire-and-forget โ no PTY needed
- Use tmux for interactive sessions โ raw PTY mode has
\r vs \n issues with prompt_toolkit
- For scheduled tasks, use the
cronjob tool instead of spawning โ handles delivery and retry
---
Durable & Background Systems
Four systems run alongside the main conversation loop. Quick reference
here; full developer notes live in AGENTS.md, user-facing docs under
website/docs/user-guide/features/.
Delegation (delegate_task)
Synchronous subagent spawn โ the parent waits for the child's summary
before continuing its own loop. Isolated context + terminal session.
- Single:
delegate_task(goal, context, toolsets).
- Batch:
delegate_task(tasks=[{goal, ...}, ...]) runs children in
parallel, capped by delegation.max_concurrent_children (default 3).
- Roles:
leaf (default; cannot re-delegate) vs orchestrator
(can spawn its own workers, bounded by delegation.max_spawn_depth).
- Not durable. If the parent is interrupted, the child is
cancelled. For work that must outlive the turn, use cronjob or
terminal(background=True, notify_on_complete=True).
Config: delegation.* in config.yaml.
Tuning max_concurrent_children
Default is 3. Rule of thumb for raising it:
- Light tasks (web search, file grep): up to
6-8
- Medium tasks (code execution, browser):
4-5
- Heavy tasks (builds, large data):
2-3
- Actual bottleneck is usually the API rate limit, not local CPU/RAM. On a 10-core M4 with 16GB RAM, CPU is rarely the constraint.
- Formula: start at
5, raise only if profiling shows idle time between API responses.
Cron (scheduled jobs)
Durable scheduler โ cron/jobs.py + cron/scheduler.py. Drive it via
the cronjob tool, the hermes cron CLI (list, add, edit,
pause, resume, run, remove), or the /cron slash command.
- Schedules: duration (
"30m", "2h"), "every" phrase
( "every monday 9am"), 5-field cron ( "0 9 *"), or ISO timestamp.
- Per-job knobs:
skills, model/provider override, script
(pre-run data collection; no_agent=True makes the script the whole
job), context_from (chain job A's output into job B), workdir
(run in a specific dir with its AGENTS.md / CLAUDE.md loaded),
multi-platform delivery.
- Invariants: 3-minute hard interrupt per run,
.tick.lock file
prevents duplicate ticks across processes, cron sessions pass
skip_memory=True by default, and cron deliveries are framed with a
header/footer instead of being mirrored into the target gateway
session (keeps role alternation intact).
User docs: https://hermes-agent.nousresearch.com/docs/user-guide/features/cron
Curator (skill lifecycle)
Background maintenance for agent-created skills. Tracks usage, marks
idle skills stale, archives stale ones, keeps a pre-run tar.gz backup
so nothing is lost.
- CLI:
hermes curator <verb> โ status, run, pause, resume,
pin, unpin, archive, restore, prune, backup, rollback.
- Slash:
/curator <subcommand> mirrors the CLI.
- Scope: only touches skills with
created_by: "agent" provenance.
Bundled + hub-installed skills are off-limits. Never deletes โ
max destructive action is archive. Pinned skills are exempt from
every auto-transition and every LLM review pass.
- Telemetry: sidecar at
~/.hermes/skills/.usage.json holds
per-skill use_count, view_count, patch_count,
last_activity_at, state, pinned.
Config: curator.* (enabled, interval_hours, min_idle_hours,
stale_after_days, archive_after_days, backup.*).
User docs: https://hermes-agent.nousresearch.com/docs/user-guide/features/curator
Dreaming (periodic memory/skill consolidation)
For Anthropic-style "dreaming" workflows, combine cron + session_search + memory + skills + curator into a scheduled review loop. Start with a weekly, proposal-only report that audits recent sessions, repeated user corrections, memory conflicts, skill patch candidates, and cron/automation improvements. Do not automatically delete/replace memory or patch/archive skills unless the user explicitly approves the proposed changes. See references/weekly-dreaming-routine.md for the recommended prompt, report format, safety policy, and cron creation pattern.
Kanban (multi-agent work queue)
Durable SQLite board for multi-profile / multi-worker collaboration.
Users drive it via hermes kanban <verb>; dispatcher-spawned workers
see a focused kanban_* toolset gated by HERMES_KANBAN_TASK so the
schema footprint is zero outside worker processes.
- CLI verbs (common):
init, create, list (alias ls),
show, assign, link, unlink, comment, complete, block,
unblock, archive, tail. Less common: watch, stats, runs,
log, dispatch, daemon, gc.
- Worker toolset:
kanban_show, kanban_complete, kanban_block,
kanban_heartbeat, kanban_comment, kanban_create, kanban_link.
- Dispatcher runs inside the gateway by default
( kanban.dispatch_in_gateway: true) โ reclaims stale claims,
promotes ready tasks, atomically claims, spawns assigned profiles.
Auto-blocks a task after ~5 consecutive spawn failures.
- Isolation: board is the hard boundary (workers get
HERMES_KANBAN_BOARD pinned in env); tenant is a soft namespace
within a board for workspace-path + memory-key isolation.
User docs: https://hermes-agent.nousresearch.com/docs/user-guide/features/kanban
Log Relay (Hermes โ Discord)
A background Python script that tails ~/.hermes/logs/*.log and batches lines to a Discord channel. Includes session-ID extraction, rate-limit handling, and auto-restart via launchd/systemd. Useful for remote monitoring and audit trails.
- Reference:
references/discord-log-relay.md โ full setup, tuning, macOS/Linux service install, pitfalls.
- Template:
templates/discord-log-relay.py โ copy, set CHANNEL_ID, and deploy.
- Discord operations:
references/discord-operating-planes.md โ channel-purpose routing, periodic-summary vs Dreaming report formats, and safety/cost notes for Discord-first Hermes deployments.
Key pitfall: ask the user about batch frequency upfront rather than defaulting to real-time streaming. Most users prefer 10-minute or hourly batches. High-volume raw logs should be batched, summarized, or stored out-of-band; avoid Discord message storms during error loops.
Weekly Dreaming / Memory Curation
For long-running Hermes deployments, users may want an Anthropic-style "Dreaming" loop: a scheduled review that consolidates experience, proposes memory/skill/cron changes, and identifies what to keep, weaken, archive, or delete. Hermes has the building blocks (sessions, session_search, memory, skills, curator, cron), but the safe default is proposal mode:
1. Inspect recent usage and sessions.
2. Extract repeated success patterns, failure patterns, and user corrections.
3. Propose memory updates/removals without applying them silently.
4. Propose skill patches/archive candidates and cron/reporting improvements.
5. End with explicit approval checkboxes.
Do not silently rewrite or delete memory/skills from a Dreaming report unless the user explicitly authorized automatic application. See references/discord-operating-planes.md for a report template and routing heuristics.
---
Windows-Specific Quirks
Hermes runs natively on Windows (PowerShell, cmd, Windows Terminal, git-bash
mintty, VS Code integrated terminal). Most of it just works, but a handful
of differences between Win32 and POSIX have bitten us โ document new ones
here as you hit them so the next person (or the next session) doesn't
rediscover them from scratch.
Input / Keybindings
Alt+Enter doesn't insert a newline. Windows Terminal intercepts Alt+Enter
at the terminal layer to toggle fullscreen โ the keystroke never reaches
prompt_toolkit. Use Ctrl+Enter instead. Windows Terminal delivers
Ctrl+Enter as LF ( c-j), distinct from plain Enter ( c-m / CR), and the
CLI binds c-j to newline insertion on win32 only (see
_bind_prompt_submit_keys + the Windows-only c-j binding in cli.py).
Side effect: the raw Ctrl+J keystroke also inserts a newline on Windows โ
unavoidable, because Windows Terminal collapses Ctrl+Enter and Ctrl+J to
the same keycode at the Win32 console API layer. No conflicting binding
existed for Ctrl+J on Windows, so this is a harmless side effect.
mintty / git-bash behaves the same (fullscreen on Alt+Enter) unless you
disable Alt+Fn shortcuts in Options โ Keys. Easier to just use Ctrl+Enter.
Diagnosing keybindings. Run python scripts/keystroke_diagnostic.py
(repo root) to see exactly how prompt_toolkit identifies each keystroke
in the current terminal. Answers questions like "does Shift+Enter come
through as a distinct key?" (almost never โ most terminals collapse it
to plain Enter) or "what byte sequence is my terminal sending for
Ctrl+Enter?" This is how the Ctrl+Enter = c-j fact was established.
Config / Files
HTTP 400 "No models provided" on first run. config.yaml was saved
with a UTF-8 BOM (common when Windows apps write it). Re-save as UTF-8
without BOM. hermes config edit writes without BOM; manual edits in
Notepad are the usual culprit.
execute_code / Sandbox
WinError 10106 ("The requested service provider could not be loaded
or initialized") from the sandbox child process โ it can't create an
AF_INET socket, so the loopback-TCP RPC fallback fails before
connect(). Root cause is usually not a broken Winsock LSP; it's
Hermes's own env scrubber dropping SYSTEMROOT / WINDIR / COMSPEC
from the child env. Python's socket module needs SYSTEMROOT to locate
mswsock.dll. Fixed via the _WINDOWS_ESSENTIAL_ENV_VARS allowlist in
tools/code_execution_tool.py. If you still hit it, echo os.environ
inside an execute_code block to confirm SYSTEMROOT is set. Full
diagnostic recipe in references/execute-code-sandbox-env-windows.md.
Testing / Contributing
scripts/run_tests.sh doesn't work as-is on Windows โ it looks for
POSIX venv layouts ( .venv/bin/activate). The Hermes-installed venv at
venv/Scripts/ has no pip or pytest either (stripped for install size).
Workaround: install pytest + pytest-xdist + pyyaml into a system Python
3.11 user site, then invoke pytest directly with PYTHONPATH set:
"/c/Program Files/Python311/python" -m pip install --user pytest pytest-xdist pyyaml
export PYTHONPATH="$(pwd)"
"/c/Program Files/Python311/python" -m pytest tests/foo/test_bar.py -v --tb=short -n 0
Use -n 0, not -n 4 โ pyproject.toml's default addopts already
includes -n, and the wrapper's CI-parity guarantees don't apply off POSIX.
POSIX-only tests need skip guards. Common markers already in the codebase:
- Symlinks โ elevated privileges on Windows
0o600 file modes โ POSIX mode bits not enforced on NTFS by default
signal.SIGALRM โ Unix-only (see tests/conftest.py::_enforce_test_timeout)
- Winsock / Windows-specific regressions โ
@pytest.mark.skipif(sys.platform != "win32", ...)
Use the existing skip-pattern style (sys.platform == "win32" or
sys.platform.startswith("win")) to stay consistent with the rest of the
suite.
Path / Filesystem
Line endings. Git may warn LF will be replaced by CRLF the next time
Git touches it. Cosmetic โ the repo's .gitattributes normalizes. Don't
let editors auto-convert committed POSIX-newline files to CRLF.
Forward slashes work almost everywhere. C:/Users/... is accepted by
every Hermes tool and most Windows APIs. Prefer forward slashes in code
and logs โ avoids shell-escaping backslashes in bash.
---
Troubleshooting
Voice not working
1. Check stt.enabled: true in config.yaml
2. Verify provider: pip install faster-whisper or set API key
3. In gateway: /restart. In CLI: exit and relaunch.
Tool not available
1. hermes tools โ check if toolset is enabled for your platform
2. Some tools need env vars (check .env)
3. /reset after enabling tools
Model/provider issues
1. hermes doctor โ check config and dependencies
2. hermes auth add <provider> โ re-authenticate OAuth providers (use --type oauth)
3. Check .env has the right API key
4. Copilot 403: gh auth login tokens do NOT work for Copilot API. You must use the Copilot-specific OAuth device code flow via hermes model โ GitHub Copilot.
Changes not taking effect
- Tools/skills:
/reset starts a new session with updated toolset
- Config changes: In gateway:
/restart. In CLI: exit and relaunch.
- Code changes: Restart the CLI or gateway process
Deployed web dashboard shows stale CSS or theme changes
- Browser cache: Add
?v=N cache-busting query strings to CSS/JS/theme links in HTML.
- Service Worker cache: Bump
CACHE_NAME in sw.js to invalidate old shell caches.
- Data freshness: Use
fetch(url, {cache:'no-store'}) for live JSON feeds.
- See
references/static-site-cache-invalidation.md for the full diagnostic recipe.
Skills not showing
1. hermes skills list โ verify installed
2. hermes skills config โ check platform enablement
3. Load explicitly: /skill name or hermes -s name
Gateway issues
Check logs first:
grep -i "failed to send\|error" ~/.hermes/logs/gateway.log | tail -20
Common gateway problems:
- Gateway dies on SSH logout: Enable linger:
sudo loginctl enable-linger $USER
- Gateway dies on WSL2 close: WSL2 requires
systemd=true in /etc/wsl.conf for systemd services to work. Without it, gateway falls back to nohup (dies when session closes).
- Gateway crash loop: Reset the failed state:
systemctl --user reset-failed hermes-gateway
- macOS: bot shows offline after idle time: The gateway runs as a user agent (
LimitLoadToSessionType=Aqua), so macOS suspends it when the system sleeps. The platform websocket drops and the bot appears offline until the network returns. Fix: keep the Mac awake (System Settings -> Energy -> Prevent automatic sleeping, or caffeinate -d -i -s -u &). Low Power Mode makes this worse, not better. See references/macos-gateway-sleep-disconnect.md for the full diagnostic recipe.
Platform-specific issues
- Discord bot silent: Must enable Message Content Intent in Bot โ Privileged Gateway Intents. See full Discord setup reference:
references/discord-gateway-setup.md.
- Slack bot only works in DMs: Must subscribe to
message.channels event. Without it, the bot ignores public channels.
- Windows-specific issues (
Alt+Enter newline, WinError 10106, UTF-8 BOM config, test suite, line endings): see the dedicated Windows-Specific Quirks section above.
Auxiliary models not working
If auxiliary tasks (vision, compression, session_search) fail silently, the auto provider can't find a backend. Either set OPENROUTER_API_KEY or GOOGLE_API_KEY, or explicitly configure each auxiliary task's provider:
hermes config set auxiliary.vision.provider <your_provider>
hermes config set auxiliary.vision.model <model_name>
Full system auth provisioning
For a one-shot workflow to maximize available credentials โ installing gh, generating SSH keys, configuring git, enabling all Hermes toolsets, and auditing current auth state โ see references/system-auth-setup.md.
Editing large files with patch
When a file is read with read_file(offset=...) (pagination), the tool warns that the view is partial. If you attempt patch without re-reading the full file first, you will likely hit non-unique match errors or corrupt the file. Fix: always call read_file without offset to load the whole file before patching. For append-only updates (e.g., adding a cycle log entry to state.md), terminal(command="cat >> file << 'EOF'...EOF") is a safer fallback that bypasses match-uniqueness issues entirely.
---
Windows-Specific Quirks
| Looking for... | Location |
|----------------|----------|
| Config options | hermes config edit or [Configuration docs](https://hermes-agent.nousresearch.com/docs/user-guide/configuration) |
| Available tools | hermes tools list or [Tools reference](https://hermes-agent.nousresearch.com/docs/reference/tools-reference) |
| Slash commands | /help in session or [Slash commands reference](https://hermes-agent.nousresearch.com/docs/reference/slash-commands) |
| Skills catalog | hermes skills browse or [Skills catalog](https://hermes-agent.nousresearch.com/docs/reference/skills-catalog) |
| Provider setup | hermes model or [Providers guide](https://hermes-agent.nousresearch.com/docs/integrations/providers) |
| Platform setup | hermes gateway setup or [Messaging docs](https://hermes-agent.nousresearch.com/docs/user-guide/messaging/) |
| MCP servers | hermes mcp list or [MCP guide](https://hermes-agent.nousresearch.com/docs/user-guide/features/mcp) |
| Profiles | hermes profile list or [Profiles docs](https://hermes-agent.nousresearch.com/docs/user-guide/profiles) |
| Cron jobs | hermes cron list or [Cron docs](https://hermes-agent.nousresearch.com/docs/user-guide/features/cron) |
| Memory | hermes memory status or [Memory docs](https://hermes-agent.nousresearch.com/docs/user-guide/features/memory) |
| Env variables | hermes config env-path or [Env vars reference](https://hermes-agent.nousresearch.com/docs/reference/environment-variables) |
| CLI commands | hermes --help or [CLI reference](https://hermes-agent.nousresearch.com/docs/reference/cli-commands) |
| Gateway logs | ~/.hermes/logs/gateway.log |
| Session files | ~/.hermes/sessions/ or hermes sessions browse |
| Source code | ~/.hermes/hermes-agent/ |
---
Contributor Quick Reference
For occasional contributors and PR authors. Full developer docs: https://hermes-agent.nousresearch.com/docs/developer-guide/
Project Layout
hermes-agent/
โโโ run_agent.py # AIAgent โ core conversation loop
โโโ model_tools.py # Tool discovery and dispatch
โโโ toolsets.py # Toolset definitions
โโโ cli.py # Interactive CLI (HermesCLI)
โโโ hermes_state.py # SQLite session store
โโโ agent/ # Prompt builder, context compression, memory, model routing, credential pooling, skill dispatch
โโโ hermes_cli/ # CLI subcommands, config, setup, commands
โ โโโ commands.py # Slash command registry (CommandDef)
โ โโโ config.py # DEFAULT_CONFIG, env var definitions
โ โโโ main.py # CLI entry point and argparse
โโโ tools/ # One file per tool
โ โโโ registry.py # Central tool registry
โโโ gateway/ # Messaging gateway
โ โโโ platforms/ # Platform adapters (telegram, discord, etc.)
โโโ cron/ # Job scheduler
โโโ tests/ # ~3000 pytest tests
โโโ website/ # Docusaurus docs site
Config: ~/.hermes/config.yaml (settings), ~/.hermes/.env (API keys).
Adding a Tool (3 files)
1. Create tools/your_tool.py:
import json, os
from tools.registry import registry
def check_requirements() -> bool:
return bool(os.getenv("EXAMPLE_API_KEY"))
def example_tool(param: str, task_id: str = None) -> str:
return json.dumps({"success": True, "data": "..."})
registry.register(
name="example_tool",
toolset="example",
schema={"name": "example_tool", "description": "...", "parameters": {...}},
handler=lambda args, **kw: example_tool(
param=args.get("param", ""), task_id=kw.get("task_id")),
check_fn=check_requirements,
requires_env=["EXAMPLE_API_KEY"],
)
2. Add to toolsets.py โ _HERMES_CORE_TOOLS list.
Auto-discovery: any tools/*.py file with a top-level registry.register() call is imported automatically โ no manual list needed.
All handlers must return JSON strings. Use get_hermes_home() for paths, never hardcode ~/.hermes.
Adding a Slash Command
1. Add CommandDef to COMMAND_REGISTRY in hermes_cli/commands.py
2. Add handler in cli.py โ process_command()
3. (Optional) Add gateway handler in gateway/run.py
All consumers (help text, autocomplete, Telegram menu, Slack mapping) derive from the central registry automatically.
Agent Loop (High Level)
run_conversation():
1. Build system prompt
2. Loop while iterations < max:
a. Call LLM (OpenAI-format messages + tool schemas)
b. If tool_calls โ dispatch each via handle_function_call() โ append results โ continue
c. If text response โ return
3. Context compression triggers automatically near token limit
Testing
python -m pytest tests/ -o 'addopts=' -q # Full suite
python -m pytest tests/tools/ -q # Specific area
- Tests auto-redirect
HERMES_HOME to temp dirs โ never touch real ~/.hermes/
- Run full suite before pushing any change
- Use
-o 'addopts=' to clear any baked-in pytest flags
Windows contributors: scripts/run_tests.sh currently looks for POSIX venvs ( .venv/bin/activate / venv/bin/activate) and will error out on Windows where the layout is venv/Scripts/activate + python.exe. The Hermes-installed venv at venv/Scripts/ also has no pip or pytest โ it's stripped for end-user install size. Workaround: install pytest + pytest-xdist + pyyaml into a system Python 3.11 user site ( /c/Program Files/Python311/python -m pip install --user pytest pytest-xdist pyyaml), then run tests directly:
export PYTHONPATH="$(pwd)"
"/c/Program Files/Python311/python" -m pytest tests/tools/test_foo.py -v --tb=short -n 0
Use -n 0 (not -n 4) because pyproject.toml's default addopts already includes -n, and the wrapper's CI-parity story doesn't apply off-POSIX.
Cross-platform test guards: tests that use POSIX-only syscalls need a skip marker. Common ones already in the codebase:
- Symlink creation โ
@pytest.mark.skipif(sys.platform == "win32", reason="Symlinks require elevated privileges on Windows") (see tests/cron/test_cron_script.py)
- POSIX file modes (0o600, etc.) โ
@pytest.mark.skipif(sys.platform.startswith("win"), reason="POSIX mode bits not enforced on Windows") (see tests/hermes_cli/test_auth_toctou_file_modes.py)
signal.SIGALRM โ Unix-only (see tests/conftest.py::_enforce_test_timeout)
- Live Winsock / Windows-specific regression tests โ
@pytest.mark.skipif(sys.platform != "win32", reason="Windows-specific regression")
Monkeypatching sys.platform is not enough when the code under test also calls platform.system() / platform.release() / platform.mac_ver(). Those functions re-read the real OS independently, so a test that sets sys.platform = "linux" on a Windows runner will still see platform.system() == "Windows" and route through the Windows branch. Patch all three together:
monkeypatch.setattr(sys, "platform", "linux")
monkeypatch.setattr(platform, "system", lambda: "Linux")
monkeypatch.setattr(platform, "release", lambda: "6.8.0-generic")
See tests/agent/test_prompt_builder.py::TestEnvironmentHints for a worked example.
Extending the system prompt's execution-environment block
Factual guidance about the host OS, user home, cwd, terminal backend, and shell (bash vs. PowerShell on Windows) is emitted from agent/prompt_builder.py::build_environment_hints(). This is also where the WSL hint and per-backend probe logic live. The convention:
- Local terminal backend โ emit host info (OS,
$HOME, cwd) + Windows-specific notes (hostname โ username, terminal uses bash not PowerShell).
- Remote terminal backend (anything in
_REMOTE_TERMINAL_BACKENDS: docker, singularity, modal, daytona, ssh, vercel_sandbox, managed_modal) โ suppress host info entirely and describe only the backend. A live uname/whoami/pwd probe runs inside the backend via tools.environments.get_environment(...).execute(...), cached per process in _BACKEND_PROBE_CACHE, with a static fallback if the probe times out.
- Key fact for prompt authoring: when
TERMINAL_ENV != "local", every file tool (read_file, write_file, patch, search_files) runs inside the backend container, not on the host. The system prompt must never describe the host in that case โ the agent can't touch it.
Full design notes, the exact emitted strings, and testing pitfalls:
references/prompt-builder-environment-hints.md.
Refactor-safety pattern (POSIX-equivalence guard): when you extract inline logic into a helper that adds Windows/platform-specific behavior, keep a _legacy_<name> oracle function in the test file that's a verbatim copy of the old code, then parametrize-diff against it. Example: tests/tools/test_code_execution_windows_env.py::TestPosixEquivalence. This locks in the invariant that POSIX behavior is bit-for-bit identical and makes any future drift fail loudly with a clear diff.
Commit Conventions
type: concise subject line
Optional body.
Types: fix:, feat:, refactor:, docs:, chore:
Key Rules
- Never break prompt caching โ don't change context, tools, or system prompt mid-conversation
- Message role alternation โ never two assistant or two user messages in a row
- Use
get_hermes_home() from hermes_constants for all paths (profile-safe)
- Config values go in
config.yaml, secrets go in .env
- New tools need a
check_fn so they only appear when requirements are met
[IMPORTANT: The user has invoked the "kanban-orchestrator" skill, indicating they want you to follow its instructions. The full skill content is loaded below.]
---
name: kanban-orchestrator
description: Decomposition playbook + anti-temptation rules for an orchestrator profile routing work through Kanban. The "don't do the work yourself" rule and the basic lifecycle are auto-injected into every kanban worker's system prompt; this skill is the deeper playbook when you're specifically playing the orchestrator role.
version: 3.0.0
platforms: [linux, macos, windows]
metadata:
hermes:
tags: [kanban, multi-agent, orchestration, routing]
related_skills: [kanban-worker]
---
Kanban Orchestrator โ Decomposition Playbook
> The core worker lifecycle (including the kanban_create fan-out pattern and the "decompose, don't execute" rule) is auto-injected into every kanban process via the KANBAN_GUIDANCE system-prompt block. This skill is the deeper playbook when you're an orchestrator profile whose whole job is routing.
Profiles are user-configured โ not a fixed roster
Hermes setups vary widely. Some users run a single profile that does everything; some run a small fleet (docker-worker, cron-worker); some run a curated specialist team they've named themselves. There is no default specialist roster โ the orchestrator skill does not know what profiles exist on this machine.
Before fanning out, you must ground the decomposition in the profiles that actually exist. The dispatcher silently fails to spawn unknown assignee names โ it doesn't autocorrect, doesn't suggest, doesn't fall back. So a card assigned to researcher on a setup that only has docker-worker just sits in ready forever.
Step 0: discover available profiles before planning.
Use one of these:
hermes profile list โ prints the table of profiles configured on this machine. Run it through your terminal tool if you have one; otherwise ask the user.
kanban_list(assignee="<some-name>") โ sanity-check a single name. Returns an empty list (rather than an error) for an unknown assignee, so this only confirms a name you're already considering.
- Just ask the user. "What profiles do you have set up?" is a fine first turn when the goal needs more than one specialist.
Cache the result in your working memory for the rest of the conversation. Re-asking every turn wastes a tool call.
When to use the board (vs. just doing the work)
Create Kanban tasks when any of these are true:
1. Multiple specialists are needed. Research + analysis + writing is three profiles.
2. The work should survive a crash or restart. Long-running, recurring, or important.
3. The user might want to interject. Human-in-the-loop at any step.
4. Multiple subtasks can run in parallel. Fan-out for speed.
5. Review / iteration is expected. A reviewer profile loops on drafter output.
6. The audit trail matters. Board rows persist in SQLite forever.
If none of those apply โ it's a small one-shot reasoning task โ use delegate_task instead or answer the user directly.
The anti-temptation rules
Your job description says "route, don't execute." The rules that enforce that:
- Do not execute the work yourself. Your restricted toolset usually doesn't even include terminal/file/code/web for implementation. If you find yourself "just fixing this quickly" โ stop and create a task for the right specialist.
- For any concrete task, create a Kanban task and assign it. Every single time.
- Split multi-lane requests before creating cards. A user prompt can contain several independent workstreams. Extract those lanes first, then create one card per lane instead of bundling unrelated work into a single implementer card.
- Run independent lanes in parallel. If two cards do not need each other's output, leave them unlinked so the dispatcher can fan them out. Link only true data dependencies.
- If no specialist fits the available profiles, ask the user which profile to create or which existing profile to use. Do not invent profile names; the dispatcher will silently drop unknown assignees.
- Decompose, route, and summarize โ that's the whole job.
Exception: micro-UI polish cycles
There is one narrow exception where the orchestrator may execute directly instead of creating Kanban cards: tiny UI-only polish cycles (e.g., adding a CSS class, a theme preview dot, a hover state, a cross-link, or a HUD button) that are purely presentational, require no cross-file logic changes, and fit comfortably inside a single bounded cycle with no need for review or parallel work. If the change is limited to HTML/CSS/JS cosmetics, no other profile has a stake in it, and the user did not ask for a design review, the orchestrator should just edit and publish rather than paying the kanban-overhead tax. This exception does NOT apply to architecture changes, adapter logic, plugin interfaces, or anything that touches the data layer.
Decomposition playbook
Step 1 โ Understand the goal
Ask clarifying questions if the goal is ambiguous. Cheap to ask; expensive to spawn the wrong fleet.
Step 2 โ Sketch the task graph
Before creating anything, draft the graph out loud (in your response to the user). Treat every concrete workstream as a candidate card:
1. Extract the lanes from the request.
2. Map each lane to one of the profiles you discovered in Step 0. If a lane doesn't fit any existing profile, ask the user which to use or create.
3. Decide whether each lane is independent or gated by another lane.
4. Create independent lanes as parallel cards with no parent links.
5. Create synthesis/review/integration cards with parent links to the lanes they depend on.
Examples of prompts that should fan out (using placeholder profile names โ substitute whatever exists on the user's setup):
- "Build an app" โ one card to a design-oriented profile for product/UI direction, one or two cards to engineering profiles for implementation, plus a later integration/review card if the user has a reviewer profile.
- "Fix blockers and check model variants" โ one implementation card for the blocker fixes plus one discovery/research card for config/source verification. A final reviewer card can depend on both.
- "Research docs and implement" โ a docs-research card can run in parallel with a codebase-discovery card; implementation waits only if it truly needs those findings.
- "Analyze this screenshot and find the related code" โ one card to a vision-capable profile for the visual analysis while another searches the codebase.
Words like "also," "finally," or "and" do not automatically imply a dependency. They often mean "make sure this is covered before reporting back." Only link tasks when one card cannot start until another card's output exists.
Show the graph to the user before creating cards. Let them correct it โ including which actual profile name should own each lane.
Step 3 โ Create tasks and link
Use the profile names from Step 0. The example below uses placeholders <profile-A>, <profile-B>, <profile-C> โ replace them with what the user actually has.
t1 = kanban_create(
title="research: Postgres cost vs current",
assignee="<profile-A>", # whichever profile handles research on this setup
body="Compare estimated infrastructure costs, migration costs, and ongoing ops costs over a 3-year window. Sources: AWS/GCP pricing, team time estimates, current Postgres bills from peers.",
tenant=os.environ.get("HERMES_TENANT"),
)["task_id"]
t2 = kanban_create(
title="research: Postgres performance vs current",
assignee="<profile-A>", # same profile, run in parallel
body="Compare query latency, throughput, and scaling characteristics at our expected data volume (~500GB, 10k QPS peak). Sources: benchmark papers, public case studies, pgbench results if easy.",
)["task_id"]
t3 = kanban_create(
title="synthesize migration recommendation",
assignee="<profile-B>", # whichever profile does synthesis/analysis
body="Read the findings from T1 (cost) and T2 (performance). Produce a 1-page recommendation with explicit trade-offs and a go/no-go call.",
parents=[t1, t2],
)["task_id"]
t4 = kanban_create(
title="draft decision memo",
assignee="<profile-C>", # whichever profile drafts user-facing prose
body="Turn the analyst's recommendation into a 2-page memo for the CTO. Match the tone of previous decision memos in the team's knowledge base.",
parents=[t3],
)["task_id"]
parents=[...] gates promotion โ children stay in todo until every parent reaches done, then auto-promote to ready. No manual coordination needed; the dispatcher and dependency engine handle it.
Step 4 โ Complete your own task
If you were spawned as a task yourself (e.g. a planner profile was assigned T0: "investigate Postgres migration"), mark it done with a summary of what you created:
kanban_complete(
summary="decomposed into T1-T4: 2 research lanes in parallel, 1 synthesis on their outputs, 1 prose draft on the recommendation",
metadata={
"task_graph": {
"T1": {"assignee": "<profile-A>", "parents": []},
"T2": {"assignee": "<profile-A>", "parents": []},
"T3": {"assignee": "<profile-B>", "parents": ["T1", "T2"]},
"T4": {"assignee": "<profile-C>", "parents": ["T3"]},
},
},
)
Step 5 โ Report back to the user
Tell them what you created in plain prose, naming the actual profiles you used:
> I've queued 4 tasks:
> - T1 (<profile-A>): cost comparison
> - T2 (<profile-A>): performance comparison, in parallel with T1
> - T3 (<profile-B>): synthesizes T1 + T2 into a recommendation
> - T4 (<profile-C>): turns T3 into a CTO memo
>
> The dispatcher will pick up T1 and T2 now. T3 starts when both finish. You'll get a gateway ping when T4 completes. Use the dashboard or hermes kanban tail <id> to follow along.
Common patterns
Fan-out + fan-in (research โ synthesize): N research-style cards with no parents, one synthesis card with all of them as parents.
Parallel implementation + validation: one implementer card makes the change while one explorer/researcher card verifies config, docs, or source mapping. A reviewer card can depend on both. Do not make the implementer own unrelated verification just because the user mentioned both in one sentence.
Pipeline with gates: planner โ implementer โ reviewer. Each stage's parents=[previous_task]. Reviewer blocks or completes; if reviewer blocks, the operator unblocks with feedback and respawns.
Same-profile queue: N tasks, all assigned to the same profile, no dependencies between them. Dispatcher serializes โ that profile processes them in priority order, accumulating experience in its own memory.
Parallel UI/frontend lanes: When the goal touches multiple independent HTML/CSS/JS files (e.g., a dashboard page and a 2D gather view), fan out to separate subagents per file. Each lane edits its own file, then the orchestrator integrates, fixes cross-file references (theme paths, shared JSON endpoints), and publishes. This avoids merge conflicts in single-file HTML dashboards and keeps each subagent's context focused. See references/parallel-ui-lanes-and-publishing.md for the post-subagent integration checklist and rsync safety notes.
Human-in-the-loop: Any task can kanban_block() to wait for input. Dispatcher respawns after /unblock. The comment thread carries the full context.
Pitfalls
Inventing profile names that don't exist. The dispatcher silently fails to spawn unknown assignees โ the card just sits in ready forever. Always assign to a profile from your Step 0 discovery; ask the user if you're unsure.
Bundling independent lanes into one card. If the user asks for two independent outcomes, create two cards. Example: "fix blockers and check model variants" is not one fixer task; create a fixer/engineer card for the fixes and an explorer/researcher card for the variant check, then optionally gate review on both.
Over-linking because of wording. "Finally check X" may still be parallel with implementation if X is static config, docs, or source discovery. Link it after implementation only when the check depends on the implementation result.
Forgetting dependency links. If the task graph says research -> implement -> review, do not create all tasks as independent ready cards. Use parent links so implement/review cannot run before their inputs exist.
Reassignment vs. new task. If a reviewer blocks with "needs changes," create a NEW task linked from the reviewer's task โ don't re-run the same task with a stern look. The new task is assigned to the original implementer profile.
Argument order for links. kanban_link(parent_id=..., child_id=...) โ parent first. Mixing them up demotes the wrong task to todo.
Ignoring explicit user feedback to keep building infrastructure. When the user says a specific UX issue (legibility, theme switching, movement density) is "immediate priority," treat it as P0 and route it before deeper packaging/architecture work. Infrastructure polish feels productive, but shipping user-visible fixes is what matters. Create cards for the UX feedback first, then resume infrastructure lanes.
Treating status: complete as immutable when user feedback says otherwise. A state.md that says status: complete does not override a user's report that a completion criterion is actually broken. If the user says "theme switching is not working" and the Final Completion Condition requires "working UI theme switcher," the mission is not complete. Reactivate immediately: set status: active, append a reactivation cycle log, and fix the issue. Do not burn cycles on post-complete verification while the user is reporting active defects.
Don't pre-create the whole graph if the shape depends on intermediate findings. If T3's structure depends on what T1 and T2 find, let T3 exist as a "synthesize findings" task whose own first step is to read parent handoffs and plan the rest. Orchestrators can spawn orchestrators.
Tenant inheritance. If HERMES_TENANT is set in your env, pass tenant=os.environ.get("HERMES_TENANT") on every kanban_create call so child tasks stay in the same namespace.
Verifying cross-file references after directory reorganization. When subagents edit HTML/CSS/JS files and the directory structure shifts (e.g., moving files from root into web/dashboard/ and web/gather/), relative asset paths ( themes/default/theme.css, ./ops-data.json) often break. After subagents finish, the orchestrator must grep for href= and src= in moved files and fix relative paths before publishing. Subagents don't know the final publish layout โ the orchestrator does.
Destructive sync wipes needed files. Commands like rsync -av --delete will delete destination files that aren't in the source list. If you publish a directory tree piecemeal (e.g., copy web/dashboard/ first, then web/gather/ separately), --delete on the first rsync will erase the gather files before the second rsync runs. Either list all source paths in a single rsync invocation, or omit --delete and use cp -r / rsync -av without deletion when doing staged copies.
Recovering stuck workers
When a worker profile keeps crashing, hallucinating, or getting blocked by its own mistakes (usually: wrong model, missing skill, broken credential), the kanban dashboard flags the task with a โ badge and opens a Recovery section in the drawer. Three primary actions:
1. Reclaim (or hermes kanban reclaim <task_id>) โ abort the running worker immediately and reset the task to ready. The existing claim TTL is ~15 min; this is the fast path out.
2. Reassign (or hermes kanban reassign <task_id> <new-profile> --reclaim) โ switch the task to a different profile (one that exists on this setup) and let the dispatcher pick it up with a fresh worker.
3. Change profile model โ the dashboard prints a copy-paste hint for hermes -p <profile> model since profile config lives on disk; edit it in a terminal, then Reclaim to retry with the new model.
Hallucination warnings appear on tasks where a worker's kanban_complete(created_cards=[...]) claim included card ids that don't exist or weren't created by the worker's profile (the gate blocks the completion), or where the free-form summary references t_<hex> ids that don't resolve (advisory prose scan, non-blocking). Both produce audit events that persist even after recovery actions โ the trail stays for debugging.
The user has provided the following instruction alongside the skill invocation: [IMPORTANT: You are running as a scheduled cron job. DELIVERY: Your final response will be automatically delivered to the user โ do NOT use send_message or try to deliver the output yourself. Just produce your report/output as your final response and the system handles the rest. SILENT: If there is genuinely nothing new to report, respond with exactly "[SILENT]" (nothing else) to suppress delivery. Never combine [SILENT] with content โ either report your findings normally, or say [SILENT] and nothing more.]
You are the 15-minute Orchestrator for Son's Autonomous Agent Lab v1, reporting to Discord channel ID 1505805763824586952.
Durable state path: /Users/jooho-hermes/.hermes/autonomous-agent-lab/state.md
Working directory for experiment artifacts: /Users/jooho-hermes/.hermes/autonomous-agent-lab/
Preferred published web root: /Users/jooho-hermes/hermes-web/agent-pets/
Top-level directive from Son:
- The project has evolved from a personal dashboard into an INSTALLABLE PRODUCT that external Hermes users can deploy.
- The final target is a self-contained, configurable, publishable solution: "Hermes Pixel Pet Ops Office".
- Do NOT shrink the mission into a small static MVP and autonomously stop.
- The Gather.town-style 2D spatial office is a first-class feature, not a side page.
Latest UX feedback from Son (treat as immediate priority before deeper packaging work):
- Details are hard for a human to understand. Add human-first summaries, plain-language labels, and progressive disclosure: summary first, technical details second.
- Gather Town version has too many agents roaming around. Reduce default movement, add density/speed controls, cluster agents by room/task, and add focus/calm mode.
- Theme switching is not visibly working. Implement real UI theme switcher with persistence and clear visual theme changes.
Key product requirements (installable solution level):
1. Config-driven architecture: all paths, URLs, colors, names, room layouts via config.yaml. No hardcoded references to jooho-hermes.
2. Self-contained package: clear directory structure (src/, web/, config/, docs/, scripts/), install script, requirements.txt.
3. Pluggable data adapter: support multiple backends via plugin architecture.
4. Themeable frontend: CSS variables driven from config, swappable themes, plus a working UI theme switcher.
5. Multi-tenant ready: works for any Hermes instance.
6. Build/Deploy ready: Dockerfile or docker-compose, or clear static-server setup.
7. Documentation: README, architecture docs, configuration reference, contributor guide.
8. Human-comprehensible UX: plain-language summaries and progressive disclosure for technical detail.
9. Gather.town calm mode: adjustable movement density/speed and less chaotic defaults.
10. Versioned releases: CHANGELOG.md, semantic versioning, release packaging.
Mission model:
- Read state.md first before doing anything else.
- If state.md says
status: inactive or has no Current Mission, do not invent work. Return exactly: ๐ก Autonomous Agent Lab ๋๊ธฐ์ค โ Son์ด ํธ๋ฆฌ๊ฑฐ/๋ฏธ์
์ ์ฃผ๋ฉด 15๋ถ ์ฌ์ดํด์ ์์ํฉ๋๋ค.
- If state.md says
status: active, run one bounded 15-minute cycle toward the full installable solution.
- If state.md says
status: complete, verify that the Final Completion Condition in state.md is truly met. If it is not fully met, reactivate or report that state needs correction.
Cycle procedure when active:
1. Read state.md first. Extract current mission, constraints, previous cycle log, and Final Completion Condition.
2. Decide the next smallest useful step toward installable solution quality. Focus on: architecture, configurability, documentation, and clean separation of concerns.
3. Use delegate_task for independent subagent lanes when helpful.
4. Prefer concrete progress: refactor to config-driven, add install scripts, create docs, add Docker support, theme system, plugin architecture.
5. Update state.md with a new cycle log entry before final reporting.
6. Completion rule: only set status: complete when every item under state.md Final Completion Condition is satisfied. A non-installable MVP is not complete.
7. Stop/block only if Son explicitly stops/redirects, a safety boundary is reached, or a hard blocker needs Son's decision.
Link requirement (never forget):
- Every cycle report MUST include at least one direct viewable link to the published dashboard/artifact.
- The canonical URL:
http://hermes-mac-mini.tail46b3c6.ts.net:8099/agent-pets/
- Include gather town URL too:
http://hermes-mac-mini.tail46b3c6.ts.net:8099/agent-pets/gather/
Final Discord message format:
[Autonomous Agent Lab v1 / Cycle N]
๋ชฉํ:
์ํ:
๊ฒฐ๊ณผ:
๊ฒ์ฆ:
๋ค์:
์ํ:
Safety/quality rules:
- Do not handle secrets, passwords, API keys, payment, permission dialogs, or destructive commands.
- Do not claim completion without updating state.md.
- Do not rely on Discord history as durable state.
- Do not spam raw logs; summarize lane outputs and verification.
- Keep working in /Users/jooho-hermes/.hermes/autonomous-agent-lab/ and publish only to /Users/jooho-hermes/hermes-web/agent-pets/ unless the state file says otherwise.
Design/UX priorities:
- Mobile responsiveness is first-class.
- Character animation/movement is desired.
- Every cycle report must include published links.
- This is now a product engineering mission. Architecture, configurability, and documentation matter as much as visuals.
Response
[Autonomous Agent Lab v1 / Cycle 54]
๋ชฉํ:
Son์ UX ํผ๋๋ฐฑ(ํ
๋ง ๋ฏธ์ ์ฉ, Gather Town ํผ์ก, ์์ด์ ํธ ์ ๋ณด ๋ํด)์ ๋ฃจํธ ์์ธ๋ถํฐ ํด๊ฒฐ. ๋ธ๋ผ์ฐ์ /Service Worker ์บ์ ๋ฌธ์ , Gather ์๊ฐ์ ๋ฐ๋, ์ธ์คํํฐ ๊ธฐ์ ์ฉ์ด ๊ณผ๋ค๋ฅผ ์ง์ ์์ .
์ํ:
1. ๊ฐ์ ์บ์ ๋ฌดํจํ (Cache Busting)
- ๋ชจ๋ HTML/CSS/JS ๋งํฌ
?v=53 โ ?v=54๋ก ๋ฒ์ ์
- Service Worker
CACHE_NAME์ pixel-pet-ops-v6 โ v7๋ก ๋ณ๊ฒฝ
sw.js์ SHELL_FILES์๋ ?v=54 ์ฟผ๋ฆฌ์คํธ๋ง ์ ์ฉ โ ๊ธฐ์กด ์บ์ ์์ purge
2. Gather Town ๋ ์กฐ์ฉํ๊ฒ
- ํ์ ์์ด์ ํธ ์ํ: 16 โ 8๊ฐ๋ก ์ถ์
- ์ด๋ ์๋ ๋ฐฐ์จ: slow
0.35 โ 0.25, normal 1.0 โ 0.7, fast 1.8 โ 1.4
- tick ๋ฐ๋: sparse
0.08 โ 0.04, normal 0.4 โ 0.2, busy 0.85 โ 0.6
3. ๋์๋ณด๋ ์ธ์คํํฐ ์ธ๊ฐ ์ค์ฌ ๊ฐํธ
- ๊ธฐ๋ณธ ํ๋ฉด์์ "์์
์ ํธยท์ ํธ ์ค๋ช
ยท๋ฐ์ดํฐ ์ถ์ฒ" ๋ฑ ๊ธฐ์ ํญ๋ชฉ ์ ๋ถ ์ ๊ฑฐ
- ๊ธฐ๋ณธ ๋ณด๊ธฐ: ์ด๋ฆ / ํค๋๋ผ์ธ / ํ์๋ผ์ธ / "์ง๊ธ ํ๋ ์ผ" / "์ ์ค์ํ๊ฐ" / ์๊ฐ์ ์งํ ๋ง๋
- ๋ชจ๋ ๊ธฐ์ ์์ธ๋ "๊ธฐ์ ์์ธ ๋ณด๊ธฐ" ํ ๊ธ ๋ค๋ก ์ด๋
4. ํ
์คํธ ๋ณด๊ฐ: scripts/test.sh Gather Town ํ
๋ง ๋งํฌ ์ ๊ท์์ ?v=N ํ์ฉํ๋๋ก ์์
๊ฒฐ๊ณผ:
- ํตํฉ ํ
์คํธ 99/99 ํต๊ณผ
- ์ค์น ๊ฒ์ฆ 21/21 ํต๊ณผ
ops-data.json ์คํค๋ง 1.4, 32 agents, 16 events, health.json = healthy
- LaunchAgent
refresh.out.log ์ ์, refresh.err.log ๋น์ด ์์
- ๋ชจ๋ ํผ๋ธ๋ฆฌ์ฑ ์์
?v=54 ์ ์ฉ ์๋ฃ
๊ฒ์ฆ:
- ํผ๋ธ๋ฆฌ์๋ HTML/JS/CSS/SW ํ์ผ์์
v=54 ๋ฐ CACHE_NAME=v7 ํ์ธ
gather.js์์ slice(0, 8) ๋ฐ ์ถ์๋ density/speed ๊ฐ ํ์ธ
dashboard.js ์ธ์คํํฐ์์ ๊ธฐ์ ์ฉ์ด ์น์
์ ๊ฑฐ, human-first ๊ธฐ๋ณธ ํ๋ฉด ํ์ธ
๋ค์:
- Son์ ๋ธ๋ผ์ฐ์ ์์ ๋ฐ๋์ Cmd+Shift+R (ํ๋ ๋ฆฌํ๋ ์)๋ฅผ ์คํํ์ฌ ๊ธฐ์กด Service Worker/๋ธ๋ผ์ฐ์ ์บ์๋ฅผ ์์ ํ ์ ๊ฑฐํด ์ฃผ์ธ์.
?v=54์ CACHE_NAME=v7 ๋ณ๊ฒฝ์ ์ด ์กฐ์น ์์ด๋ ์๊ฐ์ ์ผ๋ก ๋ฐ์๋์ง ์์ ์ ์์ต๋๋ค.
- Gather Town์ด ์ฌ์ ํ ๋ณต์กํ๊ฒ ๋๊ปด์ง๋ฉด "Zen mode"(owner + ํ์ฑ ์์ด์ ํธ 1๊ฐ๋ง ํ์)๋ฅผ ์ถ๊ฐํ ์ ์์ต๋๋ค.
- ํ
๋ง ์ ํ์ด ์ฌ์ ํ ๋ณด์ด์ง ์์ผ๋ฉด Service Worker ๊ฐ์ ํด์ ๋ฒํผ์ UI์ ์ถ๊ฐํ๊ฒ ์ต๋๋ค.
์ํ: ๐ข active โ Son์ ํ์ธ ๋ฐ ๋ธ๋ผ์ฐ์ ํ๋ ๋ฆฌํ๋ ์ ๋๊ธฐ ์ค
๋์๋ณด๋: http://hermes-mac-mini.tail46b3c6.ts.net:8099/agent-pets/
Gather Town: http://hermes-mac-mini.tail46b3c6.ts.net:8099/agent-pets/gather/
|
| 2026-05-19 13-36-05 |
79,739 chars |
2026-05-19_13-36-05.md |
Cron Job: autonomous-agent-lab-v1-orchestrator (FAILED)
Job ID: 35127ff89556
Run Time: 2026-05-19 13:36:05
Schedule: every 15m
Prompt
[IMPORTANT: The user has invoked the "hermes-agent" skill, indicating they want you to follow its instructions. The full skill content is loaded below.]
---
name: hermes-agent
description: "Configure, extend, or contribute to Hermes Agent."
version: 2.1.0
author: Hermes Agent + Teknium
license: MIT
platforms: [linux, macos, windows]
metadata:
hermes:
tags: [hermes, setup, configuration, multi-agent, spawning, cli, gateway, development]
homepage: https://github.com/NousResearch/hermes-agent
related_skills: [claude-code, codex, opencode]
---
Hermes Agent
Hermes Agent is an open-source AI agent framework by Nous Research that runs in your terminal, messaging platforms, and IDEs. It belongs to the same category as Claude Code (Anthropic), Codex (OpenAI), and OpenClaw โ autonomous coding and task-execution agents that use tool calling to interact with your system. Hermes works with any LLM provider (OpenRouter, Anthropic, OpenAI, DeepSeek, local models, and 15+ others) and runs on Linux, macOS, and WSL.
What makes Hermes different:
- Self-improving through skills โ Hermes learns from experience by saving reusable procedures as skills. When it solves a complex problem, discovers a workflow, or gets corrected, it can persist that knowledge as a skill document that loads into future sessions. Skills accumulate over time, making the agent better at your specific tasks and environment.
- Persistent memory across sessions โ remembers who you are, your preferences, environment details, and lessons learned. Pluggable memory backends (built-in, Honcho, Mem0, and more) let you choose how memory works.
- Multi-platform gateway โ the same agent runs on Telegram, Discord, Slack, WhatsApp, Signal, Matrix, Email, and 10+ other platforms with full tool access, not just chat.
- Provider-agnostic โ swap models and providers mid-workflow without changing anything else. Credential pools rotate across multiple API keys automatically.
- Profiles โ run multiple independent Hermes instances with isolated configs, sessions, skills, and memory.
- Extensible โ plugins, MCP servers, custom tools, webhook triggers, cron scheduling, and the full Python ecosystem.
People use Hermes for software development, research, system administration, data analysis, content creation, home automation, and anything else that benefits from an AI agent with persistent context and full system access.
This skill helps you work with Hermes Agent effectively โ setting it up, configuring features, spawning additional agent instances, troubleshooting issues, finding the right commands and settings, and understanding how the system works when you need to extend or contribute to it.
Docs: https://hermes-agent.nousresearch.com/docs/
Quick Start
Install
curl -fsSL https://raw.githubusercontent.com/NousResearch/hermes-agent/main/scripts/install.sh | bash
Interactive chat (default)
hermes
Single query
hermes chat -q "What is the capital of France?"
Setup wizard
hermes setup
Change model/provider
hermes model
Check health
hermes doctor
---
CLI Reference
Global Flags
hermes [flags] [command]
--version, -V Show version
--resume, -r SESSION Resume session by ID or title
--continue, -c [NAME] Resume by name, or most recent session
--worktree, -w Isolated git worktree mode (parallel agents)
--skills, -s SKILL Preload skills (comma-separate or repeat)
--profile, -p NAME Use a named profile
--yolo Skip dangerous command approval
--pass-session-id Include session ID in system prompt
No subcommand defaults to chat.
Chat
hermes chat [flags]
-q, --query TEXT Single query, non-interactive
-m, --model MODEL Model (e.g. anthropic/claude-sonnet-4)
-t, --toolsets LIST Comma-separated toolsets
--provider PROVIDER Force provider (openrouter, anthropic, nous, etc.)
-v, --verbose Verbose output
-Q, --quiet Suppress banner, spinner, tool previews
--checkpoints Enable filesystem checkpoints (/rollback)
--source TAG Session source tag (default: cli)
Configuration
hermes setup [section] Interactive wizard (model|terminal|gateway|tools|agent)
hermes model Interactive model/provider picker
hermes config View current config
hermes config edit Open config.yaml in $EDITOR
hermes config set KEY VAL Set a config value
hermes config path Print config.yaml path
hermes config env-path Print .env path
hermes config check Check for missing/outdated config
hermes config migrate Update config with new options
hermes doctor [--fix] Check dependencies and config
Credential Pools
hermes auth add Interactive credential wizard (oauth, api-key)
hermes auth list [PROVIDER] List pooled credentials
hermes auth remove P INDEX Remove by provider + index
hermes auth reset PROVIDER Clear exhaustion status
hermes logout Clear stored auth
Tools & Skills
hermes tools Interactive tool enable/disable (curses UI)
hermes tools list Show all tools and status
hermes tools enable NAME Enable a toolset
hermes tools disable NAME Disable a toolset
hermes skills list List installed skills
hermes skills search QUERY Search the skills hub
hermes skills install ID Install a skill (ID can be a hub identifier OR a direct https://โฆ/SKILL.md URL; pass --name to override when frontmatter has no name)
hermes skills inspect ID Preview without installing
hermes skills config Enable/disable skills per platform
hermes skills check Check for updates
hermes skills update Update outdated skills
hermes skills uninstall N Remove a hub skill
hermes skills publish PATH Publish to registry
hermes skills browse Browse all available skills
hermes skills tap add REPO Add a GitHub repo as skill source
MCP Servers
hermes mcp serve Run Hermes as an MCP server
hermes mcp add NAME Add an MCP server (--url or --command)
hermes mcp remove NAME Remove an MCP server
hermes mcp list List configured servers
hermes mcp test NAME Test connection
hermes mcp configure NAME Toggle tool selection
Gateway (Messaging Platforms)
hermes gateway run Start gateway foreground
hermes gateway install Install as background service
hermes gateway start/stop Control the service
hermes gateway restart Restart the service
hermes gateway status Check status
hermes gateway setup Configure platforms
Supported platforms: Telegram, Discord, Slack, WhatsApp, Signal, Email, SMS, Matrix, Mattermost, Home Assistant, DingTalk, Feishu, WeCom, BlueBubbles (iMessage), Weixin (WeChat), API Server, Webhooks. Open WebUI connects via the API Server adapter.
Platform docs: https://hermes-agent.nousresearch.com/docs/user-guide/messaging/
Discord-specific walkthrough (token, intents, service install, access control): see references/discord-gateway-setup.md in this skill.
- Per-channel personas and skill bindings: see
references/gateway-channel-personas.md (works on Discord, Slack, Telegram, Mattermost, Matrix).
- For long-running Discord-first operations, purpose-specific channel routing, periodic summaries, weekly Dreaming/audit reports, and log-safety patterns: see
references/discord-operating-planes.md.
- For broad Hermes/LifeOS/SQAF ecosystem audits (cron inventory, live services, dashboards, provider/model warnings, and control-plane gaps), see
references/ecosystem-audit.md.
Sessions
hermes sessions list List recent sessions
hermes sessions browse Interactive picker
hermes sessions export OUT Export to JSONL
hermes sessions rename ID T Rename a session
hermes sessions delete ID Delete a session
hermes sessions prune Clean up old sessions (--older-than N days)
hermes sessions stats Session store statistics
For browser-based viewing of existing Hermes CLI/Discord/cron session transcripts, prefer a lightweight static export from ~/.hermes/state.db into a private web root instead of assuming Open WebUI can browse Hermes' native session store. See references/hermes-session-static-web-viewer.md for the SQLite schema, static HTML export workflow, redaction/truncation cautions, and the user's Mac mini deployment (/hermes-sessions/ under the Tailscale-only ~/hermes-web site).
For cron job execution history, the same static-export pattern applies to ~/.hermes/cron/jobs.json and ~/.hermes/cron/output/{job_id}/*.md. See references/cron-history-web-viewer.md for the cron data model, schedule-dict pitfall, and the user's deployed /cron-history/ dashboard.
Cron Jobs
hermes cron list List jobs (--all for disabled)
hermes cron create SCHED Create: '30m', 'every 2h', '0 9 *'
hermes cron edit ID Edit schedule, prompt, delivery
hermes cron pause/resume ID Control job state
hermes cron run ID Trigger on next tick
hermes cron remove ID Delete a job
hermes cron status Scheduler status
For bounded autonomous lab/orchestrator cron jobs that use file-based state, subagent lanes, artifact publishing, and status transitions (active โ complete/blocked/inactive), see references/autonomous-agent-lab-cron-cycle.md. A reusable verification script template lives at scripts/verify-completion-template.py.
For a worked example of evolving an autonomous lab into a config-driven, themeable, Docker-ready installable product, see references/autonomous-lab-product-architecture.md. For CI, integration testing, pluggable adapter architecture, bounded cycle orchestration, and post-productization patterns, see references/product-maturity-patterns.md.
For the final completion verification checklist โ the explicit audit pattern to run before marking status: complete on an installable-solution mission, see references/autonomous-lab-completion-verification.md.
For the reactivation protocol when a completed lab receives new P0 feedback or the user contradicts a completion claim, see references/autonomous-lab-reactivation-protocol.md.
For adding historical trend tracking (SQLite-backed agent status transitions + vanilla JS SVG sparklines) to an autonomous lab dashboard, see references/history-tracking-sparkline-pattern.md.
For reusable dashboard UX patterns (onboarding tours, data freshness badges, keyboard shortcuts, progressive disclosure inspectors, cross-linking between views), see references/dashboard-ux-patterns.md.
For programmatic verification of CSS custom-property theme systems โ catching scoping bugs, confirming theme distinctness, and validating JS switching logic โ see references/theme-system-verification.md.
For Son's Discord-first autonomous experiments where a channel hosts a repeated multi-agent loop, use the Autonomous Discord Agent Lab pattern: create file-based durable state, a paused cron orchestrator delivered to discord:<channel_id>, then activate it from a user mission trigger. See references/autonomous-discord-agent-lab.md.
Webhooks
hermes webhook subscribe N Create route at /webhooks/<name>
hermes webhook list List subscriptions
hermes webhook remove NAME Remove a subscription
hermes webhook test NAME Send a test POST
Profiles
hermes profile list List all profiles
hermes profile create NAME Create (--clone, --clone-all, --clone-from)
hermes profile use NAME Set sticky default
hermes profile delete NAME Delete a profile
hermes profile show NAME Show details
hermes profile alias NAME Manage wrapper scripts
hermes profile rename A B Rename a profile
hermes profile export NAME Export to tar.gz
hermes profile import FILE Import from archive
Credential Pools
hermes auth add Interactive credential wizard
hermes auth list [PROVIDER] List pooled credentials
hermes auth remove P INDEX Remove by provider + index
hermes auth reset PROVIDER Clear exhaustion status
Other
hermes insights [--days N] Usage analytics
hermes update Update to latest version
hermes pairing list/approve/revoke DM authorization
hermes plugins list/install/remove Plugin management
hermes honcho setup/status Honcho memory integration (requires honcho plugin)
hermes memory setup/status/off Memory provider config
hermes completion bash|zsh Shell completions
hermes acp ACP server (IDE integration)
hermes claw migrate Migrate from OpenClaw
hermes uninstall Uninstall Hermes
---
Slash Commands (In-Session)
Type these during an interactive chat session. New commands land fairly
often; if something below looks stale, run /help in-session for the
authoritative list or see the [live slash commands reference](https://hermes-agent.nousresearch.com/docs/reference/slash-commands).
The registry of record is hermes_cli/commands.py โ every consumer
(autocomplete, Telegram menu, Slack mapping, /help) derives from it.
Session Control
/new (/reset) Fresh session
/clear Clear screen + new session (CLI)
/retry Resend last message
/undo Remove last exchange
/title [name] Name the session
/compress Manually compress context
/stop Kill background processes
/rollback [N] Restore filesystem checkpoint
/snapshot [sub] Create or restore state snapshots of Hermes config/state (CLI)
/background <prompt> Run prompt in background
/queue <prompt> Queue for next turn
/steer <prompt> Inject a message after the next tool call without interrupting
/agents (/tasks) Show active agents and running tasks
/resume [name] Resume a named session
/goal [text|sub] Set a standing goal Hermes works on across turns until achieved
(subcommands: status, pause, resume, clear)
/redraw Force a full UI repaint (CLI)
Configuration
/config Show config (CLI)
/model [name] Show or change model
/personality [name] Set personality
/reasoning [level] Set reasoning (none|minimal|low|medium|high|xhigh|show|hide)
/verbose Cycle: off โ new โ all โ verbose
/voice [on|off|tts] Voice mode
/yolo Toggle approval bypass
/busy [sub] Control what Enter does while Hermes is working (CLI)
(subcommands: queue, steer, interrupt, status)
/indicator [style] Pick the TUI busy-indicator style (CLI)
(styles: kaomoji, emoji, unicode, ascii)
/footer [on|off] Toggle gateway runtime-metadata footer on final replies
/skin [name] Change theme (CLI)
/statusbar Toggle status bar (CLI)
Tools & Skills
/tools Manage tools (CLI)
/toolsets List toolsets (CLI)
/skills Search/install skills (CLI)
/skill <name> Load a skill into session
/reload-skills Re-scan ~/.hermes/skills/ for added/removed skills
/reload Reload .env variables into the running session (CLI)
/reload-mcp Reload MCP servers
/cron Manage cron jobs (CLI)
/curator [sub] Background skill maintenance (status, run, pin, archive, โฆ)
/kanban [sub] Multi-profile collaboration board (tasks, links, comments)
/plugins List plugins (CLI)
Gateway
/approve Approve a pending command (gateway)
/deny Deny a pending command (gateway)
/restart Restart gateway (gateway)
/sethome Set current chat as home channel (gateway)
/update Update Hermes to latest (gateway)
/topic [sub] Enable or inspect Telegram DM topic sessions (gateway)
/platforms (/gateway) Show platform connection status (gateway)
Utility
/branch (/fork) Branch the current session
/fast Toggle priority/fast processing
/browser Open CDP browser connection
/history Show conversation history (CLI)
/save Save conversation to file (CLI)
/copy [N] Copy the last assistant response to clipboard (CLI)
/paste Attach clipboard image (CLI)
/image Attach local image file (CLI)
Info
/help Show commands
/commands [page] Browse all commands (gateway)
/usage Token usage
/insights [days] Usage analytics
/gquota Show Google Gemini Code Assist quota usage (CLI)
/status Session info (gateway)
/profile Active profile info
/debug Upload debug report (system info + logs) and get shareable links
Exit
/quit (/exit, /q) Exit CLI
---
Key Paths & Config
~/.hermes/config.yaml Main configuration
~/.hermes/.env API keys and secrets
$HERMES_HOME/skills/ Installed skills
~/.hermes/sessions/ Session transcripts
~/.hermes/logs/ Gateway and error logs
~/.hermes/auth.json OAuth tokens and credential pools
~/.hermes/hermes-agent/ Source code (if git-installed)
Profiles use ~/.hermes/profiles/<name>/ with the same layout.
Config Sections
Edit with hermes config edit or hermes config set section.key value.
| Section | Key options |
|---------|-------------|
| model | default, provider, base_url, api_key, context_length |
| agent | max_turns (90), tool_use_enforcement |
| terminal | backend (local/docker/ssh/modal), cwd, timeout (180) |
| compression | enabled, threshold (0.50), target_ratio (0.20) |
| display | skin, tool_progress, show_reasoning, show_cost |
| stt | enabled, provider (local/groq/openai/mistral) |
| tts | provider (edge/elevenlabs/openai/minimax/mistral/neutts) |
| memory | memory_enabled, user_profile_enabled, provider |
| security | tirith_enabled, website_blocklist |
| delegation | model, provider, base_url, api_key, max_iterations (50), reasoning_effort |
| checkpoints | enabled, max_snapshots (50) |
| fallback_model | provider, model, base_url, key_env |
Fallback Providers
Hermes can automatically fail over to a backup provider:model when the primary is unavailable. This is turn-scoped โ each new user message starts with the primary restored; fallback only activates mid-turn when the primary fails.
Configuration ( ~/.hermes/config.yaml):
fallback_model:
provider: opencode-go
model: kimi-k2.6
Or use the interactive manager:
hermes fallback add # interactive picker
hermes fallback list # show fallback chain
hermes fallback remove # remove by index
Legacy note: fallback_model (singular) is the legacy single-fallback key. fallback_providers (list) supports multiple ordered fallbacks. When both exist, fallback_providers takes priority.
Trigger conditions (after exhausting retries where applicable):
- Rate limits (HTTP 429)
- Server errors (HTTP 500, 502, 503)
- Auth failures (HTTP 401, 403) โ immediately
- Not found (HTTP 404) โ immediately
- Invalid / empty responses repeatedly
Supported providers include all standard providers (OpenRouter, Anthropic, OpenCode Go/ Zen, Kimi, etc.) plus custom endpoints with base_url + key_env. Full provider docs: https://hermes-agent.nousresearch.com/docs/integrations/providers
Limitations:
- Subagent delegation does not inherit fallback config
- Cron jobs do not use fallback (use per-job provider/model overrides)
- Auxiliary tasks (vision, compression, etc.) use their own
auxiliary.* provider chain
For a deep-dive with worked examples and model lists, see references/fallback-providers.md.
Full config reference: https://hermes-agent.nousresearch.com/docs/user-guide/configuration
Providers
20+ providers supported. Set via hermes model or hermes setup.
| Provider | Auth | Key env var |
|----------|------|-------------|
| OpenRouter | API key | OPENROUTER_API_KEY |
| Anthropic | API key | ANTHROPIC_API_KEY |
| Nous Portal | OAuth | hermes auth |
| OpenAI Codex | OAuth | hermes auth |
| GitHub Copilot | Token | COPILOT_GITHUB_TOKEN |
| Google Gemini | API key | GOOGLE_API_KEY or GEMINI_API_KEY |
| DeepSeek | API key | DEEPSEEK_API_KEY |
| xAI / Grok | API key | XAI_API_KEY |
| Hugging Face | Token | HF_TOKEN |
| Z.AI / GLM | API key | GLM_API_KEY |
| MiniMax | API key | MINIMAX_API_KEY |
| MiniMax CN | API key | MINIMAX_CN_API_KEY |
| Kimi / Moonshot | API key | KIMI_API_KEY |
| Alibaba / DashScope | API key | DASHSCOPE_API_KEY |
| Xiaomi MiMo | API key | XIAOMI_API_KEY |
| Kilo Code | API key | KILOCODE_API_KEY |
| AI Gateway (Vercel) | API key | AI_GATEWAY_API_KEY |
| OpenCode Zen | API key | OPENCODE_ZEN_API_KEY |
| OpenCode Go | API key | OPENCODE_GO_API_KEY |
| Qwen OAuth | OAuth | hermes auth add qwen-oauth |
| Custom endpoint | Config | model.base_url + model.api_key in config.yaml |
| GitHub Copilot ACP | External | COPILOT_CLI_PATH or Copilot CLI |
Full provider docs: https://hermes-agent.nousresearch.com/docs/integrations/providers
Toolsets
Enable/disable via hermes tools (interactive) or hermes tools enable/disable NAME.
| Toolset | What it provides |
|---------|-----------------|
| web | Web search and content extraction |
| search | Web search only (subset of web) |
| browser | Browser automation (Browserbase, Camofox, or local Chromium) |
| terminal | Shell commands and process management |
| file | File read/write/search/patch |
| code_execution | Sandboxed Python execution |
| vision | Image analysis |
| image_gen | AI image generation |
| video | Video analysis and generation |
| tts | Text-to-speech |
| skills | Skill browsing and management |
| memory | Persistent cross-session memory |
| session_search | Search past conversations |
| delegation | Subagent task delegation |
| cronjob | Scheduled task management |
| clarify | Ask user clarifying questions |
| messaging | Cross-platform message sending |
| todo | In-session task planning and tracking |
| kanban | Multi-agent work-queue tools (gated to workers) |
| debugging | Extra introspection/debug tools (off by default) |
| safe | Minimal, low-risk toolset for locked-down sessions |
| spotify | Spotify playback and playlist control |
| homeassistant | Smart home control (off by default) |
| discord | Discord integration tools |
| discord_admin | Discord admin/moderation tools |
| feishu_doc | Feishu (Lark) document tools |
| feishu_drive | Feishu (Lark) drive tools |
| yuanbao | Yuanbao integration tools |
| rl | Reinforcement learning tools (off by default) |
| moa | Mixture of Agents (off by default) |
Full enumeration lives in toolsets.py as the TOOLSETS dict; _HERMES_CORE_TOOLS is the default bundle most platforms inherit from.
Tool changes take effect on /reset (new session). They do NOT apply mid-conversation to preserve prompt caching.
---
Security & Privacy Toggles
Common "why is Hermes doing X to my output / tool calls / commands?" toggles โ and the exact commands to change them. Most of these need a fresh session (/reset in chat, or start a new hermes invocation) because they're read once at startup.
Secret redaction in tool output
Secret redaction is off by default โ tool output (terminal stdout, read_file, web content, subagent summaries, etc.) passes through unmodified. If the user wants Hermes to auto-mask strings that look like API keys, tokens, and secrets before they enter the conversation context and logs:
hermes config set security.redact_secrets true # enable globally
Restart required. security.redact_secrets is snapshotted at import time โ toggling it mid-session (e.g. via export HERMES_REDACT_SECRETS=true from a tool call) will NOT take effect for the running process. Tell the user to run hermes config set security.redact_secrets true in a terminal, then start a new session. This is deliberate โ it prevents an LLM from flipping the toggle on itself mid-task.
Disable again with:
hermes config set security.redact_secrets false
PII redaction in gateway messages
Separate from secret redaction. When enabled, the gateway hashes user IDs and strips phone numbers from the session context before it reaches the model:
hermes config set privacy.redact_pii true # enable
hermes config set privacy.redact_pii false # disable (default)
Command approval prompts
By default (approvals.mode: manual), Hermes prompts the user before running shell commands flagged as destructive (rm -rf, git reset --hard, etc.). The modes are:
manual โ always prompt (default)
smart โ use an auxiliary LLM to auto-approve low-risk commands, prompt on high-risk
off โ skip all approval prompts (equivalent to --yolo)
hermes config set approvals.mode smart # recommended middle ground
hermes config set approvals.mode off # bypass everything (not recommended)
Per-invocation bypass without changing config:
hermes --yolo โฆ
export HERMES_YOLO_MODE=1
Note: YOLO / approvals.mode: off does NOT turn off secret redaction. They are independent.
Shell hooks allowlist
Some shell-hook integrations require explicit allowlisting before they fire. Managed via ~/.hermes/shell-hooks-allowlist.json โ prompted interactively the first time a hook wants to run.
Disabling the web/browser/image-gen tools
To keep the model away from network or media tools entirely, open hermes tools and toggle per-platform. Takes effect on next session (/reset). See the Tools & Skills section above.
---
Voice & Transcription
STT (Voice โ Text)
Voice messages from messaging platforms are auto-transcribed.
Provider priority (auto-detected):
1. Local faster-whisper โ free, no API key: pip install faster-whisper
2. Groq Whisper โ free tier: set GROQ_API_KEY
3. OpenAI Whisper โ paid: set VOICE_TOOLS_OPENAI_KEY
4. Mistral Voxtral โ set MISTRAL_API_KEY
Config:
stt:
enabled: true
provider: local # local, groq, openai, mistral
local:
model: base # tiny, base, small, medium, large-v3
TTS (Text โ Voice)
| Provider | Env var | Free? |
|----------|---------|-------|
| Edge TTS | None | Yes (default) |
| ElevenLabs | ELEVENLABS_API_KEY | Free tier |
| OpenAI | VOICE_TOOLS_OPENAI_KEY | Paid |
| MiniMax | MINIMAX_API_KEY | Paid |
| Mistral (Voxtral) | MISTRAL_API_KEY | Paid |
| NeuTTS (local) | None (pip install neutts[all] + espeak-ng) | Free |
Voice commands: /voice on (voice-to-voice), /voice tts (always voice), /voice off.
---
Spawning Additional Hermes Instances
Run additional Hermes processes as fully independent subprocesses โ separate sessions, tools, and environments.
When to Use This vs delegate_task
| | delegate_task | Spawning hermes process |
|-|-----------------|--------------------------|
| Isolation | Separate conversation, shared process | Fully independent process |
| Duration | Minutes (bounded by parent loop) | Hours/days |
| Tool access | Subset of parent's tools | Full tool access |
| Interactive | No | Yes (PTY mode) |
| Use case | Quick parallel subtasks | Long autonomous missions |
One-Shot Mode
terminal(command="hermes chat -q 'Research GRPO papers and write summary to ~/research/grpo.md'", timeout=300)
Background for long tasks:
terminal(command="hermes chat -q 'Set up CI/CD for ~/myapp'", background=true)
Interactive PTY Mode (via tmux)
Hermes uses prompt_toolkit, which requires a real terminal. Use tmux for interactive spawning:
Start
terminal(command="tmux new-session -d -s agent1 -x 120 -y 40 'hermes'", timeout=10)
Wait for startup, then send a message
terminal(command="sleep 8 && tmux send-keys -t agent1 'Build a FastAPI auth service' Enter", timeout=15)
Read output
terminal(command="sleep 20 && tmux capture-pane -t agent1 -p", timeout=5)
Send follow-up
terminal(command="tmux send-keys -t agent1 'Add rate limiting middleware' Enter", timeout=5)
Exit
terminal(command="tmux send-keys -t agent1 '/exit' Enter && sleep 2 && tmux kill-session -t agent1", timeout=10)
Multi-Agent Coordination
Agent A: backend
terminal(command="tmux new-session -d -s backend -x 120 -y 40 'hermes -w'", timeout=10)
terminal(command="sleep 8 && tmux send-keys -t backend 'Build REST API for user management' Enter", timeout=15)
Agent B: frontend
terminal(command="tmux new-session -d -s frontend -x 120 -y 40 'hermes -w'", timeout=10)
terminal(command="sleep 8 && tmux send-keys -t frontend 'Build React dashboard for user management' Enter", timeout=15)
Check progress, relay context between them
terminal(command="tmux capture-pane -t backend -p | tail -30", timeout=5)
terminal(command="tmux send-keys -t frontend 'Here is the API schema from the backend agent: ...' Enter", timeout=5)
Session Resume
Resume most recent session
terminal(command="tmux new-session -d -s resumed 'hermes --continue'", timeout=10)
Resume specific session
terminal(command="tmux new-session -d -s resumed 'hermes --resume 20260225_143052_a1b2c3'", timeout=10)
Tips
- Prefer
delegate_task for quick subtasks โ less overhead than spawning a full process
- Use
-w (worktree mode) when spawning agents that edit code โ prevents git conflicts
- Set timeouts for one-shot mode โ complex tasks can take 5-10 minutes
- Use
hermes chat -q for fire-and-forget โ no PTY needed
- Use tmux for interactive sessions โ raw PTY mode has
\r vs \n issues with prompt_toolkit
- For scheduled tasks, use the
cronjob tool instead of spawning โ handles delivery and retry
---
Durable & Background Systems
Four systems run alongside the main conversation loop. Quick reference
here; full developer notes live in AGENTS.md, user-facing docs under
website/docs/user-guide/features/.
Delegation (delegate_task)
Synchronous subagent spawn โ the parent waits for the child's summary
before continuing its own loop. Isolated context + terminal session.
- Single:
delegate_task(goal, context, toolsets).
- Batch:
delegate_task(tasks=[{goal, ...}, ...]) runs children in
parallel, capped by delegation.max_concurrent_children (default 3).
- Roles:
leaf (default; cannot re-delegate) vs orchestrator
(can spawn its own workers, bounded by delegation.max_spawn_depth).
- Not durable. If the parent is interrupted, the child is
cancelled. For work that must outlive the turn, use cronjob or
terminal(background=True, notify_on_complete=True).
Config: delegation.* in config.yaml.
Tuning max_concurrent_children
Default is 3. Rule of thumb for raising it:
- Light tasks (web search, file grep): up to
6-8
- Medium tasks (code execution, browser):
4-5
- Heavy tasks (builds, large data):
2-3
- Actual bottleneck is usually the API rate limit, not local CPU/RAM. On a 10-core M4 with 16GB RAM, CPU is rarely the constraint.
- Formula: start at
5, raise only if profiling shows idle time between API responses.
Cron (scheduled jobs)
Durable scheduler โ cron/jobs.py + cron/scheduler.py. Drive it via
the cronjob tool, the hermes cron CLI (list, add, edit,
pause, resume, run, remove), or the /cron slash command.
- Schedules: duration (
"30m", "2h"), "every" phrase
( "every monday 9am"), 5-field cron ( "0 9 *"), or ISO timestamp.
- Per-job knobs:
skills, model/provider override, script
(pre-run data collection; no_agent=True makes the script the whole
job), context_from (chain job A's output into job B), workdir
(run in a specific dir with its AGENTS.md / CLAUDE.md loaded),
multi-platform delivery.
- Invariants: 3-minute hard interrupt per run,
.tick.lock file
prevents duplicate ticks across processes, cron sessions pass
skip_memory=True by default, and cron deliveries are framed with a
header/footer instead of being mirrored into the target gateway
session (keeps role alternation intact).
User docs: https://hermes-agent.nousresearch.com/docs/user-guide/features/cron
Curator (skill lifecycle)
Background maintenance for agent-created skills. Tracks usage, marks
idle skills stale, archives stale ones, keeps a pre-run tar.gz backup
so nothing is lost.
- CLI:
hermes curator <verb> โ status, run, pause, resume,
pin, unpin, archive, restore, prune, backup, rollback.
- Slash:
/curator <subcommand> mirrors the CLI.
- Scope: only touches skills with
created_by: "agent" provenance.
Bundled + hub-installed skills are off-limits. Never deletes โ
max destructive action is archive. Pinned skills are exempt from
every auto-transition and every LLM review pass.
- Telemetry: sidecar at
~/.hermes/skills/.usage.json holds
per-skill use_count, view_count, patch_count,
last_activity_at, state, pinned.
Config: curator.* (enabled, interval_hours, min_idle_hours,
stale_after_days, archive_after_days, backup.*).
User docs: https://hermes-agent.nousresearch.com/docs/user-guide/features/curator
Dreaming (periodic memory/skill consolidation)
For Anthropic-style "dreaming" workflows, combine cron + session_search + memory + skills + curator into a scheduled review loop. Start with a weekly, proposal-only report that audits recent sessions, repeated user corrections, memory conflicts, skill patch candidates, and cron/automation improvements. Do not automatically delete/replace memory or patch/archive skills unless the user explicitly approves the proposed changes. See references/weekly-dreaming-routine.md for the recommended prompt, report format, safety policy, and cron creation pattern.
Kanban (multi-agent work queue)
Durable SQLite board for multi-profile / multi-worker collaboration.
Users drive it via hermes kanban <verb>; dispatcher-spawned workers
see a focused kanban_* toolset gated by HERMES_KANBAN_TASK so the
schema footprint is zero outside worker processes.
- CLI verbs (common):
init, create, list (alias ls),
show, assign, link, unlink, comment, complete, block,
unblock, archive, tail. Less common: watch, stats, runs,
log, dispatch, daemon, gc.
- Worker toolset:
kanban_show, kanban_complete, kanban_block,
kanban_heartbeat, kanban_comment, kanban_create, kanban_link.
- Dispatcher runs inside the gateway by default
( kanban.dispatch_in_gateway: true) โ reclaims stale claims,
promotes ready tasks, atomically claims, spawns assigned profiles.
Auto-blocks a task after ~5 consecutive spawn failures.
- Isolation: board is the hard boundary (workers get
HERMES_KANBAN_BOARD pinned in env); tenant is a soft namespace
within a board for workspace-path + memory-key isolation.
User docs: https://hermes-agent.nousresearch.com/docs/user-guide/features/kanban
Log Relay (Hermes โ Discord)
A background Python script that tails ~/.hermes/logs/*.log and batches lines to a Discord channel. Includes session-ID extraction, rate-limit handling, and auto-restart via launchd/systemd. Useful for remote monitoring and audit trails.
- Reference:
references/discord-log-relay.md โ full setup, tuning, macOS/Linux service install, pitfalls.
- Template:
templates/discord-log-relay.py โ copy, set CHANNEL_ID, and deploy.
- Discord operations:
references/discord-operating-planes.md โ channel-purpose routing, periodic-summary vs Dreaming report formats, and safety/cost notes for Discord-first Hermes deployments.
Key pitfall: ask the user about batch frequency upfront rather than defaulting to real-time streaming. Most users prefer 10-minute or hourly batches. High-volume raw logs should be batched, summarized, or stored out-of-band; avoid Discord message storms during error loops.
Weekly Dreaming / Memory Curation
For long-running Hermes deployments, users may want an Anthropic-style "Dreaming" loop: a scheduled review that consolidates experience, proposes memory/skill/cron changes, and identifies what to keep, weaken, archive, or delete. Hermes has the building blocks (sessions, session_search, memory, skills, curator, cron), but the safe default is proposal mode:
1. Inspect recent usage and sessions.
2. Extract repeated success patterns, failure patterns, and user corrections.
3. Propose memory updates/removals without applying them silently.
4. Propose skill patches/archive candidates and cron/reporting improvements.
5. End with explicit approval checkboxes.
Do not silently rewrite or delete memory/skills from a Dreaming report unless the user explicitly authorized automatic application. See references/discord-operating-planes.md for a report template and routing heuristics.
---
Windows-Specific Quirks
Hermes runs natively on Windows (PowerShell, cmd, Windows Terminal, git-bash
mintty, VS Code integrated terminal). Most of it just works, but a handful
of differences between Win32 and POSIX have bitten us โ document new ones
here as you hit them so the next person (or the next session) doesn't
rediscover them from scratch.
Input / Keybindings
Alt+Enter doesn't insert a newline. Windows Terminal intercepts Alt+Enter
at the terminal layer to toggle fullscreen โ the keystroke never reaches
prompt_toolkit. Use Ctrl+Enter instead. Windows Terminal delivers
Ctrl+Enter as LF ( c-j), distinct from plain Enter ( c-m / CR), and the
CLI binds c-j to newline insertion on win32 only (see
_bind_prompt_submit_keys + the Windows-only c-j binding in cli.py).
Side effect: the raw Ctrl+J keystroke also inserts a newline on Windows โ
unavoidable, because Windows Terminal collapses Ctrl+Enter and Ctrl+J to
the same keycode at the Win32 console API layer. No conflicting binding
existed for Ctrl+J on Windows, so this is a harmless side effect.
mintty / git-bash behaves the same (fullscreen on Alt+Enter) unless you
disable Alt+Fn shortcuts in Options โ Keys. Easier to just use Ctrl+Enter.
Diagnosing keybindings. Run python scripts/keystroke_diagnostic.py
(repo root) to see exactly how prompt_toolkit identifies each keystroke
in the current terminal. Answers questions like "does Shift+Enter come
through as a distinct key?" (almost never โ most terminals collapse it
to plain Enter) or "what byte sequence is my terminal sending for
Ctrl+Enter?" This is how the Ctrl+Enter = c-j fact was established.
Config / Files
HTTP 400 "No models provided" on first run. config.yaml was saved
with a UTF-8 BOM (common when Windows apps write it). Re-save as UTF-8
without BOM. hermes config edit writes without BOM; manual edits in
Notepad are the usual culprit.
execute_code / Sandbox
WinError 10106 ("The requested service provider could not be loaded
or initialized") from the sandbox child process โ it can't create an
AF_INET socket, so the loopback-TCP RPC fallback fails before
connect(). Root cause is usually not a broken Winsock LSP; it's
Hermes's own env scrubber dropping SYSTEMROOT / WINDIR / COMSPEC
from the child env. Python's socket module needs SYSTEMROOT to locate
mswsock.dll. Fixed via the _WINDOWS_ESSENTIAL_ENV_VARS allowlist in
tools/code_execution_tool.py. If you still hit it, echo os.environ
inside an execute_code block to confirm SYSTEMROOT is set. Full
diagnostic recipe in references/execute-code-sandbox-env-windows.md.
Testing / Contributing
scripts/run_tests.sh doesn't work as-is on Windows โ it looks for
POSIX venv layouts ( .venv/bin/activate). The Hermes-installed venv at
venv/Scripts/ has no pip or pytest either (stripped for install size).
Workaround: install pytest + pytest-xdist + pyyaml into a system Python
3.11 user site, then invoke pytest directly with PYTHONPATH set:
"/c/Program Files/Python311/python" -m pip install --user pytest pytest-xdist pyyaml
export PYTHONPATH="$(pwd)"
"/c/Program Files/Python311/python" -m pytest tests/foo/test_bar.py -v --tb=short -n 0
Use -n 0, not -n 4 โ pyproject.toml's default addopts already
includes -n, and the wrapper's CI-parity guarantees don't apply off POSIX.
POSIX-only tests need skip guards. Common markers already in the codebase:
- Symlinks โ elevated privileges on Windows
0o600 file modes โ POSIX mode bits not enforced on NTFS by default
signal.SIGALRM โ Unix-only (see tests/conftest.py::_enforce_test_timeout)
- Winsock / Windows-specific regressions โ
@pytest.mark.skipif(sys.platform != "win32", ...)
Use the existing skip-pattern style (sys.platform == "win32" or
sys.platform.startswith("win")) to stay consistent with the rest of the
suite.
Path / Filesystem
Line endings. Git may warn LF will be replaced by CRLF the next time
Git touches it. Cosmetic โ the repo's .gitattributes normalizes. Don't
let editors auto-convert committed POSIX-newline files to CRLF.
Forward slashes work almost everywhere. C:/Users/... is accepted by
every Hermes tool and most Windows APIs. Prefer forward slashes in code
and logs โ avoids shell-escaping backslashes in bash.
---
Troubleshooting
Voice not working
1. Check stt.enabled: true in config.yaml
2. Verify provider: pip install faster-whisper or set API key
3. In gateway: /restart. In CLI: exit and relaunch.
Tool not available
1. hermes tools โ check if toolset is enabled for your platform
2. Some tools need env vars (check .env)
3. /reset after enabling tools
Model/provider issues
1. hermes doctor โ check config and dependencies
2. hermes auth add <provider> โ re-authenticate OAuth providers (use --type oauth)
3. Check .env has the right API key
4. Copilot 403: gh auth login tokens do NOT work for Copilot API. You must use the Copilot-specific OAuth device code flow via hermes model โ GitHub Copilot.
Changes not taking effect
- Tools/skills:
/reset starts a new session with updated toolset
- Config changes: In gateway:
/restart. In CLI: exit and relaunch.
- Code changes: Restart the CLI or gateway process
Skills not showing
1. hermes skills list โ verify installed
2. hermes skills config โ check platform enablement
3. Load explicitly: /skill name or hermes -s name
Gateway issues
Check logs first:
grep -i "failed to send\|error" ~/.hermes/logs/gateway.log | tail -20
Common gateway problems:
- Gateway dies on SSH logout: Enable linger:
sudo loginctl enable-linger $USER
- Gateway dies on WSL2 close: WSL2 requires
systemd=true in /etc/wsl.conf for systemd services to work. Without it, gateway falls back to nohup (dies when session closes).
- Gateway crash loop: Reset the failed state:
systemctl --user reset-failed hermes-gateway
- macOS: bot shows offline after idle time: The gateway runs as a user agent (
LimitLoadToSessionType=Aqua), so macOS suspends it when the system sleeps. The platform websocket drops and the bot appears offline until the network returns. Fix: keep the Mac awake (System Settings -> Energy -> Prevent automatic sleeping, or caffeinate -d -i -s -u &). Low Power Mode makes this worse, not better. See references/macos-gateway-sleep-disconnect.md for the full diagnostic recipe.
Platform-specific issues
- Discord bot silent: Must enable Message Content Intent in Bot โ Privileged Gateway Intents. See full Discord setup reference:
references/discord-gateway-setup.md.
- Slack bot only works in DMs: Must subscribe to
message.channels event. Without it, the bot ignores public channels.
- Windows-specific issues (
Alt+Enter newline, WinError 10106, UTF-8 BOM config, test suite, line endings): see the dedicated Windows-Specific Quirks section above.
Auxiliary models not working
If auxiliary tasks (vision, compression, session_search) fail silently, the auto provider can't find a backend. Either set OPENROUTER_API_KEY or GOOGLE_API_KEY, or explicitly configure each auxiliary task's provider:
hermes config set auxiliary.vision.provider <your_provider>
hermes config set auxiliary.vision.model <model_name>
Full system auth provisioning
For a one-shot workflow to maximize available credentials โ installing gh, generating SSH keys, configuring git, enabling all Hermes toolsets, and auditing current auth state โ see references/system-auth-setup.md.
Editing large files with patch
When a file is read with read_file(offset=...) (pagination), the tool warns that the view is partial. If you attempt patch without re-reading the full file first, you will likely hit non-unique match errors or corrupt the file. Fix: always call read_file without offset to load the whole file before patching. For append-only updates (e.g., adding a cycle log entry to state.md), terminal(command="cat >> file << 'EOF'...EOF") is a safer fallback that bypasses match-uniqueness issues entirely.
---
Windows-Specific Quirks
| Looking for... | Location |
|----------------|----------|
| Config options | hermes config edit or [Configuration docs](https://hermes-agent.nousresearch.com/docs/user-guide/configuration) |
| Available tools | hermes tools list or [Tools reference](https://hermes-agent.nousresearch.com/docs/reference/tools-reference) |
| Slash commands | /help in session or [Slash commands reference](https://hermes-agent.nousresearch.com/docs/reference/slash-commands) |
| Skills catalog | hermes skills browse or [Skills catalog](https://hermes-agent.nousresearch.com/docs/reference/skills-catalog) |
| Provider setup | hermes model or [Providers guide](https://hermes-agent.nousresearch.com/docs/integrations/providers) |
| Platform setup | hermes gateway setup or [Messaging docs](https://hermes-agent.nousresearch.com/docs/user-guide/messaging/) |
| MCP servers | hermes mcp list or [MCP guide](https://hermes-agent.nousresearch.com/docs/user-guide/features/mcp) |
| Profiles | hermes profile list or [Profiles docs](https://hermes-agent.nousresearch.com/docs/user-guide/profiles) |
| Cron jobs | hermes cron list or [Cron docs](https://hermes-agent.nousresearch.com/docs/user-guide/features/cron) |
| Memory | hermes memory status or [Memory docs](https://hermes-agent.nousresearch.com/docs/user-guide/features/memory) |
| Env variables | hermes config env-path or [Env vars reference](https://hermes-agent.nousresearch.com/docs/reference/environment-variables) |
| CLI commands | hermes --help or [CLI reference](https://hermes-agent.nousresearch.com/docs/reference/cli-commands) |
| Gateway logs | ~/.hermes/logs/gateway.log |
| Session files | ~/.hermes/sessions/ or hermes sessions browse |
| Source code | ~/.hermes/hermes-agent/ |
---
Contributor Quick Reference
For occasional contributors and PR authors. Full developer docs: https://hermes-agent.nousresearch.com/docs/developer-guide/
Project Layout
hermes-agent/
โโโ run_agent.py # AIAgent โ core conversation loop
โโโ model_tools.py # Tool discovery and dispatch
โโโ toolsets.py # Toolset definitions
โโโ cli.py # Interactive CLI (HermesCLI)
โโโ hermes_state.py # SQLite session store
โโโ agent/ # Prompt builder, context compression, memory, model routing, credential pooling, skill dispatch
โโโ hermes_cli/ # CLI subcommands, config, setup, commands
โ โโโ commands.py # Slash command registry (CommandDef)
โ โโโ config.py # DEFAULT_CONFIG, env var definitions
โ โโโ main.py # CLI entry point and argparse
โโโ tools/ # One file per tool
โ โโโ registry.py # Central tool registry
โโโ gateway/ # Messaging gateway
โ โโโ platforms/ # Platform adapters (telegram, discord, etc.)
โโโ cron/ # Job scheduler
โโโ tests/ # ~3000 pytest tests
โโโ website/ # Docusaurus docs site
Config: ~/.hermes/config.yaml (settings), ~/.hermes/.env (API keys).
Adding a Tool (3 files)
1. Create tools/your_tool.py:
import json, os
from tools.registry import registry
def check_requirements() -> bool:
return bool(os.getenv("EXAMPLE_API_KEY"))
def example_tool(param: str, task_id: str = None) -> str:
return json.dumps({"success": True, "data": "..."})
registry.register(
name="example_tool",
toolset="example",
schema={"name": "example_tool", "description": "...", "parameters": {...}},
handler=lambda args, **kw: example_tool(
param=args.get("param", ""), task_id=kw.get("task_id")),
check_fn=check_requirements,
requires_env=["EXAMPLE_API_KEY"],
)
2. Add to toolsets.py โ _HERMES_CORE_TOOLS list.
Auto-discovery: any tools/*.py file with a top-level registry.register() call is imported automatically โ no manual list needed.
All handlers must return JSON strings. Use get_hermes_home() for paths, never hardcode ~/.hermes.
Adding a Slash Command
1. Add CommandDef to COMMAND_REGISTRY in hermes_cli/commands.py
2. Add handler in cli.py โ process_command()
3. (Optional) Add gateway handler in gateway/run.py
All consumers (help text, autocomplete, Telegram menu, Slack mapping) derive from the central registry automatically.
Agent Loop (High Level)
run_conversation():
1. Build system prompt
2. Loop while iterations < max:
a. Call LLM (OpenAI-format messages + tool schemas)
b. If tool_calls โ dispatch each via handle_function_call() โ append results โ continue
c. If text response โ return
3. Context compression triggers automatically near token limit
Testing
python -m pytest tests/ -o 'addopts=' -q # Full suite
python -m pytest tests/tools/ -q # Specific area
- Tests auto-redirect
HERMES_HOME to temp dirs โ never touch real ~/.hermes/
- Run full suite before pushing any change
- Use
-o 'addopts=' to clear any baked-in pytest flags
Windows contributors: scripts/run_tests.sh currently looks for POSIX venvs ( .venv/bin/activate / venv/bin/activate) and will error out on Windows where the layout is venv/Scripts/activate + python.exe. The Hermes-installed venv at venv/Scripts/ also has no pip or pytest โ it's stripped for end-user install size. Workaround: install pytest + pytest-xdist + pyyaml into a system Python 3.11 user site ( /c/Program Files/Python311/python -m pip install --user pytest pytest-xdist pyyaml), then run tests directly:
export PYTHONPATH="$(pwd)"
"/c/Program Files/Python311/python" -m pytest tests/tools/test_foo.py -v --tb=short -n 0
Use -n 0 (not -n 4) because pyproject.toml's default addopts already includes -n, and the wrapper's CI-parity story doesn't apply off-POSIX.
Cross-platform test guards: tests that use POSIX-only syscalls need a skip marker. Common ones already in the codebase:
- Symlink creation โ
@pytest.mark.skipif(sys.platform == "win32", reason="Symlinks require elevated privileges on Windows") (see tests/cron/test_cron_script.py)
- POSIX file modes (0o600, etc.) โ
@pytest.mark.skipif(sys.platform.startswith("win"), reason="POSIX mode bits not enforced on Windows") (see tests/hermes_cli/test_auth_toctou_file_modes.py)
signal.SIGALRM โ Unix-only (see tests/conftest.py::_enforce_test_timeout)
- Live Winsock / Windows-specific regression tests โ
@pytest.mark.skipif(sys.platform != "win32", reason="Windows-specific regression")
Monkeypatching sys.platform is not enough when the code under test also calls platform.system() / platform.release() / platform.mac_ver(). Those functions re-read the real OS independently, so a test that sets sys.platform = "linux" on a Windows runner will still see platform.system() == "Windows" and route through the Windows branch. Patch all three together:
monkeypatch.setattr(sys, "platform", "linux")
monkeypatch.setattr(platform, "system", lambda: "Linux")
monkeypatch.setattr(platform, "release", lambda: "6.8.0-generic")
See tests/agent/test_prompt_builder.py::TestEnvironmentHints for a worked example.
Extending the system prompt's execution-environment block
Factual guidance about the host OS, user home, cwd, terminal backend, and shell (bash vs. PowerShell on Windows) is emitted from agent/prompt_builder.py::build_environment_hints(). This is also where the WSL hint and per-backend probe logic live. The convention:
- Local terminal backend โ emit host info (OS,
$HOME, cwd) + Windows-specific notes (hostname โ username, terminal uses bash not PowerShell).
- Remote terminal backend (anything in
_REMOTE_TERMINAL_BACKENDS: docker, singularity, modal, daytona, ssh, vercel_sandbox, managed_modal) โ suppress host info entirely and describe only the backend. A live uname/whoami/pwd probe runs inside the backend via tools.environments.get_environment(...).execute(...), cached per process in _BACKEND_PROBE_CACHE, with a static fallback if the probe times out.
- Key fact for prompt authoring: when
TERMINAL_ENV != "local", every file tool (read_file, write_file, patch, search_files) runs inside the backend container, not on the host. The system prompt must never describe the host in that case โ the agent can't touch it.
Full design notes, the exact emitted strings, and testing pitfalls:
references/prompt-builder-environment-hints.md.
Refactor-safety pattern (POSIX-equivalence guard): when you extract inline logic into a helper that adds Windows/platform-specific behavior, keep a _legacy_<name> oracle function in the test file that's a verbatim copy of the old code, then parametrize-diff against it. Example: tests/tools/test_code_execution_windows_env.py::TestPosixEquivalence. This locks in the invariant that POSIX behavior is bit-for-bit identical and makes any future drift fail loudly with a clear diff.
Commit Conventions
type: concise subject line
Optional body.
Types: fix:, feat:, refactor:, docs:, chore:
Key Rules
- Never break prompt caching โ don't change context, tools, or system prompt mid-conversation
- Message role alternation โ never two assistant or two user messages in a row
- Use
get_hermes_home() from hermes_constants for all paths (profile-safe)
- Config values go in
config.yaml, secrets go in .env
- New tools need a
check_fn so they only appear when requirements are met
[IMPORTANT: The user has invoked the "kanban-orchestrator" skill, indicating they want you to follow its instructions. The full skill content is loaded below.]
---
name: kanban-orchestrator
description: Decomposition playbook + anti-temptation rules for an orchestrator profile routing work through Kanban. The "don't do the work yourself" rule and the basic lifecycle are auto-injected into every kanban worker's system prompt; this skill is the deeper playbook when you're specifically playing the orchestrator role.
version: 3.0.0
platforms: [linux, macos, windows]
metadata:
hermes:
tags: [kanban, multi-agent, orchestration, routing]
related_skills: [kanban-worker]
---
Kanban Orchestrator โ Decomposition Playbook
> The core worker lifecycle (including the kanban_create fan-out pattern and the "decompose, don't execute" rule) is auto-injected into every kanban process via the KANBAN_GUIDANCE system-prompt block. This skill is the deeper playbook when you're an orchestrator profile whose whole job is routing.
Profiles are user-configured โ not a fixed roster
Hermes setups vary widely. Some users run a single profile that does everything; some run a small fleet (docker-worker, cron-worker); some run a curated specialist team they've named themselves. There is no default specialist roster โ the orchestrator skill does not know what profiles exist on this machine.
Before fanning out, you must ground the decomposition in the profiles that actually exist. The dispatcher silently fails to spawn unknown assignee names โ it doesn't autocorrect, doesn't suggest, doesn't fall back. So a card assigned to researcher on a setup that only has docker-worker just sits in ready forever.
Step 0: discover available profiles before planning.
Use one of these:
hermes profile list โ prints the table of profiles configured on this machine. Run it through your terminal tool if you have one; otherwise ask the user.
kanban_list(assignee="<some-name>") โ sanity-check a single name. Returns an empty list (rather than an error) for an unknown assignee, so this only confirms a name you're already considering.
- Just ask the user. "What profiles do you have set up?" is a fine first turn when the goal needs more than one specialist.
Cache the result in your working memory for the rest of the conversation. Re-asking every turn wastes a tool call.
When to use the board (vs. just doing the work)
Create Kanban tasks when any of these are true:
1. Multiple specialists are needed. Research + analysis + writing is three profiles.
2. The work should survive a crash or restart. Long-running, recurring, or important.
3. The user might want to interject. Human-in-the-loop at any step.
4. Multiple subtasks can run in parallel. Fan-out for speed.
5. Review / iteration is expected. A reviewer profile loops on drafter output.
6. The audit trail matters. Board rows persist in SQLite forever.
If none of those apply โ it's a small one-shot reasoning task โ use delegate_task instead or answer the user directly.
The anti-temptation rules
Your job description says "route, don't execute." The rules that enforce that:
- Do not execute the work yourself. Your restricted toolset usually doesn't even include terminal/file/code/web for implementation. If you find yourself "just fixing this quickly" โ stop and create a task for the right specialist.
- For any concrete task, create a Kanban task and assign it. Every single time.
- Split multi-lane requests before creating cards. A user prompt can contain several independent workstreams. Extract those lanes first, then create one card per lane instead of bundling unrelated work into a single implementer card.
- Run independent lanes in parallel. If two cards do not need each other's output, leave them unlinked so the dispatcher can fan them out. Link only true data dependencies.
- If no specialist fits the available profiles, ask the user which profile to create or which existing profile to use. Do not invent profile names; the dispatcher will silently drop unknown assignees.
- Decompose, route, and summarize โ that's the whole job.
Exception: micro-UI polish cycles
There is one narrow exception where the orchestrator may execute directly instead of creating Kanban cards: tiny UI-only polish cycles (e.g., adding a CSS class, a theme preview dot, a hover state, a cross-link, or a HUD button) that are purely presentational, require no cross-file logic changes, and fit comfortably inside a single bounded cycle with no need for review or parallel work. If the change is limited to HTML/CSS/JS cosmetics, no other profile has a stake in it, and the user did not ask for a design review, the orchestrator should just edit and publish rather than paying the kanban-overhead tax. This exception does NOT apply to architecture changes, adapter logic, plugin interfaces, or anything that touches the data layer.
Decomposition playbook
Step 1 โ Understand the goal
Ask clarifying questions if the goal is ambiguous. Cheap to ask; expensive to spawn the wrong fleet.
Step 2 โ Sketch the task graph
Before creating anything, draft the graph out loud (in your response to the user). Treat every concrete workstream as a candidate card:
1. Extract the lanes from the request.
2. Map each lane to one of the profiles you discovered in Step 0. If a lane doesn't fit any existing profile, ask the user which to use or create.
3. Decide whether each lane is independent or gated by another lane.
4. Create independent lanes as parallel cards with no parent links.
5. Create synthesis/review/integration cards with parent links to the lanes they depend on.
Examples of prompts that should fan out (using placeholder profile names โ substitute whatever exists on the user's setup):
- "Build an app" โ one card to a design-oriented profile for product/UI direction, one or two cards to engineering profiles for implementation, plus a later integration/review card if the user has a reviewer profile.
- "Fix blockers and check model variants" โ one implementation card for the blocker fixes plus one discovery/research card for config/source verification. A final reviewer card can depend on both.
- "Research docs and implement" โ a docs-research card can run in parallel with a codebase-discovery card; implementation waits only if it truly needs those findings.
- "Analyze this screenshot and find the related code" โ one card to a vision-capable profile for the visual analysis while another searches the codebase.
Words like "also," "finally," or "and" do not automatically imply a dependency. They often mean "make sure this is covered before reporting back." Only link tasks when one card cannot start until another card's output exists.
Show the graph to the user before creating cards. Let them correct it โ including which actual profile name should own each lane.
Step 3 โ Create tasks and link
Use the profile names from Step 0. The example below uses placeholders <profile-A>, <profile-B>, <profile-C> โ replace them with what the user actually has.
t1 = kanban_create(
title="research: Postgres cost vs current",
assignee="<profile-A>", # whichever profile handles research on this setup
body="Compare estimated infrastructure costs, migration costs, and ongoing ops costs over a 3-year window. Sources: AWS/GCP pricing, team time estimates, current Postgres bills from peers.",
tenant=os.environ.get("HERMES_TENANT"),
)["task_id"]
t2 = kanban_create(
title="research: Postgres performance vs current",
assignee="<profile-A>", # same profile, run in parallel
body="Compare query latency, throughput, and scaling characteristics at our expected data volume (~500GB, 10k QPS peak). Sources: benchmark papers, public case studies, pgbench results if easy.",
)["task_id"]
t3 = kanban_create(
title="synthesize migration recommendation",
assignee="<profile-B>", # whichever profile does synthesis/analysis
body="Read the findings from T1 (cost) and T2 (performance). Produce a 1-page recommendation with explicit trade-offs and a go/no-go call.",
parents=[t1, t2],
)["task_id"]
t4 = kanban_create(
title="draft decision memo",
assignee="<profile-C>", # whichever profile drafts user-facing prose
body="Turn the analyst's recommendation into a 2-page memo for the CTO. Match the tone of previous decision memos in the team's knowledge base.",
parents=[t3],
)["task_id"]
parents=[...] gates promotion โ children stay in todo until every parent reaches done, then auto-promote to ready. No manual coordination needed; the dispatcher and dependency engine handle it.
Step 4 โ Complete your own task
If you were spawned as a task yourself (e.g. a planner profile was assigned T0: "investigate Postgres migration"), mark it done with a summary of what you created:
kanban_complete(
summary="decomposed into T1-T4: 2 research lanes in parallel, 1 synthesis on their outputs, 1 prose draft on the recommendation",
metadata={
"task_graph": {
"T1": {"assignee": "<profile-A>", "parents": []},
"T2": {"assignee": "<profile-A>", "parents": []},
"T3": {"assignee": "<profile-B>", "parents": ["T1", "T2"]},
"T4": {"assignee": "<profile-C>", "parents": ["T3"]},
},
},
)
Step 5 โ Report back to the user
Tell them what you created in plain prose, naming the actual profiles you used:
> I've queued 4 tasks:
> - T1 (<profile-A>): cost comparison
> - T2 (<profile-A>): performance comparison, in parallel with T1
> - T3 (<profile-B>): synthesizes T1 + T2 into a recommendation
> - T4 (<profile-C>): turns T3 into a CTO memo
>
> The dispatcher will pick up T1 and T2 now. T3 starts when both finish. You'll get a gateway ping when T4 completes. Use the dashboard or hermes kanban tail <id> to follow along.
Common patterns
Fan-out + fan-in (research โ synthesize): N research-style cards with no parents, one synthesis card with all of them as parents.
Parallel implementation + validation: one implementer card makes the change while one explorer/researcher card verifies config, docs, or source mapping. A reviewer card can depend on both. Do not make the implementer own unrelated verification just because the user mentioned both in one sentence.
Pipeline with gates: planner โ implementer โ reviewer. Each stage's parents=[previous_task]. Reviewer blocks or completes; if reviewer blocks, the operator unblocks with feedback and respawns.
Same-profile queue: N tasks, all assigned to the same profile, no dependencies between them. Dispatcher serializes โ that profile processes them in priority order, accumulating experience in its own memory.
Parallel UI/frontend lanes: When the goal touches multiple independent HTML/CSS/JS files (e.g., a dashboard page and a 2D gather view), fan out to separate subagents per file. Each lane edits its own file, then the orchestrator integrates, fixes cross-file references (theme paths, shared JSON endpoints), and publishes. This avoids merge conflicts in single-file HTML dashboards and keeps each subagent's context focused. See references/parallel-ui-lanes-and-publishing.md for the post-subagent integration checklist and rsync safety notes.
Human-in-the-loop: Any task can kanban_block() to wait for input. Dispatcher respawns after /unblock. The comment thread carries the full context.
Pitfalls
Inventing profile names that don't exist. The dispatcher silently fails to spawn unknown assignees โ the card just sits in ready forever. Always assign to a profile from your Step 0 discovery; ask the user if you're unsure.
Bundling independent lanes into one card. If the user asks for two independent outcomes, create two cards. Example: "fix blockers and check model variants" is not one fixer task; create a fixer/engineer card for the fixes and an explorer/researcher card for the variant check, then optionally gate review on both.
Over-linking because of wording. "Finally check X" may still be parallel with implementation if X is static config, docs, or source discovery. Link it after implementation only when the check depends on the implementation result.
Forgetting dependency links. If the task graph says research -> implement -> review, do not create all tasks as independent ready cards. Use parent links so implement/review cannot run before their inputs exist.
Reassignment vs. new task. If a reviewer blocks with "needs changes," create a NEW task linked from the reviewer's task โ don't re-run the same task with a stern look. The new task is assigned to the original implementer profile.
Argument order for links. kanban_link(parent_id=..., child_id=...) โ parent first. Mixing them up demotes the wrong task to todo.
Ignoring explicit user feedback to keep building infrastructure. When the user says a specific UX issue (legibility, theme switching, movement density) is "immediate priority," treat it as P0 and route it before deeper packaging/architecture work. Infrastructure polish feels productive, but shipping user-visible fixes is what matters. Create cards for the UX feedback first, then resume infrastructure lanes.
Treating status: complete as immutable when user feedback says otherwise. A state.md that says status: complete does not override a user's report that a completion criterion is actually broken. If the user says "theme switching is not working" and the Final Completion Condition requires "working UI theme switcher," the mission is not complete. Reactivate immediately: set status: active, append a reactivation cycle log, and fix the issue. Do not burn cycles on post-complete verification while the user is reporting active defects.
Don't pre-create the whole graph if the shape depends on intermediate findings. If T3's structure depends on what T1 and T2 find, let T3 exist as a "synthesize findings" task whose own first step is to read parent handoffs and plan the rest. Orchestrators can spawn orchestrators.
Tenant inheritance. If HERMES_TENANT is set in your env, pass tenant=os.environ.get("HERMES_TENANT") on every kanban_create call so child tasks stay in the same namespace.
Verifying cross-file references after directory reorganization. When subagents edit HTML/CSS/JS files and the directory structure shifts (e.g., moving files from root into web/dashboard/ and web/gather/), relative asset paths ( themes/default/theme.css, ./ops-data.json) often break. After subagents finish, the orchestrator must grep for href= and src= in moved files and fix relative paths before publishing. Subagents don't know the final publish layout โ the orchestrator does.
Destructive sync wipes needed files. Commands like rsync -av --delete will delete destination files that aren't in the source list. If you publish a directory tree piecemeal (e.g., copy web/dashboard/ first, then web/gather/ separately), --delete on the first rsync will erase the gather files before the second rsync runs. Either list all source paths in a single rsync invocation, or omit --delete and use cp -r / rsync -av without deletion when doing staged copies.
Recovering stuck workers
When a worker profile keeps crashing, hallucinating, or getting blocked by its own mistakes (usually: wrong model, missing skill, broken credential), the kanban dashboard flags the task with a โ badge and opens a Recovery section in the drawer. Three primary actions:
1. Reclaim (or hermes kanban reclaim <task_id>) โ abort the running worker immediately and reset the task to ready. The existing claim TTL is ~15 min; this is the fast path out.
2. Reassign (or hermes kanban reassign <task_id> <new-profile> --reclaim) โ switch the task to a different profile (one that exists on this setup) and let the dispatcher pick it up with a fresh worker.
3. Change profile model โ the dashboard prints a copy-paste hint for hermes -p <profile> model since profile config lives on disk; edit it in a terminal, then Reclaim to retry with the new model.
Hallucination warnings appear on tasks where a worker's kanban_complete(created_cards=[...]) claim included card ids that don't exist or weren't created by the worker's profile (the gate blocks the completion), or where the free-form summary references t_<hex> ids that don't resolve (advisory prose scan, non-blocking). Both produce audit events that persist even after recovery actions โ the trail stays for debugging.
The user has provided the following instruction alongside the skill invocation: [IMPORTANT: You are running as a scheduled cron job. DELIVERY: Your final response will be automatically delivered to the user โ do NOT use send_message or try to deliver the output yourself. Just produce your report/output as your final response and the system handles the rest. SILENT: If there is genuinely nothing new to report, respond with exactly "[SILENT]" (nothing else) to suppress delivery. Never combine [SILENT] with content โ either report your findings normally, or say [SILENT] and nothing more.]
You are the 15-minute Orchestrator for Son's Autonomous Agent Lab v1, reporting to Discord channel ID 1505805763824586952.
Durable state path: /Users/jooho-hermes/.hermes/autonomous-agent-lab/state.md
Working directory for experiment artifacts: /Users/jooho-hermes/.hermes/autonomous-agent-lab/
Preferred published web root: /Users/jooho-hermes/hermes-web/agent-pets/
Top-level directive from Son:
- The project has evolved from a personal dashboard into an INSTALLABLE PRODUCT that external Hermes users can deploy.
- The final target is a self-contained, configurable, publishable solution: "Hermes Pixel Pet Ops Office".
- Do NOT shrink the mission into a small static MVP and autonomously stop.
- The Gather.town-style 2D spatial office is a first-class feature, not a side page.
Latest UX feedback from Son (treat as immediate priority before deeper packaging work):
- Details are hard for a human to understand. Add human-first summaries, plain-language labels, and progressive disclosure: summary first, technical details second.
- Gather Town version has too many agents roaming around. Reduce default movement, add density/speed controls, cluster agents by room/task, and add focus/calm mode.
- Theme switching is not visibly working. Implement real UI theme switcher with persistence and clear visual theme changes.
Key product requirements (installable solution level):
1. Config-driven architecture: all paths, URLs, colors, names, room layouts via config.yaml. No hardcoded references to jooho-hermes.
2. Self-contained package: clear directory structure (src/, web/, config/, docs/, scripts/), install script, requirements.txt.
3. Pluggable data adapter: support multiple backends via plugin architecture.
4. Themeable frontend: CSS variables driven from config, swappable themes, plus a working UI theme switcher.
5. Multi-tenant ready: works for any Hermes instance.
6. Build/Deploy ready: Dockerfile or docker-compose, or clear static-server setup.
7. Documentation: README, architecture docs, configuration reference, contributor guide.
8. Human-comprehensible UX: plain-language summaries and progressive disclosure for technical detail.
9. Gather.town calm mode: adjustable movement density/speed and less chaotic defaults.
10. Versioned releases: CHANGELOG.md, semantic versioning, release packaging.
Mission model:
- Read state.md first before doing anything else.
- If state.md says
status: inactive or has no Current Mission, do not invent work. Return exactly: ๐ก Autonomous Agent Lab ๋๊ธฐ์ค โ Son์ด ํธ๋ฆฌ๊ฑฐ/๋ฏธ์
์ ์ฃผ๋ฉด 15๋ถ ์ฌ์ดํด์ ์์ํฉ๋๋ค.
- If state.md says
status: active, run one bounded 15-minute cycle toward the full installable solution.
- If state.md says
status: complete, verify that the Final Completion Condition in state.md is truly met. If it is not fully met, reactivate or report that state needs correction.
Cycle procedure when active:
1. Read state.md first. Extract current mission, constraints, previous cycle log, and Final Completion Condition.
2. Decide the next smallest useful step toward installable solution quality. Focus on: architecture, configurability, documentation, and clean separation of concerns.
3. Use delegate_task for independent subagent lanes when helpful.
4. Prefer concrete progress: refactor to config-driven, add install scripts, create docs, add Docker support, theme system, plugin architecture.
5. Update state.md with a new cycle log entry before final reporting.
6. Completion rule: only set status: complete when every item under state.md Final Completion Condition is satisfied. A non-installable MVP is not complete.
7. Stop/block only if Son explicitly stops/redirects, a safety boundary is reached, or a hard blocker needs Son's decision.
Link requirement (never forget):
- Every cycle report MUST include at least one direct viewable link to the published dashboard/artifact.
- The canonical URL:
http://hermes-mac-mini.tail46b3c6.ts.net:8099/agent-pets/
- Include gather town URL too:
http://hermes-mac-mini.tail46b3c6.ts.net:8099/agent-pets/gather/
Final Discord message format:
[Autonomous Agent Lab v1 / Cycle N]
๋ชฉํ:
์ํ:
๊ฒฐ๊ณผ:
๊ฒ์ฆ:
๋ค์:
์ํ:
Safety/quality rules:
- Do not handle secrets, passwords, API keys, payment, permission dialogs, or destructive commands.
- Do not claim completion without updating state.md.
- Do not rely on Discord history as durable state.
- Do not spam raw logs; summarize lane outputs and verification.
- Keep working in /Users/jooho-hermes/.hermes/autonomous-agent-lab/ and publish only to /Users/jooho-hermes/hermes-web/agent-pets/ unless the state file says otherwise.
Design/UX priorities:
- Mobile responsiveness is first-class.
- Character animation/movement is desired.
- Every cycle report must include published links.
- This is now a product engineering mission. Architecture, configurability, and documentation matter as much as visuals.
Error
RuntimeError: [Autonomous Agent Lab v1 / Cycle 53]
๋ชฉํ: Son์ UX ํผ๋๋ฐฑ(ํ
๋ง ๋ฏธ์๋, Gather ๊ณผ๋ํ ์์ง์, ๊ธฐ์ ์ค์ฌ UI)์ ๋ฐ์ status: complete์์ active๋ก ์ฌํ์ฑํํ๊ณ ๊ทผ๋ณธ ์์ธ์ ์กฐ์ฌยท๊ฐ์ ํฉ๋๋ค.
์ํ:
1. ์ฌํ์ฑํ: state.md๋ฅผ status: active๋ก ๋ณ๊ฒฝ, Cycle 53 ์ฌํ์ฑํ ๋ก๊ทธ ์ถ๊ฐ.
2. ๊ฒ์ฆ ํ์ดํ๋ผ์ธ ์คํ: Adapter ์ ์ (32 agents, 15 cron, 20 sessions, 16 events), test.sh 96/99 ํต๊ณผ.
3. ๊ทผ๋ณธ ์์ธ ์กฐ์ฌ:
- ํ
๋ง ์ฝ๋๋ ๊ตฌ์กฐ์ ์ผ๋ก ์ ํ (3ํ
๋ง, 60+ ๋ณ์, crossfade, localStorage).
- Gather calm/focus/density/speed ์ฝ๋๋ ์กด์ฌํ๋ ๊ธฐ๋ณธ๊ฐ์ด ์ฌ์ ํ ํ๋ฐํจ.
- ์์ฝ ์นด๋๋ human-first ์์๋ฅผ ํฌํจํ๋ ์ฌ์ ํ ์งํ๋ฅ /์ํ ๋ฑ์ง/์์
์ค๋ช
๋ฑ์ด ๋
ธ์ถ๋จ.
- ๊ฐ์ฅ ๊ฐ๋ฅ์ฑ ๋์ ์์ธ: ๋ธ๋ผ์ฐ์ /Service Worker ์บ์ฑ์ผ๋ก ์ธํด Son์ด ๊ตฌ๋ฒ์ ํ์ผ์ ๋ณด๊ณ ์์ ๊ฐ๋ฅ์ฑ.
4. ์ฆ์ ๊ฐ์ ์ ์ฉ:
- ์บ์ ๋ฒ์คํ
: Dashboard/Gather HTML์ CSS/JS ๋งํฌ์
?v=53 ์ถ๊ฐ.
- ํ
๋ง UX: ํ
๋ง ์ ํ ์ toast ์๋ฆผ ์ถ๊ฐ (
๐จ ํ
๋ง๊ฐ '๋คํฌ ์ต์ค'๋ก ๋ณ๊ฒฝ๋์์ต๋๋ค). applyTheme์์ ์ฟผ๋ฆฌ์คํธ๋ง ์ ์ง.
- ์์ฝ ์นด๋ ๋จ์ํ: ์นด๋ ํ๋ฉด์์ ์ํ ๋ฑ์ง, ์์
๋งํ์ , ์งํ๋ฅ ๋ฐ, "ํ๋ ๊ฐ๋" ์ ๊ฑฐ. ๋จ์ ๊ฒ: ์๋ฐํ, ์ด๋ฆ, human headline, ํ ์ค ์์ฝ, "์์ธํ ๋ณด๊ธฐ โ".
- Gather ์ง์ :
- sparse ๋ฐ๋ 0.2 โ 0.08
- ๊ธฐ๋ณธ ์๋ normal โ slow
- ์๋ ๋ฐฐ์จ 0.4 โ 0.35
- ์๋ฐํ ๊ธฐ๋ณธ ์๋ 0.15-0.4 โ 0.1-0.25
- idle ์๊ณ๊ฐ ๋ํญ ์ํฅ (calm 900โ1200, normal 700โ900)
- ์ต๋ ์๋ฐํ 16๊ฐ๋ก ํ๋์บก (blocked โ working โ ๊ธฐํ ์์ผ๋ก ์ฐ์ ํ์)
- Service Worker: ์บ์ ์ด๋ฆ
v5 โ v6์ผ๋ก ์
๋ฐ์ดํธ.
5. ํ
์คํธ ์์ : cache-busted URL์ ํ์ฉํ๋๋ก test.sh ์ ๊ทํํ์ ์
๋ฐ์ดํธ (2/3 ์๋ฃ, Gather ํ
๋ง ๋งํฌ 1๊ฐ ๋จ์).
๊ฒฐ๊ณผ:
- ์์ค ์ฝ๋์ ์ง์ ์ ์ธ ๋ฒ๊ทธ๋ ์์ผ๋, Son์ ๋ธ๋ผ์ฐ์ ๊ฐ ๊ตฌ๋ฒ์ asset์ ์บ์ฑํ๊ณ ์์ ๊ฐ๋ฅ์ฑ์ด ๊ฐ์ฅ ๋์.
?v=53 ์บ์ ๋ฒ์คํ
+ SW cache name ์
๋ฐ์ดํธ๋ก ๊ฐ์ ์๋ก๊ณ ์นจ ์ ๋.
- Dashboard ์นด๋๋ ์ด์ ์๋ฐํยท์ด๋ฆยทํ ์ค ์์ฝยท"์์ธํ ๋ณด๊ธฐ"๋ง ํ์.
- Gather Town์ ๊ธฐ๋ณธ์ ์ผ๋ก ๋ ๋๋ฆฌ๊ณ , ์๋ฐํ ์๊ฐ ์ ๋ฐ์ผ๋ก ์ค์ด๋ค๋ฉฐ, ์์ง์ ๋น๋๋ ํ๊ธฐ์ ์ผ๋ก ๋ฎ์์ง.
๊ฒ์ฆ:
- Adapter ์ ์,
ops-data.json schema 1.4, health.json healthy.
test.sh 96/99 ํต๊ณผ (3๊ฐ ์คํจ ์ค 2๊ฐ๋ ์บ์๋ฒ์คํ
์ ๊ท์ ๋ฏธ๋ฐ์์ผ๋ก ์ธํ false positive, 1๊ฐ๋ Gather ํ
๋ง ๋งํฌ ๊ฒ์ฌ ์์ ์ค).
๋ค์:
- Cycle 54์์ ๋จ์ 1๊ฐ ํ
์คํธ ์์ ,
scripts/publish.sh ์คํ์ผ๋ก ๋ณ๊ฒฝ์ฌํญ ๋ฐฐํฌ, Son์ ๋ธ๋ผ์ฐ์ ์์ ์ค์ ํ
๋ง ์ ํ ๋ฐ Gather ์ง์ ํจ๊ณผ ํ์ธ ํ์.
- ์บ์ ๋ฒ์คํ
์ ์ฉ ํ์๋ ํ
๋ง๊ฐ ์ฌ์ ํ ๋ฏธ์ธํ๊ฒ ๋ณด์ธ๋ค๋ฉด, ๋๋น์ฑ
์ผ๋ก ํ
๋ง CSS์
--bg ์ธ --accent ๋ณํ๋ฅผ ๋ ๊ทน์ ์ผ๋ก(์: ๋ฐฐ๊ฒฝ ๊ทธ๋ผ๋ฐ์ด์
์ ํ) ๊ฐํ.
์ํ: active โ Son์ UX ํผ๋๋ฐฑ์ ๋ฐ์ ์ฌํ์ฑํ, ์บ์ ๋ฌธ์ ํด๊ฒฐ ๋ฐ UI ๋จ์ํยทGather ์ง์ ์กฐ์น ์ ์ฉ ์๋ฃ.
๋งํฌ:
- Dashboard:
http://hermes-mac-mini.tail46b3c6.ts.net:8099/agent-pets/
- Gather Town:
http://hermes-mac-mini.tail46b3c6.ts.net:8099/agent-pets/gather/
|