What is Flow?
Flow is CrewAI's graph-native orchestration layer: you subclass Flow[State], declare a typed Pydantic (or dict-shaped) state object, then wire methods together with @start for entry points, @listen(previous) for dataflow edges, @router for multi-way branching, and @persist when checkpoints must survive process restarts. Unlike a sequential Crew where the task list is static, Flow expresses conditional paths, human approvals, and nested kicks explicitly in Python — which is why production systems with SLAs, retries, and audit trails tend to migrate control-heavy logic here while still embedding Crews for multi-agent segments.
Execution semantics reward disciplined state mutation: CrewAI expects you to update fields on the existing state instance rather than rebinding self.state to a new object, because listeners and persistence hooks retain references to the original structure. Flow also integrates first-class streaming, kickoff_async variants, and plot() for visualizing the decorator graph when onboarding teammates.
Pick Flow when branching, side effects, or long waits dominate; pick Crew when a mostly-linear pipeline of roles is enough and you want the planner to stay inside the Task abstraction.
When to Use
Production workflows, anything with branching, retries, or HITL.
Use Cases
- • Content factories
- • Approval workflows
- • Customer journeys
- • ETL pipelines
Key Features
- ✓ Decorator-driven control flow
- ✓ Typed Pydantic state
- ✓ Persistence
- ✓ Streaming
- ✓ Plot
When NOT to Use
A one-shot two-agent demo — a Crew is enough.
Notes
State reassignment breaks listeners
Replacing self.state with a brand-new object loses in-place mutations that downstream @listen handlers already captured. Update attributes on the live instance instead.
@listen fan-in ordering
When multiple methods converge with and_/or_ helpers, document which branch owns error handling. Silent exceptions in one listener strand can stall the whole graph.
Human feedback needs persistence
Flows that pause for @human_feedback should pair with @persist so the process can exit safely and resume when the provider returns a decision.
plot() is documentation, not a debugger
Generated HTML reflects decorator wiring, not runtime data. Use it during design reviews; rely on structured logs for production incidents.
Import
from crewai.flow.flow import Flow
Key Parameters
| Parameter | Type | Default | Purpose |
|---|---|---|---|
| initial_state | BaseModel | dict | None | None | Seed state; if None, an empty default is used. |
| stream | bool | False | Emit streaming chunks during execution. |
Code Examples
Linear @start → @listen chain
from crewai.flow.flow import Flow, listen, start
class MyFlow(Flow):
@start()
def begin(self):
return 'go'
@listen(begin)
def step(self, prev):
return prev.upper()
Embed a Crew kickoff inside a Flow method
from crewai import Crew
from crewai.flow.flow import Flow, start
class Hybrid(Flow):
@start()
def run_crew(self):
crew = Crew(agents=self.state.agents, tasks=self.state.tasks, verbose=True)
return crew.kickoff(inputs=self.state.inputs)
Persisted flow skeleton
from crewai.flow.flow import Flow, start
from crewai.state.checkpoint_config import CheckpointConfig, persist
from crewai.state import SqliteProvider
@persist(config=CheckpointConfig(storage=SqliteProvider()))
class LongJob(Flow):
@start()
def kickoff(self):
return 'checkpointed'
Common Mistakes
❌ Mutating state by reassignment (`self.state = new_obj`)
✅ Mutate in place to preserve references.
Flow FAQ
What is Flow in CrewAI?
Event-driven orchestrator built on @start/@listen/@router with typed state and persistence. Flow is CrewAI's graph-native orchestration layer: you subclass Flow[State], declare a typed Pydantic (or dict-shaped) state object, then wire methods together with @start for entry points, @listen(previous) for dataflow edges, @router for multi-way branching, and @persist when checkpoints must survive process restarts. Unlike a sequential Crew where the task list is static, Flow expresses conditional paths, human approvals, and nested kicks explicitly in Python — which is wh…
Which package defines the CrewAI class Flow?
DevShelfHub maps Flow to Python module crewai.flow.flow (package path crewai.flow.flow in this reference). Pin your installed crewai version and match imports to the snippet on this page.
When should I use Flow?
Production workflows, anything with branching, retries, or HITL.
When should I avoid using Flow?
A one-shot two-agent demo — a Crew is enough.
How do I import Flow in Python?
from crewai.flow.flow import Flow
Where can I explore more CrewAI API reference pages?
Open the CrewAI API reference index on DevShelfHub to search 58 classes, 30 methods, and 16 decorators, each with runnable examples, parameters, common mistakes, and cross-links.