Skip to content

Skill System — Skills

源码版本v2026.7.20

Responsibility

A Skill is a higher-order capability unit than a Tool: a reusable, frontmatter-annotated flow (similar to the agentskills.io spec), categorized by domain under skills/<category>/. Unlike tools' "static functions", skills can be created, rewritten, and refined by the learning loop — how the agent "gets smarter the more you use it". Skills are exposed to the main loop via skills_tool.

Design Motivation

Why organize skills by category directory instead of a flat layout? The skill count grows with usage (user-added, hub-synced, learning-loop-generated all land in ~/.hermes/skills/), and a flat list returned by skills_list quickly becomes noise. Categories let progressive disclosure's first layer expose "here is a group of research skills" rather than 50 concrete skill names. Each SKILL.md is a single self-contained definition (with frontmatter), paired with files under skills/<category>/<skill>/references/ for on-demand loading, so tokens do not blow up at once.

Bundles are another layer of packaging: they load multiple skills with one slash command, because a scenario like "backend development" needs code review, TDD, and PR skills all attached at once — /skill one by one is too fragmented.

Key Files

  • skills/ directory — grouped by domain (apple, computer-use, research, software-development, yuanbao...). Each skill looks like this:
skills/
├── my-skill/
│   ├── SKILL.md           # main instructions (required)
│   ├── references/        # supporting docs
│   │   ├── api.md
│   │   └── examples.md
│   ├── templates/         # output templates
│   └── assets/            # attachments (agentskills.io standard)
└── category/
    └── another-skill/
        └── SKILL.md

The top of SKILL.md is YAML frontmatter (name/description/version/platforms/prerequisites...), followed by the body instructions. name is capped at 64 chars, description at 1024; these two fields are the only thing the first progressive-disclosure layer of skills_list returns, to save tokens.

  • skills_tool — exposes skills as a tool to the main loop. It registers two tools:
python
registry.register(
    name="skills_list",
    toolset="skills",
    schema=SKILLS_LIST_SCHEMA,
    handler=lambda args, **kw: skills_list(
        category=args.get("category"), task_id=kw.get("task_id")
    ),
    check_fn=check_skills_requirements,
    emoji="📚",
)

registry.register(
    name="skill_view",
    toolset="skills",
    schema=SKILL_VIEW_SCHEMA,
    handler=_skill_view_with_bump,
    check_fn=check_skills_requirements,
    emoji="📚",
)

skills_list returns only name + description + category (first progressive-disclosure layer); skill_view loads the full SKILL.md (second layer); reference/template files are pulled on demand via skill_view(name, file_path="references/api.md") (third layer). _skill_view_with_bump calls bump_view / bump_use on success to update usage counters, which the curator's stale timer uses to clean up unused skills.

  • skill_manager_tool — skill management (list/view/enable)
  • skills_hub — skill-hub sync (agentskills.io compatible)
  • skills_sync — local ↔ remote skill sync
  • skill_bundles — skill bundle packaging, injected into the prompt. A bundle is a small file under ~/.hermes/skill-bundles/*.yaml:
yaml
name: backend-dev
description: Backend feature work — code review, testing, PR workflow.
skills:
  - github-code-review
  - test-driven-development
  - github-pr-workflow
instruction: |
  Optional extra guidance to inject above the skill bodies.

/<bundle-name> calls build_bundle_invocation_message to splice every member skill's SKILL.md into a single user message. When a bundle and a skill share a name, the bundle wins — if the user named them the same, they want to override the colliding skill. Missing member skills do not raise; the result just notes which ones were skipped.

  • skill_preprocessing — skill content preprocessing. Replaces ${HERMES_SKILL_DIR} / ${HERMES_SESSION_ID} template variables, and runs inline shell snippets like !date +%Y-%m-%d``. A failed inline shell returns an [inline-shell error: ...] marker instead of raising, so one bad snippet does not tank the whole skill message.
  • skill nodes & edges:125-193build_skill_nodes / build_edges, organizing skills into a learning graph

Data Flow

  1. At startup, skill_preprocessing (agent/skill_preprocessing.py) scans skills/<category>/ and reads frontmatter.
  2. skill_bundles (agent/skill_bundles.py) packages relevant skills and injects them into this turn's prompt via build_turn_context:268.
  3. The provider decides to invoke a skill → tool_call skillstools/skills_tool.py loads and executes that skill's flow.
  4. The execution result is backfilled to the main loop.
  5. The learning loop reviews this turn in the background and may:

Boundaries and Failure

  • Path traversal: a skill name is concatenated onto ~/.hermes/skills/ to locate files, so _skill_lookup_path_error rejects .. segments, absolute paths, and Windows drive letters. Otherwise name="../outside" could read files outside the skills directory.
  • Prompt injection: SKILL.md content containing patterns like "ignore previous instructions", "system prompt:", or "]]>" is flagged by _INJECTION_PATTERNS. Third-party skills (synced from the hub) are untrusted content; the main loop must sanitize them on load.
  • Bundle missing members: build_bundle_invocation_message only records missing/disabled member skills into missing / disabled lists and does not raise — bundles load leniently, and a few missing members do not affect the rest.
  • Cache staleness: scanning skills/ is O(#dirs) stat, with a signature that includes directory mtime + the disabled set + platform. But in-place edits to a single SKILL.md only bump its own mtime, which the directory signature cannot see, so an additional 30s TTL acts as a fallback.

Summary

Skill = an evolvable higher-order flow, described by frontmatter, defined by a file, rewritable by the learning loop. Its relation to tools: tools are the atoms called within a skill flow; skills are knowledge about "how to combine tools to accomplish a class of tasks". See the learning loop for how skills evolve.

Unofficial community learning site. Content based on the MIT-licensed NousResearch/hermes-agent source.