Most skill systems get harder to trust as they grow.
Not because they lack more leaf skills. Because the selection layer turns fuzzy.
One folder starts collecting related skills. Then another. Eventually the family boundary lives half in directory names, half in tribal knowledge, and half in a giant umbrella document that quietly tries to do the children’s jobs itself.
That is exactly the problem the create-router-skill package inside agents-docs-kits is trying to solve.
A router is a real skill, not a label
The strongest line in the source file is also the most important design rule: a router skill is not just a category label. It is a real entrypoint with a narrow job.
That job is simple:
- decide which child skill should handle the request
- hand off cleanly
- stay honest about what happens when the best child is missing
That sounds small, but it fixes a common failure mode. Without an explicit router, discoverability drifts. The agent sees a family of related skills but has no stable place to start, no declared selection order, and no truthful fallback policy.
A good router makes the family boundary explicit without pretending to be the family itself.
What create-router-skill insists on
The package is opinionated in the right places.
It says the router should stay discoverable at the top level. It says the router should not quietly perform the full child workflow. It says child metadata should be explicit in references/children.json rather than inferred from folder names. And it says missing-child behavior must tell the truth: install the correct child when possible, otherwise disclose the fallback instead of silently degrading.
That is the right contract for a routing layer.
A selector that quietly solves the task inline is not acting like a router. It is acting like an overloaded umbrella skill. A family that depends on folder structure alone is not really modeled at all. It is just arranged.
The important file is not only SKILL.md
One of the better ideas in this package is where it puts the moving parts.
The router SKILL.md stays focused on a few things:
- the family boundary
- selection order
- install, fallback, and missing-child policy
- output format for the route decision
The change-prone child inventory lives somewhere else: references/children.json.
That matters because router logic and child metadata change at different rates. The family contract should stay readable. The child graph should stay explicit and machine-readable.
The supporting reference file makes the intent plain. children.json is where the router records:
- child summaries
- selection order
- positive routing signals
- negative routing signals
- companion relationships like
requiresandrecommends - degraded paths like
fallbacks_to - install hints for missing nested skills
That is much more honest than forcing every relationship into the directory tree.
Routers are graphs, not trees
The relationship-types reference is worth calling out because it fixes another subtle lie.
Skill families are rarely a clean tree.
Some children are primary routes. Some are bundled companions. Some require another skill before they are safe to use. Some merely recommend a post-check. Some have a weaker fallback that is still honest, but not equivalent.
The package names those relationships explicitly:
routes_toincludesrequiresrecommendsfallbacks_to
That naming matters because a fallback is not the same thing as a recommendation, and a recommendation is not the same thing as a prerequisite. When systems flatten those distinctions, the next agent starts improvising.
The layout tells the truth about the family
The default package shape is also doing real design work:
router-name/
├── SKILL.md
├── references/
│ ├── children.json
│ ├── router-metadata.md
│ └── relationship-types.md
├── scripts/
│ └── validate_router.py
├── assets/
│ ├── router-skill-template.md
│ └── children-template.json
├── evals/
│ ├── evals.json
│ └── trigger-evals.json
├── child-one/
│ └── SKILL.md
└── child-two/
└── SKILL.md The point is not aesthetics. The point is that the package boundary now communicates what the router owns:
- the family entrypoint
- the child inventory
- the validation logic
- the evals that prove the routing is better than the baseline
- the bundled leaf skills that belong inside that family
This is cleaner than a loose category page, and much more honest than a giant umbrella skill that duplicates every child body.
Validation and evals are part of the contract
Another good choice in create-router-skill is that it does not stop at structure.
It requires validation:
python3 scripts/validate_router.py <router-dir> And it requires evaluation against a believable baseline.
The package asks for at least three prompt classes in evals/evals.json:
- a direct family match
- an ambiguous boundary case
- a noisy case with misleading category words
That is the right test. A router is only useful if it chooses better than no router, a flat list, or the previous version. Otherwise it is just extra prose.
Why this skill is worth introducing
agents-docs-kits is already useful as a minimal docs scaffold. create-router-skill shows the repo has a more specific opinion too: agent tooling should not hide its selection logic.
As skill surfaces grow, the routing layer becomes part of the product. If that layer is vague, the whole family becomes harder to discover, harder to extend, and easier to misuse.
This package pushes in the opposite direction. It says routers should stay small, explicit, and honest. They should choose. They should disclose. They should hand off. They should let leaf skills remain leaf skills.
That is a good rule well beyond this one repository.
If you want to read the source directly, start here: create-router-skill/SKILL.md.