From 8bbdcde08b3ca49045bbb1059dbad0961331ad78 Mon Sep 17 00:00:00 2001 From: Hermes Agent Date: Sun, 30 Aug 2026 01:01:13 -0500 Subject: [PATCH] =?UTF-8?q?tools-update-cron:=20sync=202026-08-30=20?= =?UTF-8?q?=E2=80=94=209=20skill(s)=20updated?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ai-vault-kb/SKILL.md | 178 +++++ cognee-brain/SKILL.md | 87 +++ hermes-agent/SKILL.md | 1080 ++------------------------ hermes-capability-lookup/SKILL.md | 46 ++ ipmi-bmc-management/SKILL.md | 175 +++++ mem0-memory/SKILL.md | 129 +++ model-capability-benchmark/SKILL.md | 120 +++ save/SKILL.md | 121 +++ youtube-knowledge-ingestion/SKILL.md | 262 ++++++- 9 files changed, 1177 insertions(+), 1021 deletions(-) create mode 100644 ai-vault-kb/SKILL.md create mode 100644 cognee-brain/SKILL.md create mode 100644 hermes-capability-lookup/SKILL.md create mode 100644 ipmi-bmc-management/SKILL.md create mode 100644 mem0-memory/SKILL.md create mode 100644 model-capability-benchmark/SKILL.md create mode 100644 save/SKILL.md diff --git a/ai-vault-kb/SKILL.md b/ai-vault-kb/SKILL.md new file mode 100644 index 0000000..31866eb --- /dev/null +++ b/ai-vault-kb/SKILL.md @@ -0,0 +1,178 @@ +--- +name: ai-vault-kb +description: "Use when writing or searching the ai_vault_kb Qdrant vault." +version: 2.0.0 +author: Hermes Agent +license: MIT +platforms: [linux] +metadata: + hermes: + tags: [qdrant, knowledge-base, ai-vault, search, rag, bm25] + related_skills: [research-knowledge-management, deep-web-research, qdrant-collection-management] +--- + +# AI Vault KB — the fleet's one vault + +`ai_vault_kb` is the single Qdrant collection holding all AI/ML knowledge: research, +pipeline state, model configs, prompts, decisions, bugs, hardware facts. One vault, +one collection — never a topic-specific collection. + +## THE ONE RULE — writes go through `ai_vault_kb.py`, nothing else + +```bash +python3 /home/n8n/bin/ai_vault_kb.py add --type --title "..." --content "..." [flags] +``` + +That helper is **the only interface that produces a usable, searchable record.** + +### Why `mcp__better_qdrant__add_documents` is FORBIDDEN for this collection + +It performs a **bare-vector upsert**. For every chunk it writes it produces: + +| | `ai_vault_kb.py add` | `mcp__better_qdrant__add_documents` | +|---|---|---| +| dense vector (unnamed slot) | yes | yes | +| **`bm25` sparse vector** | **yes** | **NO** | +| `doc_type` / `title` / `tags` | yes | **NO** | +| `trust` / `host` / `path` / `doc_id` / `pipeline_stage` | yes | **NO** | + +A point with no `bm25` slot **cannot be returned by a keyword/BM25 search** — paste an +exact error string, model filename or node name and it will never match. A point with +no `doc_type` **cannot be returned by any typed search** (`--type research`, +`--type issue`, …) or by any faceted list. It survives only in the dense half of a +hybrid query and renders as `[?] (untitled)`. + +**It looks ingested and it cannot be found.** This is not a style preference — roughly +4,700 points in this collection were created that way and had to be repaired. Do not +create more. There is no file size, no hurry and no MCP convenience that justifies it. + +If you catch yourself reaching for `add_documents` because the helper is awkward for a +big file: the helper takes `--file` and chunks it itself, with no MCP 120 s timeout. + +## Writing + +```bash +python3 /home/n8n/bin/ai_vault_kb.py add \ + --type finding --title "LTX 2.3 audio desync above 121 frames" \ + --content "..." \ + --stage t2v --tool ltx-video --host 10.0.0.202 \ + --trust official --importance 0.7 --tags "ltx-2.3,audio,desync" +``` + +Long documents: `--file /abs/path/report.md` instead of `--content` (auto-chunked, +one shared `doc_id` across the chunks). `--json` prints `{"doc_id":…, "chunks":N}`. + +| Flag | Meaning | +|---|---| +| `--type` **(required)** | `tool` `setting` `workflow` `host` `model` `technique` `issue` `decision` `research` `asset` `prompt` `finding` | +| `--title` **(required)** | what a future search will read as the headline | +| `--content` / `--file` | body text, or a file to chunk | +| `--stage` | `story` `script` `character` `keyframe` `t2v` `i2v` `upscale` `interpolate` `tts` `lipsync` `music` `assembly` `publish` `infra` | +| `--tool` `--host` `--path` `--url` `--version` | provenance; `--host` is the box the fact is about | +| `--status` | `active` `candidate` `deprecated` `broken` `planned` (default `active`) | +| `--trust` | `official` `github` `community` `social` (default `official`) | +| `--tags` | comma-separated; **tags are an exact-match keyword index** — put the slug, the filename, the error code here | +| `--importance` | 0.0–1.0 | +| `--doc-id` | append more chunks to an existing document | + +Unknown vocabulary values warn but are accepted — the schema is faceted, not strict. +A warning is not a failure; do **not** switch to the MCP tool because of one. + +### Mandatory before every write: dedup-first + +```bash +python3 /home/n8n/bin/ai_vault_kb.py search --query "" +``` + +- score **≥ 0.85** — already recorded, skip +- **0.70–0.84** — add only if meaningfully new +- **< 0.70** — always add + +### Host records + +`--type host`, one stable `--doc-id` per box. Re-add with the same `--doc-id` to update +or append a dated chunk, rather than creating a second record for the same machine. + +## Reading + +```bash +# hybrid (dense + BM25, RRF fusion) — the default, use it +python3 /home/n8n/bin/ai_vault_kb.py search --query "ltx 2.3 native audio" + +# pure keyword — exact filenames, error strings, node names +python3 /home/n8n/bin/ai_vault_kb.py search --query "ltxv-097-dev-fp8.safetensors" --mode bm25 + +# typed / faceted +python3 /home/n8n/bin/ai_vault_kb.py list --type issue --tool comfyui --limit 20 +python3 /home/n8n/bin/ai_vault_kb.py list --tag 2026-08-09-horizon-scan +python3 /home/n8n/bin/ai_vault_kb.py facet --field tool +python3 /home/n8n/bin/ai_vault_kb.py stats # points, doc_type inventory, health +python3 /home/n8n/bin/ai_vault_kb.py stale --days 30 +python3 /home/n8n/bin/ai_vault_kb.py get --id +``` + +`mcp__better_qdrant__search` is **read-only and therefore allowed**, but it is +dense-only — it silently misses anything a keyword query would have found. Prefer the +helper's `search`. Use the MCP one only when you have no shell. + +## Deleting + +```bash +python3 /home/n8n/bin/ai_vault_kb.py delete --doc-id --yes # a whole document +python3 /home/n8n/bin/ai_vault_kb.py delete --id --yes # one chunk +``` + +Per-document delete **exists**. Never +`mcp__better_qdrant__delete_collection(collection="ai_vault_kb")` — that destroys the +fleet's entire brain and there is no undo. Earlier versions of this skill described the +nuke as the only option; that was wrong. + +## Verify the write landed + +A write is not done until it is retrievable **both ways**. The BM25 leg is the one a +bare upsert cannot pass, so it is the real test: + +```bash +D= +python3 /home/n8n/bin/ai_vault_kb.py search --query "" --mode bm25 --doc-id $D +python3 /home/n8n/bin/ai_vault_kb.py list --type --doc-id $D +``` + +Zero hits on the BM25 leg means something other than `ai_vault_kb.py` wrote it. + +## Deep-research reports + +Do not ingest them by hand. `publish_report.py` (in the `deep-web-research` skill) is +the only sanctioned path — it publishes, ingests via this helper, verifies hybrid+BM25, +and writes the `.meta.json` receipt in one action. + +A `.meta.json` sidecar is a **receipt written after verification, not proof**. Sidecars +written before that rule exists claim `doc_id`s that were never upserted. If you need +to know whether a report is in the vault, ask the vault (`list --tag `), never the +directory listing. + +## Infrastructure + +| Setting | Value | +|---|---| +| Qdrant | `http://10.0.0.22:6333`, collection `ai_vault_kb` | +| Embeddings | `snowflake-arctic-embed2` on **mini, `10.0.0.30:11434`** — the vault's embedder (mini also hosts `qwen3-embedding:0.6b` for the Cognee brain; the two are separate) | +| Helper | `/home/n8n/bin/ai_vault_kb.py` (zero deps, urllib only) | +| Vectors | unnamed dense 1024-dim + named sparse `bm25` | + +**The CARE rule for mini:** every vault ingest embeds there, and mini also serves the +Cognee brain's embedder (`qwen3-embedding:0.6b`). Batch your writes, keep them bounded, +never hammer it. + +## Pitfalls + +- **Never hand-roll raw Qdrant HTTP for a write.** A `PUT /collections/ai_vault_kb/points` + with a bare vector reproduces the exact defect the MCP tool causes. Reads + (`GET /collections/...`, `POST .../points/scroll`, `.../points/count`) are fine. +- **Absolute paths** for `--file` / `--path`. +- **Collection name is exact** — `ai_vault_kb`, not `ai-vault-kb`. +- **Don't create topic-specific collections.** No `ltx-research`, no `comfyui-workflows`. +- **`fact_store` and the `memories` collection are not the vault.** Research findings, + model configs, prompt guides and infra facts all go here. +- **A search that returns nothing is a real answer.** Say "not in the vault" and go + research it — do not assume the record exists but is hiding. diff --git a/cognee-brain/SKILL.md b/cognee-brain/SKILL.md new file mode 100644 index 0000000..473cadb --- /dev/null +++ b/cognee-brain/SKILL.md @@ -0,0 +1,87 @@ +--- +name: cognee-brain +description: "Use when user says brain or cognee. Cognee memory brain (Kuzu+LanceDB)." +version: 1.0.0 +author: Hermes Agent +license: MIT +platforms: [linux] +metadata: + hermes: + tags: [cognee, brain, memory, knowledge-graph, kuzu, lancedb] + related_skills: [ai-vault-kb, save, memory-ingest] +--- + +# Cognee Brain — homelab memory layer + +The homelab memory layer ("the brain") is **Cognee** on BRAIN-MAIN at `10.0.0.23`. +It replaced the previous memory layer on 2026-08-29. Cognee ingests text, builds a +knowledge graph (entities + relationships) and a vector index side-by-side, and +exposes them through Python, CLI, MCP, and REST. + +## When to Use + +- User says "brain", "cognee", "what do we know about X", "remember this" +- Before research/infra tasks — query the brain first +- After research with concrete conclusions — write durable facts back + +## Endpoints + +- API: `http://10.0.0.23:8080` (cognee-backend, cognee/cognee:main) +- MCP: `http://10.0.0.23:8001/mcp` (cognee-mcp, cognee/cognee-mcp:main) +- Dataset: `homelab-stack` (the single shared dataset — use it everywhere) +- LLM: Ollama cloud-passthrough `http://10.0.0.23:11434/v1` (minimax-m3:cloud) +- Embed: mini `http://10.0.0.30:11434/api/embed` (qwen3-embedding:0.6b, 1024 dims) +- Graph: Kuzu (Ladybug) files under `/var/lib/cognee/system/databases` +- Vectors: LanceDB files under `/var/lib/cognee/system/databases/cognee.lancedb` + +## MCP tools (auto-discovered in Hermes as `mcp__cognee__*`) + +- `remember` — store data. Without `session_id` = permanent memory (add + cognify + pipeline, builds the graph). With `session_id` = session cache only (fast, no + extraction). Pass `data` (text) OR `filename`+`content_base64` (file upload). + `dataset_name` defaults to the client's agent-scoped dataset — ALWAYS pass + `dataset_name="homelab-stack"` explicitly. +- `recall` — search memory. `query` (required), optional `search_type` + (HYBRID_COMPLETION default; CHUNKS/GRAPH_COMPLETION/RAG_COMPLETION/etc.), + `datasets` (comma-separated), `top_k`. +- `forget` — delete. `dataset` (name), `dataset_id`, `data_id`+`dataset`, or + `everything`. + +## REST API (for curl / scripts) + +- `POST /api/v1/remember` (multipart: `data=@file` + `datasetName=homelab-stack`) +- `POST /api/v1/search` (JSON: `query`, `datasets`, `searchType`) +- `DELETE /api/v1/datasets?dataset_name=...` +- `GET /health` → `{"status":"ready","health":"healthy","version":"1.5.3-local"}` + +**Field-name gotcha:** the search API uses `query` + `searchType` (NOT +`query_text`/`query_type`). Wrong names silently fall back to the default query +"What is in the document?" and return a generic summary. + +## Write rules + +- **One dataset:** `homelab-stack`. Never create a second dataset for the same + domain — the whole point is a single combined view. +- **`remember` is add+cognify in one call** — no separate cognify step. +- **No group_id, no triplet, no temporal supersession.** Cognee uses datasets. To correct a fact, `remember` the corrected statement; + Cognee's graph merges entities by name. +- **Don't re-ingest the same content twice** — `remember` is not idempotent. +- **Embed dim is 1024** (`EMBEDDING_DIMENSIONS=1024`, qwen3-embedding:0.6b). Never let it + default to 3072. + +## Verify a write + +- `recall` with a distinctive phrase from the content; a correct answer proves + the graph has it. +- Check `docker logs cognee-backend` for `api.openai.com` / `ProviderConfigMismatch` + — zero hits means the LAN-only provider pairing held. + +## Pitfalls + +- **`remember` returns `status: completed` synchronously** (unless `background=true`). + A completed status means the graph is built — no async polling needed. +- **Search field names** are `query`/`searchType` (see above). +- **No auth** on API/MCP (`REQUIRE_AUTHENTICATION=false`) — LAN-trust only. +- **Container runs as uid 1000** — `/var/lib/cognee/{system,data}` must stay 1000:1000. +- **MCP allowed_hosts** = 10.0.0.23/42/28/15 (edit `MCP_ALLOWED_HOSTS` in compose to add hosts). +- **Start/stop:** `sudo systemctl start|stop cognee.service` (docker compose up/down). diff --git a/hermes-agent/SKILL.md b/hermes-agent/SKILL.md index 5a8a56b..d21711e 100644 --- a/hermes-agent/SKILL.md +++ b/hermes-agent/SKILL.md @@ -1,547 +1,112 @@ --- name: hermes-agent -description: "Configure, extend, or contribute to Hermes Agent." -version: 2.1.0 +description: "Use, configure, theme, extend, and orchestrate Hermes Agent." +version: 3.2.0 author: Hermes Agent + Teknium license: MIT platforms: [linux, macos, windows] metadata: hermes: - tags: [hermes, setup, configuration, multi-agent, spawning, cli, gateway, development] + tags: [hermes, setup, configuration, multi-agent, spawning, cli, gateway, themes, skins, desktop-plugins, tui-widgets, petdex, 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. +Hermes Agent is an open-source AI agent framework by Nous Research that runs in your terminal, a native desktop app, messaging platforms, and IDEs. It's in 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, Google, DeepSeek, xAI, local models, and 20+ others) and runs on Linux, macOS, Windows, 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, Hindsight, 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. +- **Self-improving through skills** — Hermes learns from experience by saving reusable procedures as skills that load into future sessions. +- **Persistent memory across sessions** — remembers who you are, your preferences, environment details, and lessons learned. Pluggable memory backends. +- **Multi-platform gateway** — the same agent runs on Telegram, Discord, Slack, WhatsApp, iMessage, Signal, Matrix, Teams, Email, and a dozen more platforms with full tool access, not just chat. +- **Many surfaces** — the same agent core drives the CLI, the Ink TUI, a native Electron desktop app, a web dashboard, and an ACP server for IDEs (VS Code / Zed / JetBrains). +- **Provider-agnostic** — swap models and providers mid-workflow; 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. +- **Extensible & themeable** — plugins, MCP servers, custom tools, webhook triggers, cron scheduling, skins that theme every surface, desktop UI plugins, TUI widgets, and pet mascots. -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. +**This skill is a hub.** The body covers identity, quick start, spawning/orchestration, and hard invariants. Everything else lives in reference files — **load the matching reference (below) before answering**; do not answer detail questions from the body alone. **Docs:** https://hermes-agent.nousresearch.com/docs/ +## Scope & Verification + +This skill is a concise operating guide, not the complete source of truth for every Hermes feature. If a Hermes feature, command, or setting is not mentioned here or in a reference, do not treat that absence as evidence that it does not exist. Check the live repository and official docs before giving a negative answer. + +Good verification targets: + +- CLI commands: `hermes --help`, `hermes --help`, and `hermes_cli/main.py` +- User documentation: https://hermes-agent.nousresearch.com/docs/ +- Source tree: https://github.com/NousResearch/hermes-agent + ## Quick Start ```bash -# Install -curl -fsSL https://raw.githubusercontent.com/NousResearch/hermes-agent/main/scripts/install.sh | bash +# Install (shell installer — sets up uv, Python, the venv, and the launcher) +curl -fsSL https://hermes-agent.nousresearch.com/install.sh | bash -# Interactive chat (default) +# Interactive chat (default surface; set display.interface: tui to launch the Ink TUI instead) hermes # Single query hermes chat -q "What is the capital of France?" -# Setup wizard +# Setup wizard / pick model+provider / health check hermes setup - -# Change model/provider hermes model - -# Check health hermes doctor + +# Other surfaces +hermes desktop # launch the native desktop app (alias: hermes gui) +hermes dashboard # web admin panel + embedded chat +hermes proxy # OpenAI-compatible local proxy backed by your OAuth provider ``` ---- - -## CLI Reference - -### Global Flags +## Key Paths ``` -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 login [--provider P] OAuth login (nous, openai-codex) -hermes logout Clear stored auth -hermes doctor [--fix] Check dependencies and config -hermes status [--all] Show component status -``` - -### 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/ - -### 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 -``` - -### 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 -``` - -### Webhooks - -``` -hermes webhook subscribe N Create route at /webhooks/ -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 Run prompt in background -/queue Queue for next turn -/steer 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 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/config.yaml Main configuration (settings — never secrets) +~/.hermes/.env API keys and secrets ONLY (under $HERMES_HOME if set) $HERMES_HOME/skills/ Installed skills -~/.hermes/sessions/ Session transcripts +~/.hermes/skins/ Custom themes (see references/themes.md) +~/.hermes/desktop-plugins/ Desktop app UI plugins (see references/desktop-plugins.md) +~/.hermes/tui-widgets/ TUI widget apps (see references/tui-widgets.md) +~/.hermes/pets/ Installed pet mascots (see references/petdex.md) +~/.hermes/state.db Canonical session store (SQLite + FTS5) +~/.hermes/sessions/ Gateway routing index, request dumps, *.jsonl 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//` with the same layout. +Profiles use `~/.hermes/profiles//` with the same layout. When a profile is active, resolve the real home from `$HERMES_HOME` — never hardcode `~/.hermes`. -### Config Sections +## Routing Table — load the reference for the task -Edit with `hermes config edit` or `hermes config set section.key value`. +| User wants... | Load | +|---|---| +| CLI commands, subcommands, flags, "how do I run X" | `references/cli-reference.md` | +| In-session slash commands | `references/slash-commands.md` | +| Provider setup, API keys, OAuth | `references/providers-and-models.md` | +| config.yaml sections, toolsets, voice/STT/TTS | `references/configuration.md` | +| AGENTS.md / .hermes.md / CLAUDE.md project rules | `references/project-context-files.md` | +| Secret redaction, PII, approval modes, "reset permissions" | `references/security-privacy.md` | +| Delegation, cron, curator, kanban | `references/background-systems.md` | +| MCP servers (add, catalog, `hermes mcp`) | `references/native-mcp.md` | +| Webhook routes and event-driven runs | `references/webhooks.md` | +| A custom theme/skin ("synthwave theme", "change the gold ●") | `references/themes.md` + `templates/skin.yaml` | +| A desktop app UI element (pane, widget, ⌘K command, page) | `references/desktop-plugins.md` + `templates/plugin.js` | +| A live TUI panel or modal widget (ticker, clock, dashboard) | `references/tui-widgets.md` + `templates/clock.mjs` | +| Pet mascots — install, select, scale, diagnose | `references/petdex.md` | +| Windows-specific issues (keybinds, WinError 10106, BOM) | `references/windows-quirks.md` | +| Debugging: voice, tools missing, gateway, aux models | `references/troubleshooting.md` | +| Contributing code: adding tools, slash commands, tests | `references/contributor-guide.md` | +| delegate_task "capped at N" reports | `references/delegate-task-concurrency-diagnosis.md` | +| "Can app X use my Nous Portal subscription/OAuth?" | `references/portal-auth-for-third-party-apps.md` | +| Environment-specific failures on THIS host (cloned profiles, Ollama routing, auth exhaustion, gateway quirks) | `references/session-pitfalls.md` | -| 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) | - -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 login --provider 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. - -### Configuration Duplication Issues - -When editing Hermes configuration files directly (especially profile configs), watch for duplicated values that can cause parsing issues: - -**Pitfall**: Duplicate `enabled: true true` (or similar) values in config.yaml files -**Symptoms**: Configuration loading errors, inconsistent behavior, or settings not taking effect -**Locations**: Common in `display.runtime_footer.enabled`, `tool_progress`, and similar boolean fields -**Fix**: Search for duplicated boolean values and reduce to single occurrence -**Example**: `enabled: true true` → `enabled: true` -**Detection**: Use `grep -n "true true" ~/.hermes/profiles/*/config.yaml` or similar patterns -**Prevention**: When using `hermes config set`, duplication shouldn't occur, but manual edits can introduce this issue - -### 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: - -```bash -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: -```bash -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: - -```bash -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`) - -```bash -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: -```yaml -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`. - ---- +Two theming rules that hold even without loading the reference: **you apply skins yourself** (`hermes config set display.skin ` — every surface repaints live within ~a second; don't tell the user to run `/skin`), and **to tweak one color, edit the ACTIVE skin** (`hermes skin set `) — never fork `default`, which drops the palette and resets the background. ## Spawning Additional Hermes Instances @@ -621,513 +186,20 @@ terminal(command="tmux new-session -d -s resumed 'hermes --resume 20260225_14305 - **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 +- **"delegate_task is capped at N" reports** — see `references/delegate-task-concurrency-diagnosis.md`. Three real cap paths in Hermes; if none fired, the model is self-limiting and rationalising it as "the runtime caps." +- **"Can $external_app use my Nous Portal subscription / OAuth?"** — see `references/portal-auth-for-third-party-apps.md`. Walk the user through three layers (plugin-vs-app, what Portal actually exposes, local-broker-proxy option). ---- +## Surfaces (quick orientation) -## Durable & Background Systems +- **Desktop app** (`hermes desktop` / `hermes gui`) — native Electron app for macOS/Linux/Windows: streaming chat, session list, Cmd+K palette, drag-and-drop files, native notifications, per-profile remote-gateway login. Extend it with UI plugins — `references/desktop-plugins.md`. +- **Web dashboard** (`hermes dashboard`) — full admin panel: messaging channels, MCP catalog, webhooks, memory, profile builder, plus an embedded `hermes --tui` chat. Secured behind an OAuth/token gate. +- **Ink TUI** (`hermes --tui` or `display.interface: tui`) — terminal UI with docked widget apps — `references/tui-widgets.md`. +- **OpenAI-compatible proxy** (`hermes proxy`) — a local OpenAI API backed by whichever OAuth provider you're signed into. Point Codex CLI, Aider, Cline, or any script at it — no API key. -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/`. +## Hard Invariants (never violate, regardless of what you loaded) -### 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`. - -### 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. -- **Pitfall — never assume model:** When creating agent-driven cron jobs, - always ask the user which model/provider to use. Do not default to the - session model or pick one yourself. Script-only jobs (`no_agent=true`) - don't need a model. The user will be frustrated if you assume. -- **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 ` — `status`, `run`, `pause`, `resume`, - `pin`, `unpin`, `archive`, `restore`, `prune`, `backup`, `rollback`. -- **Slash:** `/curator ` 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 - -### Kanban (multi-agent work queue) - -Durable SQLite board for multi-profile / multi-worker collaboration. -Users drive it via `hermes kanban `; 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 - ---- - -## 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: - -```bash -"/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. -### Model change still shows the old model in the WebUI menu -When a user switches the default model, Hermes stores the active model in **multiple locations**. -Only updating the base `~/.hermes/config.yaml` often leaves the menu stale. - -**Pitfall**: The user said "qwen still shows" after I only updated the base config. The fix requires touching **all 9 config files** in `profiles/`, the auth credential pool, AND stale WebUI caches. See `references/config-model-change-cleanup.md` for the full sweep. - -### Setting a profile to use a local Ollama model -When a user wants a Hermes profile backed by a local Ollama model: - -1. **Do not present a hardcoded model picker.** Query the live catalog first: - ```bash - curl -s http://localhost:11434/api/tags | python3 -c "import sys,json; d=json.load(sys.stdin); print('\n'.join(m['name'] for m in d.get('models',[])))" - ``` -2. **Let the user pick only from that list** — or ask them to type the exact name. -3. **Verify/correct the profile's `base_url`.** The profile may have inherited a remote vLLM/DGX endpoint (e.g., `http://10.0.0.26:8000/v1`). For Ollama, `model.base_url` must be `http://localhost:11434/v1` (or wherever Ollama's OpenAI-compatible endpoint runs) and `model.provider` should be `custom`/`custom:ollama`. - -See `hermes-config-bulk-update` skill reference `local-ollama-profile-model-selection.md`. - -### Model/provider issues -1. `hermes doctor` — check config and dependencies -2. `hermes login` — re-authenticate OAuth providers -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. - -### Model change still shows the old model in the WebUI menu -When a user switches the default model, Hermes stores the active model in **multiple locations**. -Only updating the base `~/.hermes/config.yaml` often leaves the menu stale. - -**Pitfall**: The user said "qwen still shows" after I only updated the base config. The fix requires touching **all 9 config files** in `profiles/`, the auth credential pool, AND stale WebUI caches. See `references/config-model-change-cleanup.md` for the full sweep. - -### Setting a profile to use a local Ollama model -When a user wants a Hermes profile backed by a local Ollama model: - -1. **Do not present a hardcoded model picker.** Query the live catalog first: - ```bash - curl -s http://localhost:11434/api/tags | python3 -c "import sys,json; d=json.load(sys.stdin); print('\n'.join(m['name'] for m in d.get('models',[])))" - ``` -2. **Let the user pick only from that list** — or ask them to type the exact name. -3. **Verify/correct the profile's `base_url`.** The profile may have inherited a remote vLLM/DGX endpoint (e.g., `http://10.0.0.26:8000/v1`). For Ollama, `model.base_url` must be `http://localhost:11434/v1` (or wherever Ollama's OpenAI-compatible endpoint runs) and `model.provider` should be `custom`/`custom:ollama`. - -See `hermes-config-bulk-update` skill reference `local-ollama-profile-model-selection.md`. - -### Model/provider issues -1. `hermes doctor` — check config and dependencies -2. `hermes login` — re-authenticate OAuth providers -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. -| All profile configs | Same keys in every `profiles/*/config.yaml` | Script patch or per-profile CLI | -| Auth credential pool | Remove stale `custom:` entries | Edit `~/.hermes/auth.json` → `credential_pool` | -| WebUI model cache | `active_provider`, `default_model`, `configured_model_badges` | Edit or delete `~/.hermes/webui/models_cache.json` | -| Auto-regenerated caches | `models_dev_cache.json`, `context_length_cache.yaml`, `.skills_prompt_snapshot.json`, `model_catalog.json` | Delete — they regenerate on next run | - -**Quick verification script** (run inside `execute_code`): -```python -import os, glob, json, re -home = os.environ['HOME'] -for p in [f"{home}/.hermes/config.yaml"] + glob.glob(f"{home}/.hermes/profiles/*/config.yaml"): - with open(p) as f: - content = f.read() - if re.search(r'provider:\s*qwen-397b|base_url:\s*http://10\.0\.0\.26:8080', content): - print(f"STALE: {p}") - else: - print(f"OK: {os.path.basename(os.path.dirname(p)) if '/profiles/' in p else 'BASE'}") -``` - -The WebUI menu badge is driven by `models_cache.json`, which contains: -- `"active_provider"` — the provider string shown in the UI -- `"default_model"` — the model name shown in the UI -- `"configured_model_badges"` — the "Primary" label mapping - -If you change the config but the menu still shows the old model, the cache is stale. The safest fix is to delete `models_cache.json` and let the WebUI regenerate it after a browser reload. - -### Model change still shows the old model in the WebUI menu -When a user switches the default model, Hermes stores the active model in **multiple locations**. -Only updating the base `~/.hermes/config.yaml` often leaves the menu stale. - -**Pitfall**: The user said "qwen still shows" after I only updated the base config. The fix requires touching **all 9 config files** in `profiles/`, the auth credential pool, AND stale WebUI caches. See `references/config-model-change-cleanup.md` for the full sweep. - -### Setting a profile to use a local Ollama model -When a user wants a Hermes profile backed by a local Ollama model: - -1. **Do not present a hardcoded model picker.** Query the live catalog first: - ```bash - curl -s http://localhost:11434/api/tags | python3 -c "import sys,json; d=json.load(sys.stdin); print('\n'.join(m['name'] for m in d.get('models',[])))" - ``` -2. **Let the user pick only from that list** — or ask them to type the exact name. -3. **Verify/correct the profile's `base_url`.** The profile may have inherited a remote vLLM/DGX endpoint (e.g., `http://10.0.0.26:8000/v1`). For Ollama, `model.base_url` must be `http://localhost:11434/v1` (or wherever Ollama's OpenAI-compatible endpoint runs) and `model.provider` should be `custom`/`custom:ollama`. - -See `hermes-config-bulk-update` skill reference `local-ollama-profile-model-selection.md`. - -### Model/provider issues -1. `hermes doctor` — check config and dependencies -2. `hermes login` — re-authenticate OAuth providers -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. -| All profile configs | Same keys in every `profiles/*/config.yaml` | Script patch or per-profile CLI | -| Auth credential pool | Remove stale `custom:` entries | Edit `~/.hermes/auth.json` → `credential_pool` | -| WebUI model cache | `active_provider`, `default_model`, `configured_model_badges` | Edit or delete `~/.hermes/webui/models_cache.json` | -| Auto-regenerated caches | `models_dev_cache.json`, `context_length_cache.yaml`, `.skills_prompt_snapshot.json`, `model_catalog.json` | Delete — they regenerate on next run | - -**Quick verification script** (run inside `execute_code`): -```python -import os, glob, json, re -home = os.environ['HOME'] -for p in [f"{home}/.hermes/config.yaml"] + glob.glob(f"{home}/.hermes/profiles/*/config.yaml"): - with open(p) as f: - content = f.read() - if re.search(r'provider:\s*qwen-397b|base_url:\s*http://10\.0\.0\.26:8080', content): - print(f"STALE: {p}") - else: - print(f"OK: {os.path.basename(os.path.dirname(p)) if '/profiles/' in p else 'BASE'}") -``` - -The WebUI menu badge is driven by `models_cache.json`, which contains: -- `"active_provider"` — the provider string shown in the UI -- `"default_model"` — the model name shown in the UI -- `"configured_model_badges"` — the "Primary" label mapping - -If you change the config but the menu still shows the old model, the cache is stale. The safest fix is to delete `models_cache.json` and let the WebUI regenerate it after a browser reload. - -### 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: -```bash -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` - -### Platform-specific issues -- **Discord bot silent**: Must enable **Message Content Intent** in Bot → Privileged Gateway Intents. -- **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: -```bash -hermes config set auxiliary.vision.provider -hermes config set auxiliary.vision.model -``` - ---- - -## Where to Find Things - -| 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/` | - -## Support Files - -- `references/feature-lifecycle.md` — Evidence-based pattern for investigating whether a feature is actually being used and performing full removal (not just disabling). - -## 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`:** -```python -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 - -```bash -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: - -```bash -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: - -```python -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_` 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\n\n- **Never break prompt caching** — don't change context, tools, or system prompt mid-conversation\n- **Message role alternation** — never two assistant or two user messages in a row\n- Use `get_hermes_home()` from `hermes_constants` for all paths (profile-safe)\n- Config values go in `config.yaml`, secrets go in `.env`\n- New tools need a `check_fn` so they only appear when requirements are met\n\n### Configuration Duplication Issues & Comprehensive Updates\n\nWhen editing Hermes configuration files directly (especially profile configs), watch for duplicated values that can cause parsing issues:\n\n**Pitfall**: Duplicate `enabled: true true` (or similar) values in config.yaml files \n**Symptoms**: Configuration loading errors, inconsistent behavior, or settings not taking effect \n**Locations**: Common in `display.runtime_footer.enabled`, `tool_progress`, and similar boolean fields \n**Fix**: Search for duplicated boolean values and reduce to single occurrence \n**Example**: `enabled: true true` → `enabled: true` \n**Detection**: Use `grep -n \"true true\" ~/.hermes/profiles/*/config.yaml` or similar patterns \n**Prevention**: When using `hermes config set`, duplication shouldn't occur, but manual edits can introduce this issue\n\n**User Preference - Update ALL Locations**: When making configuration changes that affect shared settings (like model, provider, or display settings), always update ALL locations:\n- Base config (`~/.hermes/config.yaml`)\n- All profile configs (`~/.hermes/profiles/*/config.yaml`)\n- Auth credential pool (`~/.hermes/auth.json`)\n- Stale caches (WebUI model cache, auto-generated caches)\n\n**Example from session**: When enabling UI display enhancements per user request for more visibility, we updated:\n- `display.tool_progress_command: true` (show tool progress as executable commands)\n- `display.tool_preview_length: 150` (show first 150 chars of tool output previews)\n- `display.show_cost: true` (display token usage and estimated costs)\n- `display.final_response_markdown: preserve` (preserve markdown formatting in responses)\n- Fixed `display.runtime_footer.enabled: true true` → `enabled: true` (resolved duplication issue)\n\nThese changes were applied to both main config and active profile config following the user's preference for comprehensive updates. +- **Never break prompt caching** — don't change past context, toolsets, or the system prompt mid-conversation. The only exception is context compression. +- **Message role alternation** — never two assistant or two user messages in a row; only `tool` results can repeat. +- **Secrets in `.env`, settings in `config.yaml`** — never tell a user to put a non-credential setting in `.env`. +- **Profile-safe paths** — `get_hermes_home()` in code, `$HERMES_HOME` when resolving paths in a session. +- **Never hand-edit `config.yaml` for the user** — use `hermes config set KEY VAL`; a stray indent can corrupt the file and break the live gateway. diff --git a/hermes-capability-lookup/SKILL.md b/hermes-capability-lookup/SKILL.md new file mode 100644 index 0000000..a9fc3b1 --- /dev/null +++ b/hermes-capability-lookup/SKILL.md @@ -0,0 +1,46 @@ +--- +name: hermes-capability-lookup +description: "Use when asked if Hermes supports X or how to integrate X." +version: 1.0.0 +author: Hermes Agent +metadata: + hermes: + related_skills: [hermes-agent, native-mcp, searxng-smart-search] +--- + +# Hermes Capability Lookup + +Trigger: "does Hermes have X?", "can Hermes use X?", "is there a skill for X?", "how do I integrate X with Hermes?" + +## Lookup workflow (in order) + +1. **Local profile skills** — `search_files` pattern `**` in `~/.hermes/profiles//skills/` plus `skills_list`. Zero hits = not installed locally (may still exist upstream). +2. **Official docs** — hermes-agent.nousresearch.com/docs. Key pages: `/docs/user-guide/features/memory-providers` (bundled memory providers), `/docs/reference/skills-catalog`, `/docs/integrations/`. Read via `mcp_searxng_web_url_read` (one `url` per call). +3. **Upstream repo** — github.com/NousResearch/hermes-agent. SearXNG query: `site:github.com NousResearch hermes-agent `. GitHub issue bodies are extractable via web_url_read (nav chrome dominates but the body is in the result). +4. **If not bundled** — identify integration paths (below), present options with a recommendation (user requires Recommended + Why on every options list). + +## Bundled memory providers (9, as of 2026-08) + +Honcho, OpenViking, Mem0, Hindsight, Holographic, RetainDB, ByteRover, Supermemory, Memori. + +- Only ONE external provider active at a time; built-in MEMORY.md/USER.md always active. +- `hermes memory setup` = interactive picker; `hermes memory status`; `hermes memory off`. +- Full comparison table on the docs memory-providers page. + +## Integration paths for external memory systems + +1. **MCP registration** (config-only, minutes) — add the external tool's MCP server under `mcp_servers` in config.yaml (see native-mcp skill). Hermes gets the tools immediately. Caveat: capture side may not run — e.g. claude-mem's worker only fills from Claude Code hooks, so Hermes gets read-only search over whatever Claude Code recorded. +2. **Custom memory-provider plugin** — implement Hermes' MemoryProvider contract: `prefetch()`/`queue_prefetch()`, `sync_turn()`, `on_session_end()`, `on_memory_write(action, target, content)`. Docs: `/docs/developer-guide/memory-provider-plugin`. This is how third-party providers wire in (e.g. the local cognee integration, GitHub issue #14368). +3. **HTTP API bridge** — if the external system exposes a REST API (claude-mem worker API), a provider plugin or script can POST observations and GET search results. + +## Pitfalls + +- `mcp_searxng_web_url_read` takes `url` (singular string), NOT `urls` (list). One URL per call; batch multiple pages as parallel calls. +- "Not bundled" is a dated fact — re-verify against current docs before asserting. +- GitHub issue pages via web_url_read return heavy nav chrome; the issue body is still in the result — search result descriptions often already carry the key sentence. + +## References + +- `references/hook-system.md` — verified Hermes hook taxonomy: full VALID_HOOKS set, the "no end-of-turn hook" finding, `pre_verify` gate (file-edit + 3-nudge cap), shell-hook allowlist consent, response shapes, SOUL/USER.md paths +- `references/claude-mem-integration.md` — claude-mem: architecture, worker REST API, MCP tools, Hermes integration options +- `references/cognee-status.md` — cognee in Hermes: not bundled, issue #14368 canonical reference, lessons for Lance/Kuzu-backed providers diff --git a/ipmi-bmc-management/SKILL.md b/ipmi-bmc-management/SKILL.md new file mode 100644 index 0000000..df25987 --- /dev/null +++ b/ipmi-bmc-management/SKILL.md @@ -0,0 +1,175 @@ +--- +name: ipmi-bmc-management +description: Use when working with IPMI/BMC out-of-band server mgmt. +version: 1.0.0 +author: Hermes Agent +license: MIT +platforms: [linux] +metadata: + hermes: + tags: [ipmi, bmc, redfish, supermicro, out-of-band, hardware, firmware] + related_skills: [proxmox-lxc-deployment, truenas] +--- + +# IPMI / BMC Out-of-Band Management + +Manage servers out-of-band via their BMC (Baseboard Management Controller). +Covers read-only inventory, sensor/thermal readout, firmware version checks, +and the modern Redfish REST API. Credentials live in fact_store, never in this +skill. + +## Install + +```bash +sudo apt-get install -y ipmitool # CLI (also: freeipmi-tools) +``` + +## ipmitool — read-only inventory + +```bash +ipmitool -I lanplus -H -U -P -C 3 +``` + +Useful read-only commands: +- `mc info` — BMC identity (manufacturer, product ID, firmware rev, IPMI version) +- `fru print` — board serial, mfg date, product info +- `sensor list` / `sdr list` — thermals, voltages, fans, GPU temps +- `chassis status` — power state, fault flags, power-restore policy +- `power status` — on/off +- `lan print` — BMC network config (IP, MAC, gateway, cipher suites) +- `user list` — configured BMC accounts +- `sel info` / `sel list` — system event log (check for full/overflow) + +## CRITICAL: Supermicro cipher-suite quirk + +Supermicro BMCs (H12SSL-i and similar) FAIL the default RMCP+ cipher suite +(17 / SHA256) with: + +``` +Error in open session response message : invalid role +Error: Unable to establish IPMI v2 / RMCP+ session +``` + +**Fix: force cipher suite 3** with `-C 3`. This is the single most common +failure when scripting Supermicro IPMI. `-C 17` and `-L ADMINISTRATOR` do NOT +help — only `-C 3` works. IPMI 1.5 (`-I lan`) also works but is insecure. + +## Redfish — the modern API (preferred for firmware inventory) + +Supermicro BMCs expose a full Redfish REST API. Use it for firmware version +checks — it's cleaner than raw OEM IPMI commands (which often return +"Request data length invalid"). + +```bash +# Root (confirms Redfish + vendor) +curl -sk -u 'USER:PASS' https:///redfish/v1/ + +# Firmware inventory — BMC, BIOS, CPLD versions in one shot +curl -sk -u 'USER:PASS' https:///redfish/v1/UpdateService/FirmwareInventory + +# Per-component version +curl -sk -u 'USER:PASS' https:///redfish/v1/UpdateService/FirmwareInventory/BMC +curl -sk -u 'USER:PASS' https:///redfish/v1/UpdateService/FirmwareInventory/BIOS + +# System info (BiosVersion, Model, ProcessorSummary) +curl -sk -u 'USER:PASS' https:///redfish/v1/Systems/1 +``` + +FirmwareInventory members are named `BMC`, `BIOS`, `Motherboard_CPLD_1`, +`GPU` etc. Each returns `Version`, `Updateable`, `ReleaseDate`. GPUs show +`Version: None` (not firmware-managed via BMC). + +## Firmware currency check + +1. Read current versions via Redfish FirmwareInventory (BMC + BIOS + CPLD). +2. Cross-check against Supermicro download center: + `https://www.supermicro.com/en/support/resources/downloadcenter/firmware/MBD-/BIOS` + (search result snippets list "BIOS Revision: X.Y" and "BMC Firmware Revision: X.Y.Z"). +3. Report the gap. Note: Supermicro BMC downgrades are NOT supported after + security updates — upgrades are one-way. + +## Firmware UPDATE (flash) — method decision + +**The H12/H12SS bundle ships SAA (SuperServer Automation Assistant) UEFI, NOT +SUM.** SUM is the older in-band updater; the H12 firmware zip contains +`SAA.efi` + `flash.nsh`. Two hard rules from Supermicro's own package readme: +1. **"Using AFU tool will end up with the BIOS corruption. It should never be + used!"** — the AMI AFU flasher is forbidden on H12. +2. **BIOS flash on H12SS-and-newer MUST go through the BMC** — DOS/EFI + standalone BIOS flashing is no longer supported. The BMC web UI uploads the + .bin to the BMC flashdisk and the BMC does the flash. + +| Method | License? | Notes | +|---|---|---| +| **BMC web UI → Maintenance → Firmware Management** | No | The supported path for BOTH BMC and BIOS on H12. Upload the .bin; BMC does the flash. ~2.5 min BMC, a few min BIOS. | +| SAA UEFI shell (`flash.nsh `) | No | In-band alternative; requires booting host into EFI shell. | +| Redfish SimpleUpdate | YES (DCMS) | Returns `SMC.1.0.OemLicenseNotPassed` — "Not licensed... DCMS needed" | +| Redfish OEM SmcUpdateService.Install | No | Available (Targets + InstallOptions) but web UI is the documented path | +| ipmitool hpm upgrade | No | Only for .hpm images; Supermicro ships .bin | + +**Probe the license block before assuming Redfish works:** +`curl -sk -u 'U:P' https:///redfish/v1/UpdateService/SimpleUpdateActionInfo` +— if it returns `OemLicenseNotPassed`, SimpleUpdate is out. + +**Upgrade order:** BMC first (closes BMC CVEs, one-way), then BIOS (closes +CPU microcode/AGESA CVEs). BIOS flash requires host OFF. Apply BMC and BIOS in +one session — mismatched BIOS/BMC version pairs can hang at POST code FF. + +**Recovery safety net:** Supermicro BMCs keep quad-image redundancy — +FirmwareInventory lists `BMC/Backup_BMC/Golden_BMC/Staging_BMC` (same for +BIOS). A failed flash can boot from Backup/Golden via the web UI "Recover" +option or Redfish OEM Install with `InstallOptions=["Recover"]`. + +**Post-flash checks:** re-test the cipher suite (newer BMC firmware may switch +from cipher 3 to 17/SHA256), re-verify login, and re-read FirmwareInventory to +confirm the new version. A DHCP BMC may also change IP after reset — re-find by +MAC (fixed) via ARP scan if the IP moves. + +## Security advisories to check + +- Supermicro Security Center: https://www.supermicro.com/en/support/security_center +- Supermicro BMC advisories (e.g. July 2026 CVE-2026-3821, CVSS 8.8, SMASH + arbitrary code execution — fix is a BMC firmware update). +- AMD bulletins (e.g. AMD-SB-7054 / CVE-2025-54502, CVSS 7.1, affects EPYC 7002 + "Rome" — fix is RomePI 1.0.0.P AGESA via BIOS update). Cross-check the board's + CPU generation against the bulletin's affected list. + +## SEL (system event log) health + +`sel info` shows `Percent Used` and `Overflow`. If 100% full with +`Overflow: true`, new events are being DROPPED. Clearing is a WRITE op — +confirm with the operator before `sel clear`. Supermicro OEM events often +decode as `Unknown #0xff` (raw vendor events, not standard IPMI). + +## Security notes + +- Legacy IPMI (RMCP+ cipher 3) is weak; prefer Redfish over HTTPS where possible. +- Supermicro publishes BMC security advisories (e.g. July 2026, CVE-2026-3821, + up to 8.8 CVSS). Old BMC firmware predates these — flag for update. +- `lan print` shows `Bad Password Threshold` (default 3) and lockout interval — + repeated bad attempts lock the account. Don't brute-force. + +## Pitfalls + +- **Cipher 17 fails on Supermicro** — always `-C 3` (see above). +- **Raw OEM commands** (`raw 0x30 0x90 ...`) for BIOS version return + "Request data length invalid" on many Supermicro boards — use Redfish instead. +- **BMC up ≠ host up.** The BMC can report "System Power: on" while the host + OS is unreachable (no route to host / ARP INCOMPLETE). Verify host reachability + separately (SSH port probe) before assuming the box is down. +- **Credentials in fact_store, not here.** Look up the BMC IP/user/pass in + fact_store before connecting; never hardcode passwords in a skill. +- **Supermicro download-center PDFs are bot-blocked (403).** Release-notes PDFs + and the firmware download page return 403 to curl/SearXNG/browser. BUT the + firmware itself is freely mirrored and NOT blocked — download the actual + .bin files from `https://ftp.abacus.cz/support/FW/MB/SUPERMICRO/BIOS//` + (or `https://sm.t3x.net/`), then verify SHA256. Thomas-Krenn also mirrors + tested-stable bundles at `https://www.thomas-krenn.com/en/download?product=` + (their `/redx/tools/mb_download.php/...` links are curl-able). Only the + Supermicro.com release-notes PDFs stay behind the wall — use Thomas-Krenn wiki + changelogs or search-result snippets for those. + +## References + +- `references/h12ssl-i-firmware-update.md` — H12SSL-i concrete firmware data, + security drivers, license-block evidence, known issues, changelog sources. diff --git a/mem0-memory/SKILL.md b/mem0-memory/SKILL.md new file mode 100644 index 0000000..4cd77a0 --- /dev/null +++ b/mem0-memory/SKILL.md @@ -0,0 +1,129 @@ +--- +name: mem0-memory +description: "Use when configuring Mem0 as Hermes' memory provider." +version: 1.0.0 +author: Hermes Agent +license: MIT +metadata: + hermes: + tags: [mem0, memory, qdrant, ollama, hermes, migration] + related_skills: [hermes-agent, holographic-memory, hermes-config-bulk-update] +--- + +# Mem0 Memory Provider for Hermes Agent + +Mem0 is Hermes' server-side LLM fact-extraction memory provider with semantic +search and automatic deduplication. Plugin lives at +`~/.hermes/hermes-agent/plugins/memory/mem0/` (v1.3.0+). It is the sibling of +`holographic-memory` (local SQLite) — see that skill for the provider being +replaced in a migration. + +## When to Use + +- Setting up mem0 as the memory provider (any of its 3 modes) +- Migrating from holographic (or another provider) to mem0 +- Troubleshooting mem0 OSS mode (Qdrant/embedder/LLM wiring) +- Understanding mem0's tools vs holographic's `fact_store` + +## Three Connection Modes + +| Mode | Trigger | Needs | +|------|---------|-------| +| **Platform** (cloud) | `MEM0_API_KEY` set | API key from app.mem0.ai | +| **Self-hosted server** | `host` set (Docker dashboard URL) | Mem0 server + optional `X-API-Key` | +| **OSS** (in-process) | `mode: oss` | own LLM + embedder + vector store | + +Precedence in the plugin: **OSS > host > platform**. Setting `host` routes to +self-hosted HTTP; `mode: oss` overrides and ignores `host`. + +## OSS Mode Config (mem0.json) + +Config lives in `$HERMES_HOME/mem0.json` (per-profile). Only the secret +`MEM0_API_KEY` belongs in `.env`. Structure: + +```json +{ + "mode": "oss", + "oss": { + "llm": {"provider": "ollama", "config": {"model": "qwen3:8b", "ollama_base_url": "http://localhost:11434"}}, + "embedder": {"provider": "ollama", "config": {"model": "snowflake-arctic-embed2:latest", "ollama_base_url": "http://10.0.0.30:11434", "embedding_dims": 1024}}, + "vector_store": {"provider": "qdrant", "config": {"url": "http://10.0.0.161:6333", "collection_name": "mem0_general"}} + } +} +``` + +Supported OSS providers (from `_oss_providers.py`): +- LLM: `openai`, `ollama` +- Embedder: `openai`, `ollama` +- Vector store: `qdrant` (local `path` or server `url`), `pgvector` + +## CRITICAL PITFALL — embedding_dims not auto-set + +The plugin's `KNOWN_DIMS` map only lists `nomic-embed-text` (768) and OpenAI +models (`text-embedding-3-small` 1536, `-large` 3072, `ada-002` 1536). It does +**NOT** include `snowflake-arctic-embed2` (1024 dims). + +Consequence: `hermes memory setup mem0 --mode oss` will NOT write +`embedding_dims` for snowflake-arctic-embed2, so mem0 creates the Qdrant +collection with wrong/unknown dims and writes fail. + +Fix: set `embedding_dims` manually in `mem0.json` (or run setup then patch the +file). Verify the actual dims with: +```bash +curl -s http://:11434/api/show -d '{"name":"snowflake-arctic-embed2:latest"}' \ + | python3 -c "import sys,json; print(json.load(sys.stdin)['model_info']['bert.embedding_length'])" +``` +The plugin's `_recreate_collection_if_dims_changed` will delete a stale +collection when dims change, so a wrong first attempt self-heals on the next +correct config — but only if `embedding_dims` is eventually set. + +## Per-Profile Isolation on a Shared Qdrant + +Holographic was per-profile (own `memory_store.db`). When all profiles point at +ONE shared Qdrant, the default collection name (`mem0`) would pool every +profile's memory together. Preserve isolation with per-profile +`collection_name` (e.g. `mem0_general`, `mem0_finance`, `mem0_base`). + +## Tools (vs holographic) + +| mem0 | holographic | +|------|-------------| +| `mem0_search` | `fact_store search` | +| `mem0_add` (verbatim, no extraction) | `fact_store add` | +| `mem0_update` | `fact_store update` | +| `mem0_delete` | `fact_store remove` | + +No `fact_feedback` equivalent — mem0 has no trust scoring. `mem0_add` stores +verbatim; LLM extraction happens via `sync_turn`, not `mem0_add`. + +## Migration Checklist (holographic → mem0) + +1. Write per-profile `mem0.json` (OSS mode) with `embedding_dims` set manually. +2. `hermes config set memory.provider mem0` per profile (base + all profiles). +3. Remove holographic: delete plugin dir + all `memory_store.db` files + the + `plugins.hermes-memory-store` block (auto_extract/hrr_dim) from configs. +4. Update tool references: MEMORY.md rules and `save`/`cognee-brain` skills + reference `fact_store`/`fact_feedback` — they orphan on switch. +5. Smoke test ONE profile first: `mem0_add` → `mem0_search` → `mem0_delete`, + then confirm the Qdrant collection exists with correct dims before fanning out. + +## Pitfalls + +- **Network coupling.** mem0 OSS depends on the Qdrant host and embedder host + being reachable. Holographic was fully local (SQLite). If either service is + down, memory writes fail. +- **Circuit breaker.** "Mem0 temporarily unavailable" = 5 consecutive failures + tripped the breaker; resets after 2 minutes. +- **`mem0_add` is verbatim.** No LLM extraction on that path — use `sync_turn` + for extraction. +- **Cloud LLM fact-extraction quality varies.** Tested (2026-08): `kimi-k2.6:cloud` + and `minimax-m3:cloud` preserved full facts including temporal detail; + `deepseek-v4-pro:cloud` dropped "in March"; `glm-5.2:cloud` dropped both + "red" and "in March". For memory extraction, prefer a model that keeps + temporal context. +- **`gemini-3-flash-preview` retired 2026-07-15** — do not select it. + +## References + +- `references/oss-config-and-dims.md` — full OSS config schema, KNOWN_DIMS map, + and the embedding-dims gotcha with verification commands. diff --git a/model-capability-benchmark/SKILL.md b/model-capability-benchmark/SKILL.md new file mode 100644 index 0000000..b6ff41c --- /dev/null +++ b/model-capability-benchmark/SKILL.md @@ -0,0 +1,120 @@ +--- +name: model-capability-benchmark +description: "Use when picking a model for a capability. Benchmark." +version: 1.0.0 +author: Hermes Agent +license: MIT +platforms: [linux] +metadata: + hermes: + tags: [benchmark, evaluation, model-selection, ollama, extraction] + related_skills: [agent-routing, cognee-brain, save, save-q-memory] +--- + +# Model Capability Benchmark + +Use when the user needs to pick which model to use for a specific capability (memory +extraction, entity/relation extraction, classification, summarization quality, etc.). +The goal is a data-backed model choice, not a vibe check. + +## When to Use + +Load this skill when the user needs to pick which model to use for a specific +capability (memory extraction, entity/relation extraction, classification, +summarization quality, etc.). The goal is a data-backed model choice, not a vibe check. + +Triggers: +- "which model should I use for X" +- "run a test of the models we have" +- "compare models on " +- Selecting a model for a pipeline (memory extraction, Cognee-style work, etc.) + +## Method + +0. **Run the SAME test on every candidate — no variations.** When the user says + "test these models" or "do the same test", send the identical prompt, identical + `temperature`, identical system message to every model. Do NOT add toggles + (thinking on/off, different prompts, extra modes) unless the user explicitly asks + for a comparison of those modes. The user corrected this directly: "WHY DIDN'T you + just do the same test??? DO not turn off thinking. Just DO THE SAME TEST." A + benchmark's value is comparability; a variation you introduce silently breaks it. + +1. **Enumerate the candidate models.** For Ollama cloud models, `ollama list` shows + them; `curl -s http://localhost:11434/api/tags` reveals `remote_model`/`remote_host` + (cloud models have a `remote_host`; local models have a real byte size). Filter to + the requested scope (e.g. "cloud only" = has `remote_host`). For a non-Ollama + endpoint (e.g. a llama.cpp server on another box), hit its OpenAI-compatible + `/v1/chat/completions` directly with `urllib` — same system prompt, same + `temperature: 0`, same test cases. The harness just needs a `chat(messages)` + function; the scoring is identical regardless of backend. + +2. **Write a test-case set.** Each case = input turns + expected extraction + explicit + fail conditions. Cover the hard cases for the capability, not just happy paths. For + memory extraction the canonical hard cases are: identity/stable facts, preference + vs one-off, update/contradiction, relative time, negation, specificity, multi-entity + relation, pronoun resolution (needs prior turn), plan vs completed fact, abstention + (no facts), assistant contamination, quantity/attribute, soft preference + intensity, + two-people-easy-to-merge. + +3. **Build a harness** that sends each case to each model with a fixed system prompt + demanding a clean structured list (JSON array), `temperature=0`, and captures raw + output. Save raw outputs to disk (JSON) — never score in the same pass that runs. + +4. **Score kept / missed / invented** per case, then total. A good extractor is high + recall (kept) with near-zero inventions. For Cognee-style work also reject answers + that aren't clean entity/relation lists. + +5. **Pick the winner** on recall + zero inventions, and report per-case detail for the + interesting failures (not just totals). + +## Pitfalls + +- **Normalize BOTH sides before substring scoring.** Expected facts and model output + must go through the same `re.sub(r'[^a-z0-9 ]', ' ', s.lower())` — otherwise + hyphenated facts ("sci-fi", "15-gauge", "fine-tune", "gpt-oss-120b") are falsely + marked missed. This bit the first scoring pass. +- **Retired cloud models return HTTP 410.** A model in `ollama list` can still be + retired upstream; every call returns `ERROR: ... was retired at ... (status code: 410)`. + Detect this and exclude the model rather than scoring it as zero-kept. +- **Verify relative-time anchors yourself.** "last Tuesday" relative to a reference + date must be computed with `date -d +%A` etc. The user's expected answer may + itself be wrong (e.g. "Aug 19" when Aug 19 is a Wednesday) — compute the correct + date and flag the discrepancy rather than silently scoring against a wrong target. +- **Contamination test needs an assistant-role turn.** To test that the model ignores + assistant-suggested facts, the middle turn must be `role: "assistant"`, not user. +- **Substring scoring can give false credit.** A model that *answers* instead of + *extracting* (e.g. recommends vector DBs) may contain the expected keywords in prose + and score as "kept" when it actually failed the format. Inspect raw output for the + cases that matter before trusting the score. +- **Score from raw output, not from a live re-run.** Models are non-deterministic even + at temperature 0; re-running changes results. Persist raw outputs and score the file. +- **Large cloud models are slow — run sequentially in the background.** A 397b/675b/120b + cloud model can take ~20s per test case, so 14 cases ≈ 5 min per model. A single + foreground run of several models will hit the terminal timeout. Run one model per + background process (or a `for` loop over models in ONE background process), and poll + the error log for `DONE ` markers rather than blocking on `wait`. Background + processes that get killed mid-run leave a partial JSON — check which models actually + completed before scoring. +- **Strip fences/whitespace in the abstention check.** A model that correctly returns + an empty list may wrap it as ```json\n[]\n``` or `[ ]`. The abstention check must + strip ``` fences and whitespace and accept `[]`, `[ ]`, `""`, `null` — otherwise a + correct abstention is falsely scored as a failure. +- **Negation FORBID substrings false-positive.** A FORBID fact like "allergic to + shellfish" will match inside a *correct* negation ("not allergic to shellfish") and + be falsely scored as invented. For negation cases, either check for the negated form + explicitly (e.g. forbid "allergic to shellfish" only when NOT preceded by "not"), or + inspect the raw output manually before trusting an "invented" flag on a negation test. +- **Non-Ollama endpoints need their own auth.** A llama.cpp server (e.g. e1's + qwen38-27b at `http://10.0.0.26:8099/v1`) may require a Bearer key while `/health` + and `/v1/models` stay public — only a real completion proves auth. Reuse the same + harness by swapping the transport; don't assume the `ollama` python client works for it. + +## Support Files + +- `references/memory-extraction-results.md` — 2026-08-26 benchmark of 11 Ollama cloud + models on memory extraction, with per-model findings and the winner. +- `references/recommended-sampling-params.md` — official temperature/top_p guidance + per model (DeepSeek V4 Pro = 1.0/1.0, MiniMax M3 = 1.0/0.95, API use-case table), + plus how temperature is actually set for Hermes custom providers + (`extra_body.temperature`, not a top-level key) and how to research user-experience + threads (HN Algolia API). Load when the user asks about optimal temperature for a model. diff --git a/save/SKILL.md b/save/SKILL.md new file mode 100644 index 0000000..ae8cbb7 --- /dev/null +++ b/save/SKILL.md @@ -0,0 +1,121 @@ +--- +name: save +description: "Use when user types 'save'. Write to Brain (Cognee) and/or Vault (Qdrant ai_vault_kb)." +version: 1.3.0 +author: Hermes Agent +license: MIT +platforms: [linux] +metadata: + hermes: + tags: [memory, brain, vault, cognee, qdrant, save] + related_skills: [cognee-brain, ai-vault-kb] +--- + +# Save — write to Brain and/or Vault + +Triggered when the user types "save". Route the current session's content to the +right store and write it. + +## Routing + +- **Brain** (Cognee) = durable facts, decisions, preferences, relationships, status changes, corrections. Short atomic statements with time context. +- **Vault** (Qdrant `ai_vault_kb`) = longer context, notes, research, summaries, excerpts — for semantic "find similar" recall. +- **Both** = when something is a clean fact AND rich context: clean version to Brain, fuller version to Vault. +- Be conservative. Only store what's worth remembering. Don't write every message. + +--- + +## BRAIN — Cognee (Kuzu + LanceDB on brain 10.0.0.23) + +The brain is Cognee, reachable via the auto-discovered MCP tools `mcp__cognee__*` +(no CLI needed). Endpoints: API `http://10.0.0.23:8080`, MCP `http://10.0.0.23:8001/mcp`. + +### Write (permanent memory) + +Use the `mcp__cognee__remember` tool. ALWAYS pass `dataset_name="homelab-stack"`. + +- `data` = the text to store (atomic facts, one per statement where possible). +- Omit `session_id` — that makes it permanent memory (add + cognify, builds the graph). +- `remember` returns `status: completed` synchronously — the graph is built, no polling. + +### Read + +Use the `mcp__cognee__recall` tool. `query` (required), `datasets="homelab-stack"`, +optional `search_type` (HYBRID_COMPLETION default; CHUNKS for LLM-free retrieval). + +### Write rules + +- **One dataset:** `homelab-stack`. Never create a second dataset. +- **No group_id, no triplet, no temporal supersession.** Cognee uses datasets. To correct a fact, `remember` the corrected statement; Cognee + merges entities by name. +- **Don't re-ingest the same content twice** — `remember` is not idempotent. +- **Embed dim is 1024** (qwen3-embedding:0.6b on mini) — never let it default to 3072. + +### Verify the write + +- `recall` a distinctive phrase from the content; a correct answer proves the graph has it. +- `docker logs cognee-backend` should show zero `api.openai.com` / `ProviderConfigMismatch` hits. + +--- + +## VAULT — Qdrant `ai_vault_kb` + +CLI: `python3 /home/n8n/bin/ai_vault_kb.py` (zero deps, urllib only). Qdrant `http://10.0.0.22:6333`, collection `ai_vault_kb`. Embeddings: `snowflake-arctic-embed2` on `10.0.0.30:11434`. + +### Write (the ONLY sanctioned path) + +```bash +python3 /home/n8n/bin/ai_vault_kb.py add --type --title "..." --content "..." [flags] +``` + +Long documents: `--file /abs/path/report.md` instead of `--content` (auto-chunked, one shared `doc_id`). `--json` prints `{"doc_id":…, "chunks":N}`. + +| Flag | Meaning | +|---|---| +| `--type` **(required)** | `tool` `setting` `workflow` `host` `model` `technique` `issue` `decision` `research` `asset` `prompt` `finding` | +| `--title` **(required)** | headline a future search reads | +| `--content` / `--file` | body text, or a file to chunk | +| `--stage` | `story` `script` `character` `keyframe` `t2v` `i2v` `upscale` `interpolate` `tts` `lipsync` `music` `assembly` `publish` `infra` | +| `--tool` `--host` `--path` `--url` `--version` | provenance; `--host` is the box the fact is about | +| `--status` | `active` `candidate` `deprecated` `broken` `planned` (default `active`) | +| `--trust` | `official` `github` `community` `social` (default `official`) | +| `--tags` | comma-separated; exact-match keyword index — put slug, filename, error code here | +| `--importance` | 0.0–1.0 | +| `--doc-id` | append more chunks to an existing document | + +Unknown vocabulary values warn but are accepted — the schema is faceted, not strict. + +### Dedup-first (mandatory before every write) + +```bash +python3 /home/n8n/bin/ai_vault_kb.py search --query "" +``` + +- score **≥ 0.85** — already recorded, skip +- **0.70–0.84** — add only if meaningfully new +- **< 0.70** — always add + +### Host records + +`--type host`, one stable `--doc-id` per box. Re-add with the same `--doc-id` to update/append a dated chunk. + +### Verify the write landed (both legs) + +```bash +D= +python3 /home/n8n/bin/ai_vault_kb.py search --query "" --mode bm25 --doc-id $D +python3 /home/n8n/bin/ai_vault_kb.py list --type --doc-id $D +``` + +Zero hits on the BM25 leg means something other than `ai_vault_kb.py` wrote it. + +--- + +## Pitfalls + +- **Brain writes are not idempotent** — don't re-ingest the same content twice. +- **Vault writes MUST go through `ai_vault_kb.py`** — never a bare Qdrant upsert or `mcp__better_qdrant__add_documents` (missing bm25/doc_type makes the point unfindable). Never hand-roll raw Qdrant HTTP for a write. +- **Collection name is exact** — `ai_vault_kb`, not `ai-vault-kb`. Don't create topic-specific collections. +- **On correction:** update Brain (remember the corrected fact) and store the correction. +- **`fact_store` and the `memories` collection are not the vault** — research findings, model configs, prompt guides, infra facts go here. +- **A search that returns nothing is a real answer** — say "not in the vault" and go research it. diff --git a/youtube-knowledge-ingestion/SKILL.md b/youtube-knowledge-ingestion/SKILL.md index b46a9a9..0e4ef89 100644 --- a/youtube-knowledge-ingestion/SKILL.md +++ b/youtube-knowledge-ingestion/SKILL.md @@ -1,19 +1,44 @@ --- name: youtube-knowledge-ingestion -description: "Use when user drops a YouTube link. Transcript→brain→NAS." -version: 1.0.0 +description: "AUTO-TRIGGER: If the operator's message consists solely of a YouTube URL (youtube.com/watch, youtu.be, youtube.com/shorts — no other words), ALWAYS run the full ingestion flow immediately, without asking any clarifying questions: 1. Verbatim transcript → ai_vault_kb (the vault) per the \"Transcript Ingestion (verbatim)\" section (dedup-first, separate doc if a recipe/summary doc for the video already exists). 2. Distilled summary → Cognee brain (the brain) per the \"Brain Injection (Cognee)\" section. 3. If the video's description or pinned comment links a workflow or downloadable assets, download them to the NAS stock library per the existing procedure. 4. Reply with a minimal 4-line completion status (Brain ingest / Vault ingest / Workflow dl / Workflow(s)); write the full proof report (doc_id, chunk count, excerpt, BM25 outputs, file paths + sizes) to ~/workspace/general/logs/yt_ingestion_proofs.log instead of sending it to the operator. Use when user drops a YouTube link. Transcript→vault+brain→NAS." +version: 1.1.0 platforms: [linux] --- # YouTube Knowledge Ingestion Pipeline +## AUTO-TRIGGER (read first — highest priority) + +AUTO-TRIGGER: If the operator's message consists solely of a YouTube URL +(youtube.com/watch, youtu.be, youtube.com/shorts — no other words), ALWAYS run the full +ingestion flow immediately, without asking any clarifying questions: +1. Verbatim transcript → ai_vault_kb (the vault) per the "Transcript Ingestion (verbatim)" +section (dedup-first, separate doc if a recipe/summary doc for the video already exists). +2. Distilled summary → Cognee brain (the brain) per the "Brain Injection (Cognee)" +section. +3. If the video's description or pinned comment links a workflow or downloadable assets, +download them to the NAS stock library per the existing procedure. +4. Reply with a minimal 4-line completion status (see "Completion output" below); write +the full proof report to ~/workspace/general/logs/yt_ingestion_proofs.log instead of +sending it to the operator. + +**The failure mode this trigger exists to prevent (recurring user correction):** +loading the `youtube-content` skill and producing a chat summary. A bare URL is NOT a +request for a summary — it is a request to run THIS pipeline. Do NOT load +`youtube-content` for a bare URL; load THIS skill (`youtube-knowledge-ingestion`). +Do NOT summarize the video in chat under any circumstances. The user has corrected +this multiple times ("WHY DO YOU KEEP DOING THIS — YOU HAVE A YT INGEST SKILL"). +The two skills are easy to confuse: `youtube-content` = fetch transcript + format +(summary/thread/blog); `youtube-knowledge-ingestion` = the full transcript→vault + +summary→brain + workflow→NAS pipeline. A bare URL always means the latter. + ## When to use User drops a YouTube link for AI/ML video content (ComfyUI workflows, LTX, MiniMax, -Krea, model tutorials, prompting guides). Run the full three-step pipeline — never skip +Krea, model tutorials, prompting guides). Run the full four-step pipeline — never skip any step. -## Pipeline (always all three steps) +## Pipeline (always all four steps) ### 1. Transcript @@ -25,16 +50,16 @@ uv run python3 /scripts/fetch_transcript.py "URL" --text-only --times If `youtube-transcript-api` is missing, install with `pip3 install --user youtube-transcript-api`. -### 2. Brain Injection (MANDATORY) +### 2. Vault Injection (ai_vault_kb) (MANDATORY) -Load the `ai-brain-kb` skill. Always dedup-first, then ingest: +Load the `ai-vault-kb` skill. Always dedup-first, then ingest: ```bash # Dedup check -python3 /home/n8n/bin/ai_brain_kb.py search --query "" --limit 5 +python3 /home/n8n/bin/ai_vault_kb.py search --query "" --limit 5 # Ingest — use --type workflow for tutorials -python3 /home/n8n/bin/ai_brain_kb.py add \ +python3 /home/n8n/bin/ai_vault_kb.py add \ --type workflow \ --title "Descriptive Title — Key Topics" \ --stage \ @@ -48,7 +73,7 @@ python3 /home/n8n/bin/ai_brain_kb.py add \ --json # Verify BM25 leg -python3 /home/n8n/bin/ai_brain_kb.py search --query "" \ +python3 /home/n8n/bin/ai_vault_kb.py search --query "" \ --mode bm25 --doc-id ``` @@ -56,7 +81,7 @@ python3 /home/n8n/bin/ai_brain_kb.py search --query "" \ Include specific settings, model names, thresholds, commands, and failure modes. This is a technical reference, not a blog post. -**MANDATORY: workflow links in the brain content.** Every brain entry must include a +**MANDATORY: workflow links in the vault content.** Every vault entry must include a `## WORKFLOW LINKS` section listing the DOWNLOADED workflow files on NAS (TrueNAS 10.0.0.117, proxmoxBackup/ai_vid_stock_material/workflows/, exact filenames + the smbclient get command), the source repo URL, and the video URL. The NAS copies are @@ -68,7 +93,54 @@ already ingested. **Tag strategy**: model name, tool name, creator name, key techniques. Tags are exact-match keyword indexes. -### 3. NAS Workflow Download +### 3. Brain Injection (Cognee) (MANDATORY) + +Load the `cognee-brain` skill. Write the distilled summary to the shared Cognee +brain (10.0.0.23) as a narrative finding — LLM extraction pulls out the entities +(models, tools, creators) and facts (claims, settings, comparisons) automatically: + +Call the Cognee MCP tool `mcp__cognee__remember` with: +- `data` = the distilled summary (2-4 sentences) +- `dataset_name` = `homelab-stack` +- omit `session_id` (permanent memory — runs add + cognify, builds the graph) + +- `remember` is synchronous (`status: completed` means the graph is built). No + polling needed; verify later with `recall` if needed. +- Always use dataset `homelab-stack` (the single shared brain dataset). Never + create a second dataset. +- The brain holds the distilled facts; the vault (ai_vault_kb) holds the verbatim + transcript. Both are written for every video — never skip either. + +**MCP timeout + REST fallback (learned 2026-08-29).** The MCP `remember` call can +fail with `TimeoutError: MCP call timed out after 120.0s` because cognify is +variable — the REST path took 77s for a 6-item ingest, while MCP full-size payloads +ran 9.8–12.2s. The MCP server itself is healthy; it is the client-side 120s +per-tool-call timeout that aborts slow cognify runs. Two-part fix: + +1. **Raise the timeout** in `~/.hermes/profiles/general/config.yaml` (cognee MCP + block): `timeout: 120` → `timeout: 300`. Takes effect on next Hermes restart + (MCP connections are read once at startup). Note: the `patch` tool refuses to + edit Hermes config files — use terminal Python for an exact string replace, then + `python3 -c "import yaml; yaml.safe_load(open('config.yaml'))"` to validate. +2. **REST fallback** when MCP times out (documented in the `cognee-brain` skill): + +```bash +# Write (synchronous; returns status:completed + items_processed) +curl -s -m 300 -X POST "http://10.0.0.23:8080/api/v1/remember" \ + -F "data=@/tmp/brain_summary.txt" \ + -F "datasetName=homelab-stack" + +# Verify (field names are query + searchType, NOT query_text/query_type) +curl -s -m 60 -X POST "http://10.0.0.23:8080/api/v1/search" \ + -H "Content-Type: application/json" \ + -d '{"query":"","datasets":["homelab-stack"],"searchType":"HYBRID_COMPLETION"}' +``` + +A `status: completed` from the REST write is proof the graph is built — no separate +cognify step. If the MCP call times out, do NOT retry it blindly; use the REST path +and verify with the search call above. + +### 4. NAS Workflow Download If the video description contains workflow links (GitHub repos, direct JSON files), extract the description with `yt-dlp --print description "URL"`, clone the repos, @@ -92,15 +164,171 @@ Examples: `amao2001-ltx2.5-video_ltx2_5_t2v1.json`, `vionex-krea2-film-studio-v0 **Target**: `proxmoxBackup/ai_vid_stock_material/workflows/` on TrueNAS (10.0.0.117). +**ComfyUI custom-node repos (no workflow JSONs) → `scripts/`, not `workflows/`.** +When the description links a ComfyUI custom-node pack (e.g. PlagueKind's +`ComfyUI-PlagueKind-Nodes` — the SLA attention node), the repo is Python source with +no `example_workflows/*.json` to copy. Archive it as a tarball under +`ai_vid_stock_material/scripts/` (same pattern as full apps — see +`references/fetch-path-and-walled-links.md`): + +```bash +cd /tmp && rm -rf && git clone --depth 1 +COMMIT=$(cd && git log -1 --format=%h) +tar czf --.tar.gz +smbclient -N //10.0.0.117/proxmoxBackup \ + -c 'cd ai_vid_stock_material/scripts; put /tmp/ ' +``` + +`workflows/` stays reserved for ComfyUI JSONs; `scripts/` is the home for node packs +and tools. Record the commit hash in the WORKFLOW LINKS section. + +## Transcript Ingestion (verbatim) — when the task says "transcript" + +When the task asks for the TRANSCRIPT (not a summary/recipe), the vault doc must contain +the verbatim spoken text. A distilled recipe summary is NOT a transcript. + +**Omit useless segments.** "Verbatim" means the informative spoken content word-for-word — +not the filler around it. Cut entirely: sponsor reads / ad segments, song lyrics and +music-only passages, giveaway/merch/Patreon plugs, like-and-subscribe boilerplate, and +unrelated channel promo. Replace each cut with a one-line marker at that spot — [sponsor +segment omitted], [music omitted], [channel promo omitted] — so the cut is visible and +auditable. When in doubt, keep it: anything touching the technical content (settings, +models, node names, reasoning, results) is never filler, even if it sounds chatty. The +word count in the summary header notes omissions, e.g. "2,140 words (3 segments omitted: 2 +sponsor, 1 music)." + +1. **Fetch the caption track**: `yt-dlp --skip-download --write-auto-subs --write-subs + --sub-langs "en.*" ` (fall back to `--sub-langs en` if needed). Clean the VTT/SRT + to plain text: strip WEBVTT headers, cue timestamps, and inline ``/timestamp tags; + dedupe rolling-caption repeated lines. Result must read as continuous spoken sentences. +2. **Body layout**: short distilled summary header (10–15 lines max) at top, then the FULL + verbatim transcript. Title pattern: `YT: