Agent router
Ranks your installed Claude Code skills/agents for a task and routes to the best one — and learns from your ratings.
npx -y skills add RamanaNani/agent-router --skill agent-routerAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
One thing to look at
- 1 stars1 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
What its author says it does
Copied from the file, not written here
When the user has a task and many skills/subagents installed and wants the BEST one chosen automatically. Use when the user says "which agent/skill should I use", "route this", "pick the best agent for", "what's the best skill for X", or asks you to find and dispatch the right specialist. Discovers all available skills and agents, ranks them for the task, and either recommends or dispatches to the top pick.
SKILL.md
12.4 KB, as published. Nobody here has run it
Agent Router
A meta-router. Given a task, it inventories every skill and subagent available in this session, scores them against the task, and routes to the best one.
When to use
- The user is unsure which of the many installed skills/agents fits their task.
- The user explicitly asks to "route", "pick the best agent", or "find a skill for X".
- Before starting a non-trivial task, to confirm a specialist exists instead of doing it generically.
Procedure
Locate the scripts once. Throughout, <scripts> is the agent-router scripts
directory. Resolve it to the first that exists: ~/.claude/agent-router/scripts/
(npx install) · ./scripts/ (this repo) · the installed plugin's own scripts/
dir. Use that prefix for every node <scripts>/*.js below.
Mode check (first). If the invocation is feedback <bad|ok|good|excellent> [note],
skip routing and go straight to step 7 (rate the last route). Otherwise run steps
0-6 to route a task.
0. Update check (one line, non-blocking)
Run node <scripts>/update-check.js and, if it prints anything, surface that single
line. It's daily-cached and silent when you're current or offline — never let it block routing.
1. Capture the task
Restate the user's task in one sentence. Note the domain (code review, research, testing, design, security, infra, data, etc.) and any constraints (language, framework, speed vs. depth).
1a. Decompose multi-task requests (do NOT collapse to one tool)
If the request bundles multiple distinct tasks ("audit X, fix the SSE latency, add inline citations, find optimizations"), routing the whole thing to a single agent is the #1 failure mode — it leaves most of the request unaddressed. Instead:
- Split it into sub-tasks; run steps 2-4 to route each sub-task to its own best specialist.
- Classify dependencies:
- Independent sub-tasks → dispatch in parallel (multiple Task calls in one turn).
- Dependent sub-tasks (B needs A's output — e.g. "fix the latency" needs the audit first) → sequence them, and say why.
- Show the decomposition as a short plan first —
sub-task → chosen tool → parallel | after <X>— so the user sees all N tasks are covered, not just one. Then dispatch per the plan and give one consolidated Run summary (5a) spanning every sub-task. A single-tool route is correct only when the request is genuinely one task.
2. Inventory via the retrieval index (do NOT read every skill)
You may have thousands of installed skills/agents across ~/.claude/skills/,
~/.claude/agents/, and ~/.claude/plugins/ — far too many to read each one, and
eyeballing only the session-list names silently misses whole families (gstack, etc.).
Use the index instead:
node <scripts>/build-index.js # refresh (fast; only re-tokenizes changed files)
node <scripts>/build-index.js --query "<the task text>" # top ~15 candidates across EVERYTHING installed
The index (BM25 + optional dense, RRF-fused) covers top-level skills/agents and the
full plugins tree, so gstack/ecc/ruflo are all in scope. Take its top ~15 as your
candidate set, plus any obviously-relevant tool from the session list it missed. For
each, record name, type (skill|agent), description, source.
If build-index.js is unavailable (plugin-only install without the scripts), fall
back to scanning ~/.claude/skills/*/SKILL.md + ~/.claude/agents/*.md + the session
list, and tell the user the index would make the inventory far more complete.
3. Score each candidate (0-100)
Combine three signals:
-
Relevance (0-60): semantic match between the task and the candidate's
description+name. Exact-domain match scores high; generic matches low. -
Specificity (0-20): a purpose-built specialist beats a catch-all (e.g.
python-reviewer> genericcode-reviewerfor Python). -
Reputation (0-20): combine two separate sources —
- the curated baseline registry (
tools[]) — shareable, shipped with the package, the same for everyone. Read it from the installed location~/.claude/agent-router/data/registry.json(in this source repo it lives atdata/registry.json); and - your personal learned overlay at
~/.claude/agent-router/learned.json(per-(domain,tool) scores from your own ratings — see step 7), which is private and never lives in the repo.
Prefer the learned score when this (domain,tool) has been rated before; else use the curated score; else default 10. The skill only references the private overlay at runtime — internal/runtime data and the shareable skill stay separate. Optionally refine with a web search when the user wants "market findings".
- the curated baseline registry (
Drop anything scoring < 25 as irrelevant.
4. Present the ranking
Show the top 3-5 as a table: rank, name, type, score, one-line reason. Always state WHY the top pick won and what the runner-up would be better at.
5. Route
- If the top candidate is an agent and the user wants it done: dispatch it via the
Task tool (
subagent_type: <name>), passing the restated task. Append this operating contract to every dispatch prompt so the work is legible, verified, and safe when it returns — these four guardrails are mandatory, not optional:1. Plan before high-risk edits. Before editing a high-risk surface — auth/RLS, DB migrations, citations, artifact/file storage, memory writes, SSE contracts, file uploads, or anything touching credentials/secrets — first state a 5-line plan: root cause · files you'll change · files off-limits · behavior that must not change · the test that proves success. Then implement. (Low-risk edits can skip the plan.) 2. Verify by running, not by reasoning. Run the test, command, or actual product flow that exercises your change and report the OBSERVED result. Never claim a pass you did not see. Prefer a repeatable smoke test/script over an in-your-head check. 3. Security is non-negotiable. If you find or cause any secret exposed in plaintext (an
.env, hardcoded token, AWS / Anthropic / Supabase JWT key, etc.), treat it as COMPROMISED: flag it for immediate rotation and never recommend deferring rotation. Do not print secret values. 4. Close with proof. End your reply with a## What I didsection (each file changed: path + what/why; commands run; anything skipped or unverified) AND a## Final acceptancechecklist: files changed · commands run · tests passing (y/n) · manual flow tested (y/n + what) · migrations applied (y/n/NA) · known deferred items · risky areas touched · rollback plan · decision (accept / needs another pass). - If the top candidate is a skill: invoke it via the Skill tool (or tell the user the
/commandto run). - If two candidates are within 5 points, ask the user to choose (show both).
- Nothing scored ≥ 25 (no installed tool fits)? Don't stop at "nothing found" —
automatically run
/skill-finderfor this task. It searches the marketplace + web + curated catalog for an uninstalled specialist and returns ranked options with the exact install command. Never invent a tool that doesn't exist.
5a. Report what the agent(s) did (consolidated summary)
After any dispatched agent finishes, don't just end the turn — print a clean consolidated report so the user sees what happened without expanding each subagent transcript:
## Run summary
**<agent> — <surface / scope>** (<N> tool uses)
- Changed: <file> — <what / why>
- Verified: <command> → <pass | fail> (observed, not assumed)
- Skipped / flagged: <anything deferred or uncertain>
- Acceptance: tests <y/n> · manual flow <y/n> · migrations <y/n/NA> · rollback <one line> · <accept | needs another pass>
- Security: <none | SECRET EXPOSED — rotate now: which key(s)>
One block per dispatched agent (pull Changed/Verified/Skipped from its ## What I did
section and the Acceptance/Security lines from its ## Final acceptance checklist). If
agents ran in parallel, show all blocks, then a one-line Net: of the combined result
(e.g. "both surfaces compile; Supabase JWT secret exposed — rotate before merge"). Surface
any unrotated secret loudly — never let it sit in the deferred list. Keep it tight — this is
the at-a-glance view; the full transcript is still one keypress away (ctrl+o / the agent panel).
5b. Ask for a rating (native-style, one keypress)
Right after routing, close with a single compact line that mirrors Claude Code's own session-feedback widget — optional, one character, never blocking:
Rate this route?
1bad ·2ok ·3good ·4excellent ·0skip
If the user's next message is a single digit 1-4, record it immediately and learn in the
background (step 7): node <scripts>/feedback.js <digit>. 0, "skip", or anything unrelated =
leave the row unrated and move on. Never re-ask, never block on it. (A skill can't render the
real keypress widget — this one-line digit prompt is the closest equivalent.)
6. Log the decision (internal dogfooding)
After every routing decision, append ONE JSONL line to your decision log so you
can review and improve routing over time:
Use the log subcommand — it JSON-encodes every value, so quotes / $() / backticks in the
task text can't corrupt the line or inject a shell command. Never hand-build the JSON with
echo.
node <scripts>/hina-memory.js log \
--skill agent-router --task "$TASK" --domain "$DOMAIN" \
--chosen "$CHOSEN" --chosen-score "$SCORE" --runner-up "$RUNNER_UP" --action "$ACTION"
Fill the placeholders; leave outcome/feedback/rating/reward empty — they get
filled later by the rating step (7). Misroutes and "action":"none" rows are the
highest-value signals — they show which data/registry.json scores to fix or which
new skill to add. Run node <scripts>/review-logs.js to summarize the log.
7. Capture a rating (closes the learning loop)
A route teaches the router nothing until it's rated — learn.js only trains on rows
that carry a reward. Rating uses a 4-level scale that maps to a reward in [0,1]:
| rating | reward |
|---|---|
| bad | 0.0 |
| ok | 0.34 |
| good | 0.67 |
| excellent | 1.0 |
When the user invokes /agent-router feedback <bad|ok|good|excellent> [note], skip
routing and record it instantly, then learn in the background — the user must never
wait on processing:
node <scripts>/feedback.js <bad|ok|good|excellent> [note] # instant: one-line append to the last row
node <scripts>/learn.js >/dev/null 2>&1 & # detached: retrain the bandit, do NOT block
The first command is a sub-second append. The second folds the rating into learned.json
and runs detached (&), so confirm the rating in one line ("logged ✓ — good (0.67)") and
let the user go straight to their next task. Never make them wait for the learning step.
(feedback.js sets rating, reward, a back-compat outcome, and any note as feedback on
the most recent row in ~/.claude/agent-router/logs/decisions.jsonl.)
In a plain terminal, running it with no args opens an interactive rater that shows the last route and waits for a single keypress:
[1] bad [2] ok [3] good [4] excellent [f] add a note [s] skip
Tip: add a shell alias so rating is one key — alias f='node ~/.claude/agent-router/scripts/feedback.js' — then just type f after a route.
Periodically fold ratings into the reputation scores:
node <scripts>/learn.js # discounted bandit over graded rewards -> ~/.claude/agent-router/learned.json (private)
node <scripts>/review-logs.js # summary: most-routed, gaps, ratings
Output contract
Return: (a) the ranked table, (b) the chosen route + why, (c) the result if you dispatched, or the exact command for the user to run if you did not.
Notes
- Never recommend a skill/agent you did not actually find in the inventory.
- "Market findings" = the
data/registry.jsonscores plus, only if asked, a web search for the tool's reputation. Keep it cheap by default.