hermes - 💡(How to fix) Fix Plugin skills: opt-in <available_skills> awareness-band listing for register_skill() [1 participants]

Official PRs (…)
ON THIS PAGE

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…
GitHub stats
NousResearch/hermes-agent#25052Fetched 2026-05-14 03:49:29
View on GitHub
Comments
0
Participants
1
Timeline
5
Reactions
0
Participants
Timeline (top)
labeled ×4cross-referenced ×1

Code Example

provides_tools:
  - ...
provides_hooks:
  - ...
provides_skills:
  list_in_awareness: true   # default: false (preserves current behavior)

---

ctx.register_skill(
    name="my-workflow",
    path=skill_md_path,
    description="...",
    list_in_awareness=True,  # default: False
)
RAW_BUFFERClick to expand / collapse

Problem

ctx.register_skill() (introduced in the build-a-plugin guide as the recommended path for bundling skills) namespaces plugin skills as <plugin>:<skill> and explicitly excludes them from the system prompt's <available_skills> index. Per hermes_cli/plugins.py L632–634:

The skill becomes resolvable as '<plugin_name>:<name>' via skill_view(). It does not enter the flat ~/.hermes/skills/ tree and is not listed in the system prompt's <available_skills> index — plugin skills are opt-in explicit loads only.

This is correct for collision-safety — namespacing prevents plugin skills from shadowing built-in or user-authored skills. But it creates a discovery cliff: plugin skills are invisible to the agent's awareness band until the agent already knows they exist.

The legacy shutil.copytree pattern (still documented in the same guide as "legacy") sidesteps this by copying skills into ~/.hermes/skills/<plugin-name>/, where they surface ambient in the system prompt like any other user skill — at the cost of collision risk and the substrate-mutation side-effect at every register() call.

So plugin authors today face a forced tradeoff:

PatternCollision-safe?Surfaces in awareness band?Side-effect-free?
shutil.copytree (legacy)
ctx.register_skill() (recommended)

Both columns aren't simultaneously satisfiable. The guide nudges authors toward the recommended path, but the column where it loses (discovery) is load-bearing for any plugin suite where the skills are meant to fire opportunistically as the agent works — not just be loaded by name when the operator knows to call for them.

Concrete cases

Mirror issue: witt3rd/oh-my-hermes#19 — OMH wants to retire its legacy _install_skills() copytree but the discovery loss makes the migration cost too high for a production-shipped suite. OMH skills (omh-ralplan, omh-ralph, omh-deep-interview, omh-autopilot, omh-triage, etc.) are designed to surface in the awareness band so the agent reaches for the right one when the work calls for it. Forcing operators to know omh:ralplan exists before they can use it inverts the intent.

The same shape applies to any plugin shipping a coherent skill suite (gardening, debugging, workflow, etc.) where the value is in the awareness band recognizing the right tool for the moment, not in the operator memorizing a namespace.

Proposed solution

Opt-in <available_skills> listing for plugin-registered skills. Manifest field on plugin.yaml:

provides_tools:
  - ...
provides_hooks:
  - ...
provides_skills:
  list_in_awareness: true   # default: false (preserves current behavior)

Or per-skill at registration time:

ctx.register_skill(
    name="my-workflow",
    path=skill_md_path,
    description="...",
    list_in_awareness=True,  # default: False
)

When True, the plugin's skills surface in the <available_skills> index alongside user skills, namespaced as <plugin>:<skill> so collisions are still prevented at the resolution layer. Operators (or plugin authors) make the explicit choice that this suite is meant to fire opportunistically rather than being loaded by-name.

Why opt-in (not default-on)

  • Most plugins ship 1–2 skills; ambient listing is unnecessary noise.
  • Plugins that ship many skills (10+) and intend them as a coherent suite benefit from awareness-band surfacing.
  • Opt-in preserves the current safety property (no plugin can flood the system prompt without operator/author consent).

Why this matters now

The legacy shutil.copytree pattern is structurally bad (collision risk, substrate-mutation side-effects, no read-only enforcement). The recommended ctx.register_skill() path is structurally correct except for discovery. Closing this gap unblocks plugin authors from migrating off the legacy pattern without paying ergonomic cost.

Without this, suites like OMH have to choose between:

  • Keeping legacy copytree (suboptimal but functional).
  • Migrating to register_skill and losing discovery (better hygiene, worse UX).
  • Building hybrid double-bookkeeping (both surfaces work, drift risk).

None of those serve users well. Opt-in awareness-band listing makes the migration cost-free for plugins that want it.

Related

  • Build-a-plugin guide §"Bundle skills" and the :::tip Legacy pattern callout.
  • hermes_cli/plugins.py::PluginContext.register_skill() L622–665.
  • agent/skill_utils.py::_NAMESPACE_RE and resolution logic.

⚒️ Forge

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING