Router Pattern: Smart Input Handling in Skills
Master the router pattern for AI skills that intelligently route different inputs to specialized handlers, creating unified interfaces for diverse tasks.
Master the router pattern for AI skills that intelligently route different inputs to specialized handlers, creating unified interfaces for diverse tasks.
Not all inputs are created equal. A skill that handles code reviews might receive Python, JavaScript, or TypeScript. A document processor might encounter PDFs, Word documents, or plain text. A data transformer might face JSON, XML, or CSV. The router pattern solves this challenge by analyzing inputs and directing them to specialized handlers.
The router pattern creates a single, unified interface that intelligently dispatches work to the most appropriate processor. Users do not need to know which specific handler to call—the router figures it out automatically.
In this guide, we will explore how to design and implement router-based skills that handle diverse inputs elegantly and efficiently.
The router pattern follows a decision flow:
Input → [Analyze] → [Decide] → [Route] → [Handler] → Output
↓
┌────┴────┐
↓ ↓ ↓
[A] [B] [C]
The router:
Router-based skills have distinct properties:
Single Entry Point: Users interact with one skill regardless of input type.
Intelligent Dispatch: The router makes smart decisions about routing.
Specialized Handlers: Each handler is optimized for its specific input type.
Unified Output: Results come in a consistent format despite different handlers.
Extensible: New handlers can be added without changing the interface.
The router pattern excels when:
Avoid router when:
Effective routers require careful design of detection, routing logic, and handlers.
The router must reliably identify input types:
## Detection Strategies
### Explicit Type Declaration
User specifies the type directly.
```json
{
"input": "...",
"type": "python"
}
Infer type from file extension.
{
"file": "script.py"
}
Analyze content to detect type.
{
"content": "def hello(): print('hi')"
}
Check file signatures for binary formats.
PDF: %PDF-
PNG: 0x89504E47
ZIP: 0x504B0304
Combine multiple strategies.
### Routing Logic
Define how decisions are made:
```markdown
## Routing Decision Framework
### Priority-Based Routing
Routes are tried in priority order until one matches.
```yaml
routes:
- name: python
priority: 100
match:
extension: [".py", ".pyw"]
content: "^(import|from|def|class)"
handler: python-handler
- name: javascript
priority: 90
match:
extension: [".js", ".mjs"]
content: "(const|let|var|function|=>)"
handler: javascript-handler
- name: default
priority: 0
match: always
handler: generic-handler
Calculate confidence for each route, choose highest.
routing:
strategy: highest-confidence
minConfidence: 0.7
fallback: generic-handler
handlers:
python-handler:
signals:
- pattern: "^import"
weight: 0.3
- pattern: "def\\s+\\w+\\("
weight: 0.4
- pattern: "class\\s+\\w+:"
weight: 0.3
Explicit rules determine routing.
rules:
- if: extension in [".py"] AND size < 100KB
route: python-handler
- if: hasShebang("python")
route: python-handler
- if: contentType == "application/json"
route: json-handler
- default: generic-handler
### Handler Design
Each handler should be focused and consistent:
```markdown
## Handler Interface
All handlers must implement:
### Input Contract
```typescript
interface HandlerInput {
content: string | Buffer;
metadata: {
detectedType: string;
confidence: number;
originalRequest: any;
};
config: HandlerConfig;
}
interface HandlerOutput {
result: any;
metadata: {
handler: string;
version: string;
processingTime: number;
};
}
interface HandlerError {
success: false;
error: {
type: string;
message: string;
handler: string;
};
}
All handlers return the same output structure, ensuring consistent API.
## Implementing Router Skills
Let us build a complete router-based skill.
### Example: Universal Code Analyzer
```markdown
---
name: code-analyzer
description: Analyzes code in any supported language
version: 1.0.0
---
# Universal Code Analyzer
Analyze code quality, complexity, and issues for any supported language through a single interface.
## Architecture
Input → [Language Detector] → [Router] ↓ ┌─────────────┼─────────────┐ ↓ ↓ ↓ [Python] [JavaScript] [TypeScript] [Handler] [Handler] [Handler] ↓ ↓ ↓ └─────────────┼─────────────┘ ↓ [Output Normalizer] ↓ [Response]
---
## Input
Accept code for analysis:
```json
{
"code": "source code string",
"language": "optional language hint",
"file": "optional filename for extension detection",
"analysis": {
"complexity": true,
"security": true,
"style": true,
"suggestions": true
}
}
Explicit Language
If language is provided, use it directly.
File Extension Map extensions to languages:
.py, .pyw → Python.js, .mjs, .cjs → JavaScript.ts, .tsx → TypeScript.go → Go.rs → Rust.java → JavaShebang Line Check first line for interpreter:
#!/usr/bin/env python → Python#!/usr/bin/node → JavaScriptContent Patterns Analyze code for language-specific patterns:
Python indicators:
import X or from X importdef function_name():class ClassName:JavaScript indicators:
const, let, var declarationsfunction keyword or arrow functionsrequire() or import fromTypeScript indicators:
: string, : numberinterface or type declarations<T>Fallback If no confident match, use generic analyzer.
interface DetectionResult {
language: string;
confidence: number; // 0.0 to 1.0
signals: string[]; // What indicated this language
}
Require confidence > 0.7 for specialized handler.
routes:
python:
handler: analyze-python
minConfidence: 0.7
capabilities: [complexity, security, style, suggestions]
javascript:
handler: analyze-javascript
minConfidence: 0.7
capabilities: [complexity, security, style, suggestions]
typescript:
handler: analyze-typescript
minConfidence: 0.7
capabilities: [complexity, security, style, suggestions, types]
go:
handler: analyze-go
minConfidence: 0.8
capabilities: [complexity, style, suggestions]
generic:
handler: analyze-generic
minConfidence: 0
capabilities: [basic-analysis]
1. Get detection result with confidence
2. Find all routes where confidence >= minConfidence
3. Select route with highest match and all requested capabilities
4. If no route has all capabilities, select best partial match
5. If no confident match, use generic handler
## Python Analysis Handler
Specialized analysis for Python code.
### Capabilities
- Cyclomatic complexity per function
- Security: SQL injection, command injection, hardcoded secrets
- Style: PEP 8 compliance, naming conventions
- Suggestions: Pythonic improvements, type hints
### Processing
1. Parse AST using Python grammar
2. Walk tree for complexity calculation
3. Pattern match for security issues
4. Check style against PEP 8 rules
5. Identify improvement opportunities
### Output
Standard analysis result format (see Output section)
## JavaScript Analysis Handler
Specialized analysis for JavaScript/Node.js code.
### Capabilities
- Cyclomatic complexity
- Security: XSS, prototype pollution, eval usage
- Style: ESLint-compatible checks
- Suggestions: Modern syntax, async patterns
### Processing
1. Parse AST using JavaScript grammar
2. Calculate complexity metrics
3. Scan for security anti-patterns
4. Check style consistency
5. Suggest modernizations
### Output
Standard analysis result format
## TypeScript Analysis Handler
Specialized analysis for TypeScript code.
### Capabilities
- All JavaScript capabilities PLUS
- Type coverage analysis
- Type safety checks
- Interface/type suggestions
### Processing
1. Parse TypeScript AST
2. Include all JavaScript analysis
3. Analyze type annotations
4. Check type safety patterns
5. Suggest type improvements
### Output
Standard analysis result format with type section
## Generic Analysis Handler
Fallback for unrecognized or unsupported languages.
### Capabilities
- Basic pattern matching
- Generic complexity heuristics
- Common security patterns
- Universal style checks
### Processing
1. Apply language-agnostic analysis
2. Look for common patterns (functions, classes)
3. Check for obvious security issues
4. Basic style assessment
### Output
Standard format with reduced detail
Note: Includes flag indicating generic analysis was used
All handlers produce consistent output:
{
"success": true,
"language": {
"detected": "python",
"confidence": 0.95,
"handler": "analyze-python"
},
"analysis": {
"complexity": {
"overall": "moderate",
"score": 15,
"functions": [
{
"name": "process_data",
"complexity": 8,
"location": {"line": 10, "column": 0}
}
]
},
"security": {
"issues": [
{
"severity": "high",
"type": "sql-injection",
"message": "Possible SQL injection vulnerability",
"location": {"line": 25, "column": 12},
"suggestion": "Use parameterized queries"
}
],
"score": 70
},
"style": {
"violations": [
{
"rule": "line-length",
"message": "Line exceeds 80 characters",
"location": {"line": 15},
"fixable": true
}
],
"score": 85
},
"suggestions": [
{
"type": "improvement",
"message": "Consider using list comprehension",
"location": {"line": 30},
"example": "result = [x * 2 for x in items]"
}
]
},
"summary": {
"overallScore": 78,
"issueCount": 5,
"criticalIssues": 1,
"recommendations": [
"Fix SQL injection vulnerability on line 25",
"Reduce complexity in process_data function"
]
},
"metadata": {
"processingTime": 245,
"linesAnalyzed": 150,
"version": "1.0.0"
}
}
If language cannot be detected with any confidence:
{
"success": true,
"language": {
"detected": "unknown",
"confidence": 0.0,
"handler": "analyze-generic"
},
"warning": "Could not detect language, using generic analysis"
}
If a specialized handler fails:
{
"success": false,
"error": {
"type": "HandlerError",
"message": "Python handler failed to parse code",
"handler": "analyze-python",
"fallback": "Attempting generic analysis"
}
}
Then attempt fallback to generic handler.
If all handlers fail:
{
"success": false,
"error": {
"type": "AnalysisFailed",
"message": "Unable to analyze code",
"attempted": ["analyze-python", "analyze-generic"],
"suggestion": "Check that code is valid and complete"
}
}
## Advanced Routing Techniques
### Multi-Route Processing
Sometimes input should go to multiple handlers:
```markdown
## Multi-Route Patterns
### Parallel Processing
Send input to multiple handlers simultaneously.
```yaml
routing:
strategy: parallel
handlers:
- security-scanner
- performance-analyzer
- style-checker
merge: aggregate-results
Use case: Different aspects of the same input analyzed separately.
Try handlers in sequence until one succeeds.
routing:
strategy: cascade
handlers:
- specialized-handler
- fallback-handler
- generic-handler
stopOn: success
Use case: Prefer specialized processing but ensure coverage.
Different parts of input go to different handlers.
routing:
strategy: split
splitter: detect-sections
routing:
code: code-handler
documentation: doc-handler
config: config-handler
merge: combine-sections
Use case: Mixed content files (like README with code blocks).
### Dynamic Handler Discovery
Handlers can be added dynamically:
```markdown
## Handler Registry
### Registration
```typescript
interface HandlerRegistration {
name: string;
version: string;
capabilities: string[];
supportedTypes: string[];
handler: HandlerFunction;
priority: number;
}
registry.register({
name: "rust-handler",
version: "1.0.0",
capabilities: ["complexity", "safety", "style"],
supportedTypes: ["rust", ".rs"],
handler: rustAnalyzer,
priority: 100
});
Router queries registry for matching handlers:
1. Get all handlers supporting detected type
2. Filter by required capabilities
3. Sort by priority
4. Return best match
External handlers can register:
plugins:
- path: ./handlers/rust-handler
autoload: true
- path: ./handlers/kotlin-handler
autoload: true
### Contextual Routing
Route based on context, not just input type:
```markdown
## Context-Aware Routing
### Factors Beyond Content
- User preferences
- Project configuration
- Historical patterns
- Resource availability
- Performance requirements
### Example
```yaml
routing:
rules:
- if: user.preferences.strict == true
use: strict-handlers
- if: project.framework == "react"
use: react-optimized-handlers
- if: input.size > 100KB
use: streaming-handlers
- if: deadline < 5s
use: fast-handlers
default: standard-handlers
## Testing Router Skills
Routers require comprehensive testing of detection and routing logic.
### Detection Testing
```markdown
## Detection Test Suite
### Positive Tests
Each language should be correctly detected:
- Python: `def hello(): pass`
- JavaScript: `const x = () => {}`
- TypeScript: `const x: string = "hi"`
- Go: `func main() {}`
- Rust: `fn main() {}`
### Negative Tests
Unrecognized content should not match:
- Plain text: "This is just text"
- Unknown code: Made-up syntax
### Edge Cases
- Empty input: Should handle gracefully
- Ambiguous: Could be multiple languages
- Polyglot: Valid in multiple languages
- Partial: Incomplete code snippets
### Confidence Calibration
Verify confidence scores are accurate:
- Clear Python: confidence > 0.9
- Obfuscated Python: confidence 0.6-0.8
- Python-like: confidence < 0.5
## Routing Test Suite
### Handler Selection
- Python code → python-handler
- JavaScript code → javascript-handler
- Unknown → generic-handler
### Capability Matching
- Request security on Python → uses python-handler
- Request types on JS → falls back or errors appropriately
### Priority Testing
- TypeScript matches both TS and JS patterns
- Verify TS handler selected over JS
### Fallback Testing
- Simulate handler failures
- Verify fallback chain works
- Confirm error reporting
## Integration Tests
### End-to-End
Input: Real Python file
Expected: Complete analysis with Python-specific insights
### Cross-Handler Consistency
Same conceptual issue in different languages
Should be reported consistently
### Performance
Various input sizes and types
Verify routing overhead is minimal
---
name: file-processor
description: Processes any file type through appropriate handler
---
# Universal File Processor
## Supported Types
- Documents: PDF, DOCX, TXT, MD
- Data: JSON, CSV, XML, YAML
- Code: Python, JS, TS, Go, Rust
- Images: PNG, JPG, SVG (metadata extraction)
## Detection
1. Check MIME type if available
2. Check file extension
3. Analyze magic bytes
4. Content pattern matching
## Routing
Route to specialized processor:
- document-processor
- data-processor
- code-processor
- image-processor
Each returns normalized output format.
---
name: query-router
description: Routes queries to appropriate knowledge handlers
---
# Smart Query Router
## Query Types
- Factual: Questions about facts
- Procedural: How-to questions
- Analytical: Why/how questions
- Creative: Generation requests
- Code: Programming questions
## Detection
Analyze query structure and intent:
- "What is..." → Factual
- "How do I..." → Procedural
- "Why does..." → Analytical
- "Write a..." → Creative
- Contains code/tech terms → Code
## Routing
- Factual → knowledge-base-handler
- Procedural → step-generator-handler
- Analytical → reasoning-handler
- Creative → generation-handler
- Code → code-assistant-handler
The router pattern creates powerful, user-friendly interfaces that hide complexity behind smart input handling. Instead of requiring users to know which specific handler to call, routers figure it out automatically.
Key principles for effective router skills:
Start with a simple router handling two or three input types. As you gain confidence in your detection and routing logic, expand to cover more cases. The goal is a single, intuitive interface that just works regardless of what users throw at it.
The router pattern is your tool for building unified, intelligent interfaces that adapt to diverse inputs automatically.
Design short-term, long-term, and graph-based memory architectures for agents