Exercise 1: Same Agent, Two Frameworks (LangGraph + CrewAI)
Pairs with Stage 4 — Agent Frameworks Exercise 1.
🎓 How to use this:
starter.pyis the complete solution, not a TODO skeleton. The active approach works better —mv starter.py starter_reference.py, read the signatures but not the bodies, write your ownstarter.pyfrom scratch, then runpython test.pyto check it; if you are stuck for 20 minutes, go back and compare against the reference. Full methodology indocs/HOW_TO_USE.md.
📚 Want the chapter-length version? The starter in this folder is an illustrative build focused on the core pattern plus two SDK paths — it is not in-depth teaching material. Recommended for depth:
datawhalechina/hello-agents⭐ the most complete Chinese-language course out there — chapter by chapter, plus 16 production capabilities. This exercise maps to hello-agents' framework comparison / orchestration chapter- LangGraph Quickstart + CrewAI official docs
- Full references in Stage 4 Curated Projects
#Task
A minimal search + summarize agent:
- Given a query (e.g. "summarize Taipei")
- Agent uses a
searchtool to hit a knowledge base - LLM summarizes the result in 1-2 sentences
Built once in LangGraph and once in CrewAI — compare styles.
#How to run — two paths + two frameworks
#Path A (default, free, local)
pip install -r requirements.txt
ollama pull qwen2.5:3b
ollama serve
python starter.py # LangGraph + Ollama
python starter_crewai.py # CrewAI + Ollama (comparison)
Budget: $0.
#Path B (Anthropic, cloud-quality)
pip install -r requirements.txt
export ANTHROPIC_API_KEY=sk-ant-...
python starter_anthropic.py # LangGraph + Claude
Budget: ~$0.001 per run (claude-haiku-4-5).
#Validate the logic (mock-based)
python test.py # LangGraph + mock LLM
python test_anthropic.py # starter_anthropic loads + ChatAnthropic constructs
python test_crewai.py # CrewAI tool + module loads
#Side-by-side framework comparison
| Dimension | LangGraph | CrewAI |
|---|---|---|
| Core abstraction | StateGraph + node + edge | Agent + Task + Crew |
| Mental model | "How does state flow?" | "Who plays what role?" |
| Loop control | Explicit conditional edges | Hidden inside Crew.kickoff() |
| Lines of code (this task) | ~50 | ~25 |
| Debug path | Inspect graph state, time-travel | Verbose logs, hard to step |
| Best for | Complex branching, production, audit | Multi-agent prototypes, role-based tasks |
| Learning curve | Medium-high | Low |
#LangGraph style (condensed)
g = StateGraph(State)
g.add_node("agent", agent_node)
g.add_node("tools", tool_node)
g.add_conditional_edges("agent", should_continue, {"tools": "tools", END: END})
g.add_edge("tools", "agent")
"I tell the system explicitly: state shape, nodes, edges, branching via should_continue."
#CrewAI style (condensed)
researcher = Agent(role="Researcher", goal="...", tools=[search], llm=MODEL)
task = Task(description=query, expected_output="...", agent=researcher)
crew = Crew(agents=[researcher], tasks=[task])
crew.kickoff()
"I describe: who plays this role, what task, what tools. Framework decides how to run."
#What to observe
- Abstraction cost: CrewAI hides more, writes less code; but stack depth grows when debugging
- Small-model friendliness: LangGraph is more stable with qwen2.5:3b; CrewAI's denser prompts can confuse small models
- Controllability: LangGraph exposes state transitions; CrewAI is "result-oriented"
- When to pick: production / audit → LangGraph. Multi-agent prototypes / role-based → CrewAI
#Common pitfalls
- LangGraph
bind_tools: mustllm.bind_tools([search])to expose tool schema. Without it the model doesn't know the tool exists - CrewAI model spec: needs LiteLLM format (
"ollama/qwen2.5:3b", not"qwen2.5:3b"). Misspell and framework silently falls back to OpenAI default - CrewAI return type:
crew.kickoff()returns aCrewOutputobject;str(result)to get text. Bareprint(result)may show repr
#Want smarter answers?
MODEL=claude-sonnet-5 python starter_anthropic.py # more stable
MODEL=qwen2.5:7b python starter.py # larger local model
#Extensions
- Streaming: LangGraph
graph.stream(...), CrewAIcrew.kickoff(stream=True) - Checkpointing: LangGraph +
MemorySaverfor time-travel debug - Human-in-the-loop: see Exercise 3