DS DevShelfHub Projects · AI tools
Tutorials / CrewAI / Reference / Decorators / @router
Decorator crewai.flow.flow

@router: Reference Guide

By DevShelfHub

Routes Flow execution to different downstream listeners based on the decorated method's return value.

See the CrewAI API reference index, CrewAI introduction, hooks and events tutorial, and core concepts for surrounding context.

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

python
from crewai.flow.flow import router

How to Apply

python
@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

python
@router(review)
def route(self):
    return 'approved' if self.state.score > 0.7 else 'rejected'

Multi-way routing with enums

python
@router(classify)
def triage(self, label):
    return {
        'billing': 'finance_queue',
        'bug': 'engineering_queue',
        'other': 'general_queue',
    }.get(label, 'general_queue')

Listeners on router tags

python
@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.