关于 skill-router
根据意图选择合适的技能,并输出可直接粘贴的命令。读取 MANIFEST.json(若没有清单,则读取每个 SKILL.md 的 frontmatter),并根据 use_when 短语、精选关键词和 not_for 排除项为意图评分。当 Agent 安装了多个技能、需要在开始操作前选择一个入口,或想知道哪个脚本负责“给我做个 Logo”而哪个负责“阅读此页面”时使用。
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ aminmzadev/ keyless-agent-skills --skill skill-router安装后在 Claude Code 中输入/skill-router确认已加载。
附带文件scripts/route.py
README 原文English
来自项目 READMEREADME 暂无中文译文,以下为英文原文;中文介绍见上方。
skill-router
One command that answers "which of these seven things do I run?".
route.py "make me a logo for a coffee shop"
# anon-image (1.88)
# python3 anon-image/scripts/imgen.py gen "make me a logo for a coffee shop" -o out.jpg
route.py "which skill handles PDFs" --top 3
route.py "I need a voiceover for my video" --explain
route.py --list
route.py "read this page" --json
What it actually does
-
Find the pack.
--skills-dir, else$AGENT_SKILLS_DIR, else walk up from the script until it seesMANIFEST.json(or a directory ofSKILL.mdfiles). -
Load the catalogue.
MANIFEST.jsonif present — it carriesuse_when,not_for,keywords,entryandcommands. No manifest? It parses the YAML frontmatter of everySKILL.mdand guesses the entry point fromscripts/. That fallback is what makes this work for other people's skill packs too. -
Score the intent.
score = 3.0 × best match against any use_when phrase + 3.0 × curated keyword hit rate (two hits = full credit) + 1.5 × keyword overlap with description + 1.5 × keyword overlap with the skill name − 4.0 × match against not_for (a veto, not a nudge)not_foris the field that stops an agent trying to generate music with a TTS endpoint, so it is weighted heavier than any positive signal. -
Refuse to guess. Below
1.00it prints "no confident match" and the closest three, exit code1. A wrong confident answer costs an agent more than an honest shrug — it will spend four tool calls doing the wrong thing. -
Print a command, not advice. The output is pasteable and already contains the intent where the skill takes free text.
Special case: meta questions
"which skill / what tool / list skills / what should I use" is a question about the
pack, not a task. Bag-of-words scoring will never rank the router first for those, so
there is an explicit detector that does. It is deliberately narrow — "route this: I
need a podcast intro" still routes to anon-audio, because route alone is not a
meta signal.
Composition hint
When the runner-up is within ~1.2 points and the winner declares it in
composes_with, the router says so:
anon-audio (2.62)
python3 anon-audio/scripts/tts.py say "I need a voiceover for my video" -o out.mp3
Becomes, when ffmpeg-pipeline wins by a hair:
note: close call with anon-audio and it composes — ffmpeg-pipeline can call it for you
That one line is usually the correct answer: the task genuinely needs two skills.
Output contract
| Mode | Shape |
|---|---|
| default | skill (score) + indented command (+ alternatives when --top > 1) |
--json | {intent, root, match:{skill,entry,command,score}, alternatives[], all[]} |
--explain | the per-field score breakdown for the winner |
--list | the whole routing table: name, entry, first use_when phrase |
Exit codes: 0 matched · 1 nothing above threshold · 2 no skills found.
Failure modes
| Symptom | Meaning | Action |
|---|---|---|
no confident match | intent too vague, or genuinely not covered | rephrase with the object you want ("logo", "voiceover", "PDF"); the three closest are printed |
everything scores 0.00 | no skill owns those words | check --list; the pack has no such capability and it is telling you so |
| wrong skill wins | that skill's keywords are too broad | edit keywords in MANIFEST.json — the router is data-driven on purpose, fixing routing should not mean editing Python |
no skills found | pack layout not recognised | --skills-dir /path/to/pack or export AGENT_SKILLS_DIR |
only one skill found under … | you installed the router on its own — there is nothing to route between | point it at a pack: --skills-dir ~/agent-skills or export AGENT_SKILLS_DIR=~/agent-skills |
Notes for the agent
- Run the router once, before a multi-step task, not before every call. It costs nothing but it is a decision, not a reflex.
--jsonif you are parsing; the human output is for humans and its exact spacing is not a contract.- If the router says no confident match and you still think a skill applies, run it
anyway with
--provider-style explicit arguments — the router is a hint, and the scripts are the source of truth.