# How to Configure Custom Routing Rules in routing.json for New Skill Types

> Learn to configure custom routing rules in routing.json for new skill types. Add route entries and update priority arrays for seamless integration and control.

- Repository: [ZhaoXu/reverse-skill](https://github.com/zhaoxuya520/reverse-skill)
- Tags: how-to-guide
- Published: 2026-08-18

---

**To register a new skill type, add a route entry to [`skills/config/routing.json`](https://github.com/zhaoxuya520/reverse-skill/blob/main/skills/config/routing.json) specifying the label, skill path, and keyword matching rules, then insert the route ID into the priority array to control selection precedence.**

The `reverse-skill` repository uses a declarative routing system where the [`skills/config/routing.json`](https://github.com/zhaoxuya520/reverse-skill/blob/main/skills/config/routing.json) file serves as the single source of truth for all skill dispatching logic. This JSON configuration defines which skill handles each user query through regex-based keyword matching and a priority-ordered resolution mechanism. Unlike code-based routing systems, no script modifications are required—simply updating this configuration file automatically propagates changes across all routing components.

## Understanding the routing.json Structure

The [`routing.json`](https://github.com/zhaoxuya520/reverse-skill/blob/main/routing.json) file contains two top-level sections that work together to determine skill selection:

- **`routes`** — A mapping of route identifiers (e.g., `R1`, `R2`, `R41`) to route definitions containing the skill metadata and matching rules
- **`priority`** — An ordered array of route identifiers where earlier positions receive higher precedence when multiple routes match

Each route entry in `routes` follows this schema:

| Field | Type | Description |
|-------|------|-------------|
| `label` | string | Human-readable description of the skill purpose |
| `skill` | string | Relative path to the skill's markdown documentation file |
| `keywords` | array | Matching rules that determine when this route applies |
| `priority` *(implied)* | integer | Derived from position in the global `priority` array |

## Keyword Matching Rules

The `keywords` array contains objects that define query matching through regular expressions. The routing engine evaluates these rules to score each route's relevance.

### Available Matching Operators

- **`must`** — Required regex pattern that must appear in the query for this keyword object to match
- **`exclude`** *(optional)* — Disqualifying regex; if this pattern appears, the keyword object fails to match regardless of `must`
- **`mustAll`** *(optional)* — Array of additional regex patterns that must all match alongside `must`

Multiple keyword objects in the `keywords` array are evaluated independently—any matching keyword object contributes to the route's score.

## Step-by-Step: Adding a New Skill Route

### Step 1: Create Your Skill File

Before configuring routing, ensure your skill documentation exists at `skills/<your-skill>/SKILL.md`. The `skill` field in your route will reference this path relative to `skills/`.

### Step 2: Define the Route Entry

Add a new unique route identifier to the `routes` object following the established pattern in [`routing.json`](https://github.com/zhaoxuya520/reverse-skill/blob/main/routing.json). Route IDs use the format `R` followed by a number (e.g., `R41`, `R42`).

Example route for an IoT reverse engineering skill:

```json
"R41": {
  "label": "IoT / Embedded reverse",
  "skill": "iot-reverse/SKILL.md",
  "keywords": [
    {
      "must": "iot|embedded|firmware|device|microcontroller|arm|mcu|esp32|esp8266",
      "note": "All IoT-related queries should match this route"
    }
  ]
}

```

### Step 3: Set Priority Position

Insert your new route ID into the `priority` array at the desired precedence level. Routes earlier in the array win ties when multiple routes achieve equal match scores.

```json
"priority": [
  "R4", "R1", "R2", "R3", "R30", "R31", "R33", "R5", "R9", "R21",
  "R22", "R6", "R7", "R8", "R34", "R28", "R17", "R16", "R18", "R24",
  "R37", "R23", "R35", "R25", "R36", "R29", "R38", "R32", "R26", "R27",
  "R10", "R11", "R12", "R13", "R14", "R15", "R19", "R40", "R20", "R39",
  "R0", "R41"
]

```

Placing `R41` at the end gives it lowest priority; move it earlier to override more generic routes.

## Advanced Routing Patterns

### Combined Requirements with mustAll

For skills requiring multiple distinct concepts, use `mustAll` to ensure all patterns appear:

```json
"R42": {
  "label": "JTAG Firmware Extraction",
  "skill": "jtag-firmware/SKILL.md",
  "keywords": [
    {
      "must": "jtag",
      "mustAll": ["firmware", "extract|dump"],
      "note": "Ensures the query explicitly mentions JTAG and firmware extraction"
    }
  ]
}

```

This route only matches when the query contains "jtag" AND "firmware" AND either "extract" or "dump".

### Negative Exclusion Patterns

Prevent false positives by excluding ambiguous terms:

```json
"R43": {
  "label": "Cloud Function Reverse",
  "skill": "cloud-function/SKILL.md",
  "keywords": [
    {
      "must": "lambda|function|cloud",
      "exclude": "aws|gcp|azure",
      "note": "Only match custom-written cloud functions, not managed services"
    }
  ]
}

```

The `exclude` pattern prevents matching generic cloud provider queries.

## Validation and Testing

Three PowerShell scripts automatically consume [`routing.json`](https://github.com/zhaoxuya520/reverse-skill/blob/main/routing.json) and verify its integrity:

- **`skills/scripts/verify-routing-coherence.ps1`** — Validates that [`routing.json`](https://github.com/zhaoxuya520/reverse-skill/blob/main/routing.json) matches generated documentation
- **`skills/scripts/test-routing.ps1`** — Executes 162 test cases to ensure new routes don't break existing logic
- **`skills/scripts/master-route.ps1`** — The production routing engine that reads this configuration

Run these scripts after any [`routing.json`](https://github.com/zhaoxuya520/reverse-skill/blob/main/routing.json) modification to catch syntax errors or priority conflicts before deployment.

```powershell

# Run full routing test suite

.\skills\scripts\test-routing.ps1

# Verify documentation coherence

.\skills\scripts\verify-routing-coherence.ps1

```

## Summary

- **[`skills/config/routing.json`](https://github.com/zhaoxuya520/reverse-skill/blob/main/skills/config/routing.json)** is the single configuration file controlling all skill routing
- **Route entries** require a unique ID, label, skill path, and keyword matching rules
- **Keyword rules** support `must`, `exclude`, and `mustAll` regex operators for precise matching
- **Priority array** determines selection precedence—position earlier for higher priority
- **No code changes needed**—the configuration automatically propagates to validation and runtime scripts

## Frequently Asked Questions

### What happens if two routes match the same query with equal scores?

The routing engine consults the `priority` array and selects whichever matching route appears first. This deterministic tie-breaking ensures consistent behavior without requiring arbitrary tie-breaker logic in code.

### Can I use case-insensitive matching in my regex patterns?

Yes—all regex evaluation in the routing engine is case-insensitive by default, so patterns like `iot|embedded` match "IoT", "IOT", "iot", and mixed-case variants without requiring explicit case flags.

### How do I test my new route without running the full test suite?

Create a minimal test case in `skills/scripts/test-routing.ps1` or execute the routing logic directly against your query string using `master-route.ps1` with diagnostic output enabled. The test framework will automatically pick up new routes from [`routing.json`](https://github.com/zhaoxuya520/reverse-skill/blob/main/routing.json) for evaluation.

### Is there a limit to how many keyword objects a route can have?

No explicit limit exists in the schema, though practical considerations suggest keeping routes focused. Multiple keyword objects within a route are ORed together—any matching keyword contributes to the score—allowing you to cover synonymous concepts without excessive regex complexity in a single pattern.