Skip to content

Intelligent Routing

BobaMixer's intelligent routing system automatically selects the optimal AI profile based on context, task type, project characteristics, and usage patterns.

Overview

Routing rules allow you to:

  • Optimize costs by using cheaper models for simple tasks
  • Improve quality by using better models for complex work
  • Save time by using faster models when appropriate
  • Explore alternatives with epsilon-greedy optimization
  • Adapt to context based on project, branch, time, and more

How Routing Works

  1. Rule Evaluation: Rules are evaluated in order (first match wins)
  2. Condition Checking: Each rule's condition is evaluated against current context
  3. Profile Selection: When a rule matches, its profile is selected
  4. Fallback Handling: If the selected profile fails, fallback is used
  5. Exploration: Occasionally (ε% of time), alternative profiles are tested

Configuration

Routes are defined in ~/.boba/routes.yaml:

yaml
rules:
  - id: rule-identifier
    if: "condition expression"
    use: profile-name
    fallback: backup-profile
    explain: "Why this rule exists"

exploration:
  enabled: true
  epsilon: 0.03
  min_samples: 10

Routing DSL

Available Variables

VariableTypeDescriptionExample
ctx_charsintInput character countctx_chars > 50000
textstringInput text contenttext.contains('code')
project_typesarrayProject typesproject_types.includes('go')
branchstringGit branch namebranch.matches('main')
time_of_daystringTime periodtime_of_day == 'night'
intentstringDetected intentintent == 'format'

Time of Day Values

  • morning - 6 AM to 12 PM
  • day - 12 PM to 6 PM
  • evening - 6 PM to 10 PM
  • night - 10 PM to 6 AM

Available Functions

FunctionDescriptionExample
text.matches(pattern)Regex match (case-insensitive)text.matches('\\bformat\\b')
text.contains(str)Substring searchtext.contains('review')
array.includes(item)Array membershipproject_types.includes('react')

Operators

  • Comparison: >, <, >=, <=, ==, !=
  • Logical: && (and), || (or), ! (not)
  • Parentheses: (...) for grouping

Common Routing Patterns

1. Context Size-Based Routing

Route based on input size:

yaml
rules:
  - id: extra-large-context
    if: "ctx_chars > 100000"
    use: claude-opus
    fallback: claude-sonnet
    explain: "Very large context requires highest capacity model"

  - id: large-context
    if: "ctx_chars > 50000"
    use: claude-sonnet
    fallback: claude-haiku
    explain: "Large context needs capable model"

  - id: medium-context
    if: "ctx_chars > 10000"
    use: claude-haiku
    explain: "Medium context, balanced model"

  - id: small-context
    if: "ctx_chars > 0"
    use: gpt-4o-mini
    explain: "Small context, economical model"

Why this works: Larger contexts need models with higher capacity. This pattern optimizes costs while ensuring quality.

2. Task Type Recognition

Route based on task keywords:

yaml
rules:
  - id: code-generation
    if: "text.matches('write.*function|implement|create.*class|build.*API')"
    use: code-specialist
    explain: "Code generation task"

  - id: code-review
    if: "text.matches('review|analyze.*code|find.*bug|refactor')"
    use: code-reviewer
    explain: "Code review task"

  - id: formatting
    if: "text.matches('format|prettier|eslint|lint|style')"
    use: fast-formatter
    explain: "Simple formatting, use fast model"

  - id: documentation
    if: "text.matches('document|explain|write.*docs|README|comment')"
    use: doc-writer
    explain: "Documentation task"

  - id: testing
    if: "text.matches('test|spec|unit test|integration test')"
    use: test-specialist
    explain: "Testing task"

Why this works: Different tasks have different requirements. Code generation needs creativity, while formatting just needs accuracy.

3. Project Type Routing

Route based on project characteristics:

yaml
rules:
  - id: frontend-react
    if: "project_types.includes('react') || project_types.includes('vue')"
    use: frontend-specialist
    explain: "Frontend framework project"

  - id: backend-go
    if: "project_types.includes('go')"
    use: backend-go-specialist
    explain: "Go backend project"

  - id: backend-rust
    if: "project_types.includes('rust')"
    use: backend-rust-specialist
    explain: "Rust backend project"

  - id: ml-python
    if: "project_types.includes('python') && text.matches('tensor|model|train|dataset')"
    use: ml-specialist
    explain: "Machine learning task"

  - id: data-analysis
    if: "project_types.includes('python') && text.matches('analyze|dataframe|csv|pandas')"
    use: data-specialist
    explain: "Data analysis task"

Why this works: Specialized models for specific tech stacks can provide better, more accurate responses.

4. Branch-Based Routing

Different profiles for different branches:

yaml
rules:
  - id: production-branch
    if: "branch.matches('main|master|prod')"
    use: high-accuracy
    fallback: medium-accuracy
    explain: "Production branch, use most accurate model"

  - id: staging-branch
    if: "branch.matches('staging|stage')"
    use: medium-accuracy
    explain: "Staging branch, balanced model"

  - id: feature-branch
    if: "branch.matches('feature/.*|feat/.*')"
    use: balanced-model
    explain: "Feature development"

  - id: hotfix-branch
    if: "branch.matches('hotfix/.*|fix/.*')"
    use: fastest-model
    explain: "Urgent fix, prioritize speed"

  - id: experiment-branch
    if: "branch.matches('exp/.*|test/.*|playground/.*')"
    use: experimental-model
    explain: "Experimental work"

Why this works: Production code needs more careful review, while experiments can use faster/cheaper models.

5. Time-Based Routing

Optimize costs during off-peak hours:

yaml
rules:
  - id: night-mode
    if: "time_of_day == 'night'"
    use: cost-optimized
    explain: "Off-peak hours, use cheaper model for cost savings"

  - id: business-hours
    if: "time_of_day == 'day' || time_of_day == 'morning'"
    use: high-performance
    explain: "Business hours, prioritize speed and quality"

  - id: evening-balanced
    if: "time_of_day == 'evening'"
    use: balanced-model
    explain: "Evening work, balanced approach"

Why this works: Your budget can stretch further by using cheaper models during non-critical hours.

6. Multi-Condition Rules

Combine multiple conditions:

yaml
rules:
  - id: complex-backend-refactor
    if: "ctx_chars > 20000 && project_types.includes('go') && text.matches('refactor|optimize|improve')"
    use: senior-engineer
    explain: "Complex backend refactoring needs expert model"

  - id: urgent-production-fix
    if: "branch.matches('hotfix/.*') && text.contains('urgent')"
    use: fastest-accurate
    fallback: fastest-model
    explain: "Urgent production fix, speed critical"

  - id: large-frontend-feature
    if: "ctx_chars > 30000 && project_types.includes('react') && text.matches('feature|component')"
    use: frontend-expert
    explain: "Large frontend feature needs specialized model"

  - id: simple-night-task
    if: "ctx_chars < 5000 && time_of_day == 'night'"
    use: mini-model
    explain: "Simple task at night, minimize cost"

Why this works: Combining conditions allows precise targeting of specific scenarios.

7. Cost-Aware Routing

Balance cost and capability:

yaml
rules:
  - id: critical-quality
    if: "text.matches('production|customer-facing|critical|important')"
    use: premium-model
    fallback: good-model
    explain: "Quality critical work, use best model"

  - id: non-critical-small
    if: "ctx_chars < 5000 && !text.matches('critical|important|urgent')"
    use: mini-model
    explain: "Small, non-critical task, minimize cost"

  - id: bulk-processing
    if: "text.contains('batch') || text.contains('multiple files')"
    use: economical-model
    explain: "Bulk processing, optimize for cost"

  - id: exploratory-work
    if: "text.matches('explore|experiment|try|investigate')"
    use: cheap-model
    explain: "Exploratory work, cost over quality"

Why this works: Not all tasks need the best model. Save budget for what matters.

8. Content Type Detection

Route based on content type:

yaml
rules:
  - id: data-analysis
    if: "text.matches('analyze.*data|CSV|JSON|dataframe|SQL')"
    use: data-specialist
    explain: "Data analysis task"

  - id: image-work
    if: "text.contains('image') || text.contains('screenshot') || text.contains('visual')"
    use: vision-model
    explain: "Image-related task needs vision capability"

  - id: pure-text
    if: "ctx_chars > 0"
    use: text-model
    explain: "Pure text task"

Why this works: Different content types need different model capabilities.

Advanced Patterns

Intent-Based Routing

yaml
rules:
  - id: format-intent
    if: "intent == 'format'"
    use: fast-formatter
    explain: "Formatting intent detected"

  - id: review-intent
    if: "intent == 'review'"
    use: code-reviewer
    explain: "Code review intent"

  - id: generate-intent
    if: "intent == 'generate'"
    use: code-generator
    explain: "Code generation intent"

Note: Intent detection requires configuration or integration with external intent classifier.

Cascading Rules

yaml
rules:
  # Highest priority: Production critical
  - id: prod-critical
    if: "branch.matches('main') && text.contains('critical')"
    use: best-model
    explain: "Production critical work"

  # Medium priority: Production non-critical
  - id: prod-normal
    if: "branch.matches('main')"
    use: good-model
    explain: "Production work"

  # Lower priority: Other branches
  - id: dev-work
    if: "ctx_chars > 10000"
    use: medium-model
    explain: "Development work"

  # Fallback: Everything else
  - id: default
    if: "ctx_chars > 0"
    use: economical-model
    explain: "Default for small tasks"

Why this works: Most specific rules first, gradually broadening to catch everything.

Dynamic Thresholds

yaml
rules:
  # Adjust thresholds based on project type
  - id: large-go-project
    if: "project_types.includes('go') && ctx_chars > 30000"
    use: go-specialist
    explain: "Large Go codebase"

  - id: large-python-project
    if: "project_types.includes('python') && ctx_chars > 50000"
    use: python-specialist
    explain: "Large Python codebase (higher threshold for Python)"

  - id: large-js-project
    if: "project_types.includes('javascript') && ctx_chars > 40000"
    use: js-specialist
    explain: "Large JavaScript codebase"

Why this works: Different languages have different verbosity, so adjust thresholds accordingly.

Epsilon-Greedy Exploration

BobaMixer can automatically discover better profiles using exploration.

How It Works

  1. Exploitation (97%): Use the best known profile based on rules
  2. Exploration (3%): Try alternative profiles to discover better options
  3. Learning: Track performance (cost, latency, quality)
  4. Suggestions: Recommend better profiles when found

Configuration

yaml
exploration:
  enabled: true
  epsilon: 0.03          # 3% exploration rate
  min_samples: 10        # Need 10+ samples before exploring
  cooldown_hours: 24     # Wait 24h between re-testing profiles
  exclude_profiles:      # Never explore these
    - critical-only
    - production-only

Benefits

  • Automatic optimization: Finds cost-performance sweet spots
  • Adaptation: Adjusts to changing usage patterns
  • Discovery: Reveals unexpected good matches
  • No manual work: System learns over time

Viewing Exploration Results

bash
# See exploration events
boba report --format json | jq '.[] | select(.explore == true)'

# Review suggestions
boba action

# Apply a suggestion
boba action apply <suggestion-id>

Testing Routes

Always test routing rules before deploying.

Test with Text

bash
# Test inline text
boba route test "Write a function to sort an array"

# Shows: which rule matched, which profile selected, why

Test with File

bash
# Test file content
boba route test @path/to/prompt.txt

# Test multiple files
for file in test-cases/*.txt; do
  echo "Testing: $file"
  boba route test @"$file"
done

Verbose Testing

bash
# See detailed evaluation
boba route test --verbose "Your prompt here"

# Shows:
# - All rules evaluated
# - Which conditions matched/failed
# - Final selection reasoning

List All Rules

bash
# View configured rules
boba route list

# Shows rules in evaluation order

Best Practices

1. Order Matters

Rules are evaluated top-to-bottom. First match wins.

Wrong Order (generic rule first):

yaml
rules:
  - if: "ctx_chars > 0"      # Matches everything!
    use: cheap-model

  - if: "ctx_chars > 50000"  # Never reached
    use: expensive-model

Correct Order (specific rules first):

yaml
rules:
  - if: "ctx_chars > 50000"
    use: expensive-model

  - if: "ctx_chars > 0"
    use: cheap-model

2. Always Provide Explanations

yaml
# Good: Clear explanation
- id: large-context
  if: "ctx_chars > 50000"
  use: high-capacity
  explain: "Large context requires high-capacity model for quality"

# Bad: No explanation
- id: rule1
  if: "ctx_chars > 50000"
  use: profile1

Explanations help with:

  • Debugging routing issues
  • Understanding logs
  • Team collaboration

3. Use Fallbacks for Critical Paths

yaml
# Production: always have fallback
- id: production
  if: "branch.matches('main')"
  use: best-model
  fallback: good-model
  explain: "Production with fallback"

# Experimental: fallback optional
- id: experiment
  if: "branch.matches('exp')"
  use: experimental-model
  explain: "Experimental work"

4. Test Thoroughly

bash
# Create test suite
mkdir route-tests

# Add test cases
echo "Write a function" > route-tests/code-gen.txt
echo "Review this code" > route-tests/code-review.txt
echo "Format with prettier" > route-tests/format.txt

# Test all cases
for f in route-tests/*.txt; do
  boba route test @"$f"
done

5. Monitor Route Performance

bash
# Stats by profile
boba stats --by-profile --7d

# Identify which routes are used most
boba report --format json | jq 'group_by(.profile) | map({profile: .[0].profile, count: length})'

6. Enable Exploration Gradually

yaml
# Start conservative
exploration:
  enabled: true
  epsilon: 0.01  # 1% exploration

# Increase after confidence
exploration:
  enabled: true
  epsilon: 0.03  # 3% exploration

7. Document Your Strategy

yaml
# Add comments in routes.yaml
rules:
  # === PRODUCTION RULES ===
  # These handle production branch work
  # Always use high-quality models with fallbacks

  - id: prod-critical
    # ...

  # === DEVELOPMENT RULES ===
  # These handle feature branch work
  # Optimize for cost while maintaining quality

  - id: dev-work
    # ...

Common Mistakes

Mistake 1: Overly Generic Rules

Problem:

yaml
- if: "text.contains('code')"
  use: code-model

Solution:

yaml
- if: "text.matches('write.*code|implement|create.*function')"
  use: code-generation-model

- if: "text.matches('review.*code|analyze|refactor')"
  use: code-review-model

Mistake 2: No Default Rule

Problem: No rule matches, system has no fallback

Solution: Always have a catch-all at the end

yaml
- id: default
  if: "ctx_chars > 0"
  use: balanced-model
  explain: "Default for unmatched cases"

Mistake 3: Regex Errors

Problem:

yaml
# Wrong: unescaped special chars
if: "text.matches('format|prettier')"  # Correct
if: "text.matches('format\\|prettier')"  # Wrong (escaped |)

Solution: Only escape regex special chars like \b, \d, \w, etc.

Mistake 4: Circular Fallbacks

Problem:

yaml
profile-a:
  # ...
  fallback: profile-b

profile-b:
  # ...
  fallback: profile-a

Solution: Use linear fallback chains

yaml
profile-a:
  fallback: profile-b

profile-b:
  fallback: profile-c

profile-c:
  # No fallback (or different one)

Debugging Routes

Enable Verbose Logging

bash
export BOBA_LOG_LEVEL=debug
boba route test "Your test"

Check Logs

bash
tail -f ~/.boba/logs/boba.log

Verify Rule Syntax

bash
# Check YAML syntax
yamllint ~/.boba/routes.yaml

# Validate with boba
boba doctor

Test Edge Cases

bash
# Empty input
boba route test ""

# Very large input
boba route test @large-file.txt

# Special characters
boba route test "Code with 'quotes' and \"escapes\""

Integration with Other Features

With Budgets

yaml
# When near budget, use cheaper models
- id: budget-conscious
  if: "ctx_chars < 10000"
  use: economical-model
  explain: "Small task, conserve budget"

Check budget status: boba budget --status

With Analytics

bash
# Analyze routing effectiveness
boba stats --by-profile --30d

# Export for analysis
boba report --format csv --output routing-analysis.csv

With Git Hooks

Install git hooks to use routing automatically:

bash
cd your-project
boba hooks install

Next Steps

Examples Repository

For more examples, see: