How the Routing Priority Array in routing.json Determines Skill Selection in reverse-skill
The priority array in routing.json serves as a deterministic tie-breaker: after scoring all keyword matches, the router selects the first route from the priority list that appears among the highest-scoring candidates.
The reverse-skill repository implements a two-stage routing system where multiple skills can match the same user prompt. When keyword overlaps occur, the priority array guarantees consistent and predictable skill selection without arbitrary randomness. This mechanism is central to how the platform routes requests to the appropriate skill handler.
The Two-Stage Routing Pipeline
The routing logic operates in distinct phases, each defined in skills/config/routing.json. Understanding both stages clarifies why the priority array matters.
Stage 1: Keyword Matching and Scoring
Every incoming request is evaluated against all routes defined in the routes section of routing.json. Each route contains a keywords list with must patterns and optional exclude patterns.
The scoring rules are documented in the meta section (lines 5–7):
{
"meta": {
"scoringRule": "count_of_satisfied_keyword_rules",
"fallbackId": "R0",
"description": "Route priority: lower index = higher priority"
}
}
For each route, the router increments the score by 1 for every keyword rule whose must pattern matches and whose exclude pattern (if present) does not match. Routes with zero matches are discarded.
Stage 2: Priority Resolution for Ties
When multiple routes achieve the same highest score, the priority array (lines 16–21) breaks the tie:
{
"priority": ["R1", "R3", "R2", "R5", "R4", "R6", "R7", "R8", "R9", "R0"]
}
The router traverses this array left-to-right and selects the first route ID that exists in the candidate set. Leftmost position indicates highest precedence.
Implementation Details from the Source Code
Core Selection Logic
The routing scripts implement this pipeline in Python. The scoring and priority resolution work as follows:
import json
import re
def select_skill(prompt):
with open('skills/config/routing.json') as f:
routing = json.load(f)
candidates = {}
# Stage 1: Keyword matching → compute scores
for rid, route in routing['routes'].items():
score = 0
for kw in route['keywords']:
if re.search(kw['must'], prompt):
if 'exclude' not in kw or not re.search(kw['exclude'], prompt):
score += 1
if score:
candidates[rid] = score
if not candidates:
return routing['meta']['fallbackId'] # → "R0"
# Identify highest-scoring candidates
max_score = max(candidates.values())
highest = [rid for rid, s in candidates.items() if s == max_score]
# Stage 2: Apply priority ordering
for rid in routing['priority']:
if rid in highest:
return rid # selected route ID
return routing['meta']['fallbackId'] # defensive fallback
Entry Point Scripts
The platform invokes routing through wrapper scripts. In skills/scripts/master-route.ps1 (Windows) or master-route.sh (Linux/macOS):
$hint = "<user prompt>"
$selectedId = & python -c "import select; print(select.select_skill('$hint'))"
Write-Host "Routing selected: $selectedId"
# Subsequent logic loads the corresponding SKILL.md using the route's 'skill' field
The select_skill() function encapsulates the score → priority → fallback pipeline that determines which skill content gets retrieved.
Routing Priority Array: Design Intent
The priority array in routing.json serves three critical purposes:
- Determinism — Same input always produces same output, regardless of JSON key ordering or hash randomization
- Explicit precedence — Route priority is human-readable and version-controlled
- Conflict resolution — Overlapping keyword patterns are resolved through intentional ordering rather than implementation-dependent behavior
A validation script skills/scripts/verify-routing-coherence.ps1 ensures the priority array remains synchronized with skills/MASTER-ROUTING.md, preventing documentation drift.
Example Scenario: Multiple Keyword Matches
Consider two routes:
| Route ID | Keywords Matched | Score |
|---|---|---|
| R3 | "api", "design" | 2 |
| R5 | "api", "design" | 2 |
Both routes match equally. With priority: ["R1", "R3", "R2", "R5", ...], the router selects R3 because it appears before R5 in the array.
If the priority array were ["R1", "R5", "R3", "R2", ...], the selection would be R5 instead.
Summary
- The
priorityarray inrouting.jsonprovides deterministic tie-breaking when multiple routes achieve identical keyword match scores - Route selection follows a strict score → priority → fallback pipeline implemented in
skills/scripts/master-route.ps1andmaster-route.sh - Array position determines precedence: leftmost routes win ties against rightmost routes
- The
fallbackId("R0") catches cases where no keywords match or unexpected errors occur - Coherence between
priorityarray and documentation is enforced byverify-routing-coherence.ps1
Frequently Asked Questions
What happens if no routes match any keywords?
The router returns the fallbackId defined in routing.json's meta section, which defaults to "R0". This route typically contains a generic skill handler or error response.
Can the priority array contain routes that don't exist in the routes section?
While technically possible in JSON, the verify-routing-coherence.ps1 script validates consistency between all routing definitions. Missing routes in the priority array would cause validation failures in the CI pipeline.
How does scoring handle partial keyword matches?
Each satisfied keyword rule contributes exactly 1 point to a route's score. The router uses simple counting rather than weighted scoring, making the priority array's role as tie-breaker more significant for complex routing scenarios.
Where should I modify routing behavior for a new skill?
Add your route to skills/config/routing.json in the routes section, then insert your route ID into the priority array at your desired precedence position. Update skills/MASTER-ROUTING.md to document the change, and run verify-routing-coherence.ps1 before committing.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →