CrewAI Tutorial (Python): building conditional routing for advanced developers
This tutorial shows you how to build a CrewAI workflow that routes tasks conditionally based on agent output, so you can branch into different execution paths instead of running a fixed linear chain. You need this when the next step depends on what the previous agent found, which is common in support triage, claims handling, fraud review, and escalation workflows.
What You'll Need
- •Python 3.10+
- •
crewai - •
crewai-tools - •An OpenAI API key set as
OPENAI_API_KEY - •Basic familiarity with CrewAI agents, tasks, and crews
- •A terminal and a virtual environment
Install the packages:
pip install crewai crewai-tools
Set your API key:
export OPENAI_API_KEY="your-key-here"
Step-by-Step
- •Start by defining two agents: one to classify the input and one to handle the routed follow-up. The first agent will decide whether the request is simple or needs escalation.
from crewai import Agent
triage_agent = Agent(
role="Triage Analyst",
goal="Classify incoming requests as simple or escalated",
backstory="You review customer issues and determine routing.",
verbose=True,
)
specialist_agent = Agent(
role="Specialist",
goal="Handle escalated requests with detailed analysis",
backstory="You resolve complex cases that need deeper investigation.",
verbose=True,
)
- •Create a task that asks for a strict routing label. Keep the output constrained so your Python code can reliably branch on it.
from crewai import Task
triage_task = Task(
description=(
"Review the user's request and return exactly one word: "
"'simple' if it can be answered directly, or 'escalate' if it needs specialist handling."
),
expected_output="One word: simple or escalate",
agent=triage_agent,
)
- •Run the triage task first, then use plain Python conditionals to route the rest of the flow. This is the important part: CrewAI handles agent execution, while your application owns control flow.
from crewai import Crew, Process
crew = Crew(
agents=[triage_agent],
tasks=[triage_task],
process=Process.sequential,
verbose=True,
)
user_request = "A customer says their policy was canceled after payment."
result = crew.kickoff(inputs={"request": user_request})
route = str(result).strip().lower()
print("Route:", route)
if route == "simple":
print("Handle directly in app logic.")
else:
print("Send to specialist path.")
- •Build a second task for the escalation path and execute it only when routing says to do so. This keeps expensive specialist work off the critical path for low-complexity cases.
specialist_task = Task(
description=(
"Analyze this escalated case and provide a concise action plan: "
"{request}"
),
expected_output="A short action plan with next steps.",
agent=specialist_agent,
)
if route == "escalate":
escalation_crew = Crew(
agents=[specialist_agent],
tasks=[specialist_task],
process=Process.sequential,
verbose=True,
)
escalation_result = escalation_crew.kickoff(inputs={"request": user_request})
print("\nEscalation result:\n", escalation_result)
- •If you want stronger control, validate the router output before branching. In production, never trust an LLM response without normalization and fallback logic.
def normalize_route(text: str) -> str:
value = text.strip().lower()
if "simple" in value:
return "simple"
if "escalate" in value:
return "escalate"
return "unknown"
route = normalize_route(str(result))
if route == "unknown":
print("Fallback: send to manual review queue.")
elif route == "simple":
print("Fallback: auto-handle.")
else:
print("Fallback: run specialist workflow.")
Testing It
Run the script with two different inputs: one trivial request and one ambiguous or high-risk request. You should see the triage output change between simple and escalate, then confirm only the matching branch executes.
If both branches run every time, your Python conditionals are wrong. If the model returns extra text instead of a clean label, tighten the task wording and keep expected_output strict.
For production testing, log three things: raw LLM output, normalized route, and final branch taken. That gives you enough signal to debug bad routing without guessing.
Next Steps
- •Add structured outputs with Pydantic so routing decisions are machine-safe.
- •Replace single-step routing with multi-stage branching for risk scoring and human review.
- •Add tool usage in each branch so specialized agents can query internal systems before responding.
Keep learning
- •The complete AI Agents Roadmap — my full 8-step breakdown
- •Free: The AI Agent Starter Kit — PDF checklist + starter code
- •Work with me — I build AI for banks and insurance companies
By Cyprian Aarons, AI Consultant at Topiax.
Want the complete 8-step roadmap?
Grab the free AI Agent Starter Kit — architecture templates, compliance checklists, and a 7-email deep-dive course.
Get the Starter Kit