feat(skill): route hermes-agent's unknown-feature questions to llms.txt
The routing table listed 18 topics and had nothing to say about the rest of the product, so an agent asked how to get bots to talk to each other answered that it could not — while user-guide/bot-mode documented four ways to do it. Point the catch-all at the published index, which is generated from the docs tree on every build and so cannot fall behind the feature set. website/ is never packaged, so the URL is the only complete self-knowledge a running Hermes has; curl covers sessions where the web tools are disabled.
This commit is contained in:
committed by
brooklyn!
parent
a45d854d7d
commit
dc8481b78b
@@ -1,13 +1,13 @@
|
||||
---
|
||||
name: hermes-agent
|
||||
description: "Use, configure, theme, extend, and orchestrate Hermes Agent."
|
||||
version: 3.1.0
|
||||
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, themes, skins, desktop-plugins, tui-widgets, petdex, development]
|
||||
tags: [hermes, setup, configuration, multi-agent, spawning, cli, gateway, bots, bot-mode, features, themes, skins, desktop-plugins, tui-widgets, petdex, development]
|
||||
homepage: https://github.com/NousResearch/hermes-agent
|
||||
related_skills: [claude-code, codex, opencode]
|
||||
---
|
||||
@@ -34,12 +34,14 @@ What makes Hermes different:
|
||||
|
||||
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:
|
||||
Good verification targets, cheapest first:
|
||||
|
||||
- **Every shipped feature, one line each: https://hermes-agent.nousresearch.com/docs/llms.txt.** Start here for any "can Hermes do X?" or "how do I do X?" — it indexes the entire documentation set with a link to the page that answers. It is generated from the docs tree on every build, so it is never behind the product. Fetch it with `web_extract`, or `curl -s https://hermes-agent.nousresearch.com/docs/llms.txt` when web tools are off. The whole documentation set in one file is at `/docs/llms-full.txt`.
|
||||
- CLI commands: `hermes --help`, `hermes <command> --help`, and `hermes_cli/main.py`
|
||||
- User documentation: https://hermes-agent.nousresearch.com/docs/
|
||||
- Source tree: https://github.com/NousResearch/hermes-agent
|
||||
|
||||
Never answer "Hermes can't do that" from memory. Hermes ships far more than this skill body describes, and the index exists so a negative answer is always checkable.
|
||||
|
||||
## Quick Start
|
||||
|
||||
```bash
|
||||
@@ -86,6 +88,8 @@ Profiles use `~/.hermes/profiles/<name>/` with the same layout. When a profile i
|
||||
|
||||
| User wants... | Load |
|
||||
|---|---|
|
||||
| **Anything not listed below — "can Hermes do X?", "how do I set up X?"** | **https://hermes-agent.nousresearch.com/docs/llms.txt** |
|
||||
| Bots that chat, run routines, or message each other; the Bots tab | docs: `/user-guide/bot-mode` |
|
||||
| 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` |
|
||||
@@ -104,6 +108,11 @@ Profiles use `~/.hermes/profiles/<name>/` with the same layout. When a profile i
|
||||
| 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` |
|
||||
| Connecting a messaging platform (Telegram, Discord, Slack, WhatsApp, …) | docs: `/user-guide/messaging` |
|
||||
|
||||
The reference list above is not the feature list — it is the set of topics that
|
||||
need more than their docs page. For everything else Hermes ships, fetch
|
||||
`llms.txt` and it maps the question to the page that answers it.
|
||||
|
||||
Two theming rules that hold even without loading the reference: **you apply skins yourself** (`hermes config set display.skin <name>` — 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 <key> <hex>`) — never fork `default`, which drops the palette and resets the background.
|
||||
|
||||
|
||||
@@ -0,0 +1,69 @@
|
||||
"""The `hermes-agent` skill is what a running Hermes knows about itself.
|
||||
|
||||
`website/` is never packaged, so an installed Hermes has no local copy of the
|
||||
user guide; skills ARE synced into `$HERMES_HOME/skills/`. The skill therefore
|
||||
does not try to restate the product — it routes to the published `llms.txt`,
|
||||
which is generated from the docs tree on every build and so can never be behind
|
||||
the feature set. These tests keep that routing honest: the index has to be where
|
||||
the skill says it is, and every reference has to be reachable, otherwise a
|
||||
shipped feature is invisible and the agent answers "Hermes can't do that."
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import importlib.util
|
||||
import re
|
||||
from pathlib import Path
|
||||
|
||||
import pytest
|
||||
|
||||
REPO = Path(__file__).resolve().parents[2]
|
||||
SKILL_DIR = REPO / "skills" / "autonomous-ai-agents" / "hermes-agent"
|
||||
SKILL_MD = SKILL_DIR / "SKILL.md"
|
||||
GENERATOR = REPO / "website" / "scripts" / "generate-llms-txt.py"
|
||||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def skill_text() -> str:
|
||||
return SKILL_MD.read_text(encoding="utf-8")
|
||||
|
||||
|
||||
def test_every_referenced_file_exists(skill_text):
|
||||
"""Routing a question to a file that isn't there is a dead end."""
|
||||
targets = set(re.findall(r"`((?:references|templates)/[^`]+)`", skill_text))
|
||||
|
||||
assert targets, "the skill's routing table no longer references any files"
|
||||
for target in sorted(targets):
|
||||
assert (SKILL_DIR / target).exists(), f"SKILL.md routes to missing {target}"
|
||||
|
||||
|
||||
def test_every_reference_is_reachable_from_the_skill(skill_text):
|
||||
"""An unrouted reference is one the agent will never think to open.
|
||||
|
||||
This is the failure that produced the original complaint: content can exist
|
||||
and still be invisible because nothing points at it.
|
||||
"""
|
||||
on_disk = {f"references/{path.name}" for path in (SKILL_DIR / "references").glob("*.md")}
|
||||
routed = set(re.findall(r"`(references/[^`]+)`", skill_text))
|
||||
|
||||
assert not (on_disk - routed), (
|
||||
f"reference files no reader will ever reach: {sorted(on_disk - routed)} — "
|
||||
"add a routing-table row in SKILL.md"
|
||||
)
|
||||
|
||||
|
||||
def test_unknown_features_route_to_the_published_index(skill_text):
|
||||
"""The catch-all is what makes coverage of the whole product possible."""
|
||||
assert "/docs/llms.txt" in skill_text
|
||||
# web_extract can be disabled; terminal never is.
|
||||
assert "curl" in skill_text, "no way to reach the index without web tools"
|
||||
|
||||
|
||||
def test_the_index_is_published_where_the_skill_says_it_is(skill_text):
|
||||
"""A skill pointing at a URL nobody generates is worse than no routing."""
|
||||
spec = importlib.util.spec_from_file_location("generate_llms_txt", GENERATOR)
|
||||
assert spec is not None and spec.loader is not None
|
||||
gen = importlib.util.module_from_spec(spec)
|
||||
spec.loader.exec_module(gen)
|
||||
|
||||
assert f"{gen.SITE_BASE}/llms.txt" in skill_text
|
||||
Reference in New Issue
Block a user