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.
Router Pattern: Smart Input Handling in Skills
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.
Understanding the Router Pattern
The router pattern follows a decision flow:
Input → [Analyze] → [Decide] → [Route] → [Handler] → Output
↓
┌────┴────┐
↓ ↓ ↓
[A] [B] [C]
The router:
- Receives input
- Analyzes characteristics to determine type or category
- Decides which handler is most appropriate
- Routes to that handler
- Returns the handler's output
Core Characteristics
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.
When to Use Router
The router pattern excels when:
- Inputs vary in format, type, or structure
- Different inputs require different processing logic
- You want to hide complexity behind a simple interface
- Handlers share a common output format
- Input type can be reliably detected
When Not to Use Router
Avoid router when:
- All inputs require the same processing
- Routing logic is simple enough for a conditional check
- Handlers have incompatible output formats
- Input type cannot be reliably detected
- Users need direct control over handler selection
Designing Router Skills
Effective routers require careful design of detection, routing logic, and handlers.
Input Detection
The router must reliably identify input types:
## Detection Strategies
### Explicit Type Declaration
User specifies the type directly.
```json
{
"input": "...",
"type": "python"
}
- Always accurate
- Requires user knowledge
File Extension
Infer type from file extension.
{
"file": "script.py"
}
- Simple and fast
- Can be misleading (.txt could be anything)
Content Analysis
Analyze content to detect type.
{
"content": "def hello(): print('hi')"
}
- Works with raw content
- Requires robust detection logic
Magic Bytes
Check file signatures for binary formats.
PDF: %PDF-
PNG: 0x89504E47
ZIP: 0x504B0304
- Very reliable for binary
- Only works for known formats
Hybrid Detection
Combine multiple strategies.
- Check explicit type if provided
- Check file extension
- Analyze content patterns
- Default to generic handler
### 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
Confidence-Based Routing
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
Rule-Based Routing
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;
}
Output Contract
interface HandlerOutput {
result: any;
metadata: {
handler: string;
version: string;
processingTime: number;
};
}
Error Contract
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
}
}
Language Detection
Detection Pipeline
-
Explicit Language If
languageis 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→ Java
-
Shebang Line Check first line for interpreter:
#!/usr/bin/env python→ Python#!/usr/bin/node→ JavaScript
-
Content Patterns Analyze code for language-specific patterns:
Python indicators:
import Xorfrom X importdef function_name():class ClassName:- Indentation-based blocks
JavaScript indicators:
const,let,vardeclarationsfunctionkeyword or arrow functionsrequire()orimport from- Curly brace blocks
TypeScript indicators:
- JavaScript patterns PLUS
- Type annotations
: string,: number interfaceortypedeclarations- Generic syntax
<T>
-
Fallback If no confident match, use generic analyzer.
Confidence Scoring
interface DetectionResult {
language: string;
confidence: number; // 0.0 to 1.0
signals: string[]; // What indicated this language
}
Require confidence > 0.7 for specialized handler.
Routing
Route Selection
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]
Routing Decision
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
Handlers
Python 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 Handler
## 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 Handler
## 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 Handler
## 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
Output
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"
}
}
Error Handling
Detection Failure
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"
}
Handler Failure
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.
Complete Failure
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.
Cascade Processing
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.
Split Processing
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
});
Discovery
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
Plugin Architecture
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 Testing
## 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 Testing
## 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
Real-World Router Examples
Universal File Processor
---
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.
Smart Query Router
---
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
Conclusion
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:
- Reliable detection: Invest in robust type/category detection
- Clear routing logic: Make routing decisions predictable and testable
- Consistent output: All handlers should produce compatible output formats
- Graceful fallback: Always have a fallback for unrecognized inputs
- Extensibility: Design for adding new handlers without changing the interface
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.