hermes - ✅(Solved) Fix [Bug]: skill_view/skills_list name mismatch breaks agent tool-calling loop — model can't load skills it discovers [2 pull requests, 1 comments, 2 participants]

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

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#18872Fetched 2026-05-03 04:53:49
View on GitHub
Comments
1
Participants
2
Timeline
8
Reactions
0
Timeline (top)
labeled ×5cross-referenced ×2commented ×1

Error Message

JSON error, and the model either gives up on the skill or hallucinates its contents. {"success": false, "error": "Skill 'bar' not found."} through the tool-calling loop. The model sees a valid error response from warn or skip mismatched skills. Prevents the problem at install time but requires

Root Cause

The root cause is a dual-namespace architecture where discovery and resolution use different identifiers:

Fix Action

Fixed

PR fix notes

PR #18879: fix(skills): skill_view fallback to frontmatter name lookup (fixes #18872)

Description (problem / solution / changelog)

Fix: skill_view/skills_list name mismatch breaks agent tool-calling loop

Fixes #18872

Problem

When a skill's directory name differs from its frontmatter name: field (e.g., directory foo/ with name: bar in SKILL.md), skills_list() returns the frontmatter name ("bar") but skill_view() only looks up by directory name ("foo"). This causes skill_view("bar")"Skill 'bar' not found", breaking the agent's tool-calling loop when it tries to load a discovered skill.

Root Cause

_find_all_skills() (line 588) uses frontmatter.get("name", skill_dir.name) — frontmatter name takes priority. But skill_view() searches by directory name via found_skill_md.parent.name == name and direct path matching, with no frontmatter name fallback.

Fix

Add a fallback search in skill_view() that scans all skill SKILL.md files and matches by frontmatter name: field when directory-name lookup fails. This makes skill_view() accept both directory names and frontmatter names, ensuring consistent resolution regardless of which name skills_list() returns.

Testing

  • skills_list() → returns frontmatter name ✓ (unchanged)
  • skill_view("directory_name") → works ✓ (existing path)
  • skill_view("frontmatter_name") → works ✓ (new fallback)
  • Slash commands: /frontmatter_name still works via command map ✓ (unchanged)

Changed files

  • tools/skills_tool.py (modified, +19/-0)

PR #18901: fix(skills): add frontmatter-name fallback in skill_view to resolve name mismatch

Description (problem / solution / changelog)

Summary

Fixes the skill discovery→loading loop where skills_list reports a frontmatter name but skill_view can only resolve by directory name, making mismatched skills silently undiscoverable by the agent.

Problem

When a skill's frontmatter name differs from its directory name (e.g., directory foo but frontmatter name: bar):

  1. skills_list → returns "bar" (from frontmatter)
  2. Agent calls skill_view("bar")"Skill 'bar' not found." (resolves by directory name)
  3. Skill is unusable — no crash, no warning, just a dead entry

The agent's tool chain contradicts itself silently. The model can't self-correct because it has no way to know skill_view needs a different identifier than what skills_list reported.

Fix

Added a frontmatter-name fallback in skill_view(): when directory-name lookup fails (steps 1-3), the function now iterates all SKILL.md files and checks if the frontmatter name field matches. If found, uses that skill's directory path.

This is backwards-compatible:

  • skill_view("foo") still works (directory name lookup, existing behavior)
  • skill_view("bar") now works (frontmatter name fallback, new behavior)
  • No API changes to skills_list output

Verification

mkdir -p ~/.hermes/skills/foo
cat > ~/.hermes/skills/foo/SKILL.md << 'EOF'
---
name: bar
description: Test skill with mismatched name
---
# Bar
Content here.
EOF
  • skills_list → shows bar
  • skill_view("bar") → loads the skill (was: "not found")
  • skill_view("foo") → still loads the skill (unchanged)

Fixes #18872

Changed files

  • tools/skills_tool.py (modified, +19/-0)

Code Example

# 1. Create a skill with diverging names
mkdir -p ~/.hermes/skills/foo
cat > ~/.hermes/skills/foo/SKILL.md << 'EOF'
---
name: bar
description: An agent-facing skill with mismatched identifiers
version: 1.0.0
---
# Bar
This skill is in directory `foo` but declares `name: bar`.
EOF

---

bar — An agent-facing skill with mismatched identifiers   (category: null)

---

{"success": false, "error": "Skill 'bar' not found."}
RAW_BUFFERClick to expand / collapse

Bug Description

The agent's tool-calling pipeline has a self-inconsistency that makes skills undiscoverable via the primary code path:

  1. Model calls skills_list → sees skill name "bar" (from frontmatter name)
  2. Model calls skill_view("bar")"Skill 'bar' not found." (resolves by directory name)
  3. Skill is unusable — the agent's own tool chain contradicts itself

This is not just a UX papercut for human users — it's a functional break in the model's skill discovery→loading loop. The bug is silent (no crash, no stack trace), which makes it hard to diagnose: skills_list succeeds, skill_view returns a valid JSON error, and the model either gives up on the skill or hallucinates its contents.

The root cause is a dual-namespace architecture where discovery and resolution use different identifiers:

OperationIdentifier sourceCode
skills_list / _find_all_skillsfrontmatter nametools/skills_tool.py:588
skill_viewdirectory nametools/skills_tool.py:958,973
scan_skill_commands (slash)frontmatter nameagent/skill_commands.py:245

Slash commands happen to work because scan_skill_commands stores the absolute directory path alongside the frontmatter name, and build_skill_invocation_message resolves via that path — but the opposite direction fails: skill_view called by the directory name works, while skill_view called by the frontmatter name (which is what skills_list reports) does not.

Steps to Reproduce

# 1. Create a skill with diverging names
mkdir -p ~/.hermes/skills/foo
cat > ~/.hermes/skills/foo/SKILL.md << 'EOF'
---
name: bar
description: An agent-facing skill with mismatched identifiers
version: 1.0.0
---
# Bar
This skill is in directory `foo` but declares `name: bar`.
EOF
  1. skills_list returns:

    bar — An agent-facing skill with mismatched identifiers   (category: null)
  2. The model, acting on this output, calls skill_view("bar"):

    {"success": false, "error": "Skill 'bar' not found."}
  3. skill_view("foo") succeeds, but the model never learned the name "foo".

  4. Slash commands exhibit asymmetric behavior:

    • /bar → works (command map uses absolute path internally)
    • /foo → not registered (no command key for directory name)

Expected Behavior

The name skills_list returns should be the same name that skill_view accepts. Either:

  • skills_list reports the directory name ("foo"), making the file system the single source of truth, or
  • skill_view accepts frontmatter names as a fallback when directory lookup fails

Actual Behavior

The agent's own tool outputs contradict each other. The model discovers "bar" but can only load "foo". No warning is emitted. The skill silently becomes a dead entry in the skill list.

Affected Component

  • tools/skills_tool.py:588_find_all_skills uses frontmatter.get("name", skill_dir.name)
  • tools/skills_tool.py:958,973skill_view resolves by search_dir / name and parent.name == name
  • tools/skills_tool.py:446_get_category_from_path returns None for 2-layer paths (foo/SKILL.md), so mismatched skills also lose category attribution
  • agent/skill_commands.py:245scan_skill_commands uses frontmatter name for command key (slash commands partially work around the bug by storing absolute paths)
  • agent/skill_commands.py:280-283reload_skills diff uses slash-command snapshot, inherits the inconsistency

Debug Report

N/A — no crash. The bug is a logical inconsistency that propagates silently through the tool-calling loop. The model sees a valid error response from skill_view and has no way to know it should try a different name.

Proposed Fix

Option A (recommended): Make _find_all_skills:588 use skill_dir.name instead of frontmatter.get("name", ...). This makes the directory name the canonical identifier everywhere. The frontmatter name field becomes display-only metadata. One-line change, no fallback overhead, no ambiguity.

Option B: Add a frontmatter-name fallback in skill_view around line 977. When directory-name search fails, iterate SKILL.md files and match fm.get("name"). Preserves backwards compatibility but adds a file-read pass on every miss.

Option C: Validate on discovery that frontmatter name matches directory name; warn or skip mismatched skills. Prevents the problem at install time but requires migration for existing skills.

Operating System

All (cross-platform Python logic). Reproduced on macOS.

Additional Context

Related: #17914 covers the human UX angle of this same bug. This issue focuses on the agent tool-calling impact, which is the more critical failure mode: human users can work around a confusing name, but the model cannot.

extent analysis

TL;DR

The most likely fix is to make the directory name the canonical identifier by changing _find_all_skills to use skill_dir.name instead of frontmatter.get("name", ...), as proposed in Option A.

Guidance

  • Identify the inconsistency between skills_list and skill_view by analyzing the code paths in tools/skills_tool.py and agent/skill_commands.py.
  • Verify the issue by reproducing the steps in the issue description, specifically creating a skill with diverging names and observing the behavior of skills_list and skill_view.
  • Consider the three proposed fix options: Option A (recommended), Option B, and Option C, and evaluate their trade-offs in terms of simplicity, backwards compatibility, and performance.
  • To mitigate the issue, ensure that the name field in the frontmatter matches the directory name for all skills, or implement a validation mechanism to warn or skip mismatched skills.

Example

No code snippet is provided as the issue description already includes detailed code references and proposed fixes.

Notes

The issue is specific to the agent's tool-calling pipeline and does not affect human users directly. The proposed fixes aim to resolve the logical inconsistency between skills_list and skill_view, but may require additional testing and validation to ensure backwards compatibility and performance.

Recommendation

Apply Option A (recommended) as it provides a simple and efficient solution by making the directory name the canonical identifier, eliminating the ambiguity and inconsistency between skills_list and skill_view.

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

hermes - ✅(Solved) Fix [Bug]: skill_view/skills_list name mismatch breaks agent tool-calling loop — model can't load skills it discovers [2 pull requests, 1 comments, 2 participants]