What is @router?
@router decorates a Flow method that inspects upstream results or Flow state and returns a short string tag. Listeners register with @listen using that exact tag, so only the matching branch executes. This is CrewAI's structured alternative to deeply nested if statements spread across unrelated functions — the graph encodes control flow while Python bodies stay small and testable.
Router outputs should be stable enumerations: think approval states, severity bands, or product-line codes. Dynamic tags that include raw user text invite accidental injection into listener routing tables and complicate observability. Normalize external inputs to canonical tags inside the router method, then emit the normalized token downstream.
Routers compose cleanly with fan-in listeners: a prior and_() stage can finish analytics, then a router chooses fulfillment versus escalation paths. Document each tag in team runbooks so new listeners do not collide or miss default fallbacks when you add categories over time.
When to Use
Branching to different next steps based on state.
Use Cases
- • Approval branching
- • Ticket-type routing
- • A/B paths in a pipeline
Key Features
- ✓ Returns a string tag
- ✓ Multiple downstream listeners can match
- ✓ Composable with @listen
When NOT to Use
Pure sequencing — use @listen.
Notes
Tag consistency
Listeners match string equality. Use constants or Enum values coerced to str centrally so refactors do not silently orphan branches.
Default paths
Always decide what happens when inputs are ambiguous. Returning None or empty strings often means no branch fires; prefer an explicit 'fallback' tag with a listener that raises or alerts.
Human-in-the-loop interplay
Routers after @human_feedback should assume delayed decisions. Keep router inputs on persisted state so resume semantics stay coherent when reviewers answer hours later.
Observability
Emit structured logs with the tag, upstream method name, and correlation IDs. Routers are control-plane code — when they misfire, you need enough context to replay the decision offline.
Import
from crewai.flow.flow import router
How to Apply
@router(prev_step)
def pick(self):
return 'path_a' if self.state.kind == 'a' else 'path_b'
What It Enables
- ✓ Branching
- ✓ Conditional dispatch
Code Examples
Approve/deny
@router(review)
def route(self):
return 'approved' if self.state.score > 0.7 else 'rejected'
Multi-way routing with enums
@router(classify)
def triage(self, label):
return {
'billing': 'finance_queue',
'bug': 'engineering_queue',
'other': 'general_queue',
}.get(label, 'general_queue')
Listeners on router tags
@router(review)
def decision(self):
return 'publish' if self.state.ok else 'rewrite'
@listen('publish')
def ship(self):
return 'sent'
@listen('rewrite')
def revise(self):
return 'retry'
Integration Patterns
@listen('approved') / @listen('rejected') downstream
Common Mistakes
❌ Returning non-string tags
✅ Return a hashable string consistent with downstream @listen labels.
Related: Task class reference, Agent class reference, and the first Crew tutorial.
@router FAQ
What is @router in CrewAI?
Routes Flow execution to different downstream listeners based on the decorated method's return value. @router decorates a Flow method that inspects upstream results or Flow state and returns a short string tag. Listeners register with @listen using that exact tag, so only the matching branch executes. This is CrewAI's structured alternative to deeply nested if statements spread across unrelated functions — the graph encodes control flow while Python bodies stay small and testable. Router outputs should be stable enumerations: think approval states, severity bands, or product…
Which module defines the CrewAI decorator @router?
DevShelfHub maps @router to Python module crewai.flow.flow. Pin your installed crewai version and match imports to the import snippet on this page.
When should I use @router?
Branching to different next steps based on state.
When should I avoid @router?
Pure sequencing — use @listen.
How do I apply @router in Python?
@router(prev_step) def pick(self): return 'path_a' if self.state.kind == 'a' else 'path_b'
Where can I explore more CrewAI API reference pages?
Open the CrewAI API reference index on DevShelfHub to search classes, methods, and decorators, each with runnable examples, parameters, common mistakes, and cross-links.