Workflow:CrewAIInc CrewAI Flow Based Orchestration
| Knowledge Sources | |
|---|---|
| Domains | Multi_Agent_Systems, Event_Driven_Architecture, Workflow_Orchestration |
| Last Updated | 2026-02-11 18:00 GMT |
Overview
End-to-end process for building event-driven, stateful workflows using CrewAI Flows that orchestrate multiple Crews, conditional routing, and persistent state management.
Description
This workflow covers the production-grade approach to CrewAI: using the Flow engine to compose complex multi-step automations with precise control. Flows use Python decorators (@start, @listen, @router) to define an event-driven execution graph where methods trigger based on the completion of other methods. Each Flow maintains a typed state object (plain dict or Pydantic model) that persists across steps. Flows can embed Crew kickoffs as individual steps, enabling a hybrid architecture where autonomous agent teams operate within a controlled orchestration layer. The Flow engine supports conditional branching via @router, parallel execution through multiple @start methods, logical combinators (or_, and_), state persistence via SQLite, human-in-the-loop feedback pauses, and visualization of the execution graph.
Usage
Execute this workflow when you need fine-grained control over multi-step AI automation. Use Flows when: the process requires conditional branching based on intermediate results, multiple Crews need to be orchestrated in sequence or parallel, you need persistent state across execution steps, or the business logic includes non-AI Python code mixed with agent operations. Flows are the recommended architecture for production deployments.
Execution Steps
Step 1: State Model Design
Define the state schema for the Flow. State can be an unstructured dictionary or a typed Pydantic BaseModel. The state object persists across all Flow methods and is the primary mechanism for passing data between steps. Design the state to capture all intermediate results, configuration parameters, and control flags needed throughout the workflow.
Key considerations:
- Pydantic models provide type safety and validation
- Unstructured dicts offer flexibility for dynamic schemas
- State is accessed via self.state within Flow methods
- State can be persisted to SQLite for cross-session resumability
Step 2: Flow Class Definition
Create a class that extends Flow[StateType] where StateType is the state model. Define methods decorated with @start() for entry points, @listen(trigger) for event handlers, and @router(trigger) for conditional branching. Each method receives the output of its trigger method as an argument and can access/modify the shared state.
Key considerations:
- A Flow must have at least one @start() method
- Multiple @start() methods execute in parallel
- @listen can reference method names or string route labels
- @router methods return string labels that trigger corresponding listeners
Step 3: Crew Integration
Embed Crew.kickoff() calls within Flow methods to leverage autonomous agent teams at specific steps. Create Crew instances with agents and tasks inside the Flow method, call kickoff with appropriate inputs from the Flow state, and store the crew output back into the Flow state. This enables a hybrid architecture combining agent autonomy with workflow precision.
Key considerations:
- Crews run within the Flow method's execution context
- Crew inputs can be derived from the Flow state
- Crew outputs should be stored in the Flow state for downstream use
- Multiple Crews can run in parallel using multiple @start methods
Step 4: Conditional Routing
Implement decision points using @router decorated methods. A router method evaluates the current state and returns a string label. Downstream @listen methods that match the returned label are triggered. Use or_() to trigger when any condition matches and and_() to trigger when all conditions match. This enables branching workflows with multiple paths.
Key considerations:
- Router methods must return a string label
- Multiple listeners can match the same route label
- or_ and and_ combinators compose complex trigger conditions
- Routers enable retry loops and cyclic execution patterns
Step 5: State Persistence
Add the @persist decorator or pass a persistence argument to enable state persistence via SQLiteFlowPersistence. This saves the state after each method execution, enabling recovery from failures and cross-session resumability. For human-in-the-loop workflows, use the @human_feedback decorator to pause execution and wait for external input before resuming.
Key considerations:
- SQLiteFlowPersistence stores state in a local SQLite database
- Flow can be restored from a specific flow_id
- resume() continues execution after human feedback
- from_pending() restores a flow waiting for human input
Step 6: Execution and Visualization
Execute the Flow by calling flow.kickoff() or await flow.akickoff(). The engine traverses the execution graph, running methods in dependency order. Use flow.plot() to generate an interactive HTML visualization of the Flow graph showing all methods, edges, and routing paths. Monitor execution through the event system which emits typed events for each Flow lifecycle stage.
Key considerations:
- kickoff() blocks until all paths complete
- akickoff() is the native async variant
- The visualization shows the full execution graph as an interactive diagram
- Events track method start, completion, routing decisions, and state changes