Build real AI agents
Framework packaging
Port your hand-rolled agent to LangGraph or smolagents or CrewAI
Learning objectives
- Port your hand-rolled agent to LangGraph or smolagents or CrewAI
- Keep evals green after the port
- [object Object]
Frameworks second: wrap what you already understand
LangGraph, smolagents, CrewAI, and peers encode graph nodes, checkpointing, tool routing, and parallelism — patterns you hand-rolled across lessons 7.1–7.6. Porting to a framework should reduce boilerplate, not replace mental models. This lesson migrates your agent, keeps trajectory/eval behavior equivalent, and closes Milestone 7: a production-shaped single agent with README, tests, and honest limits.
Callout — port behavior, not line count: If framework version skips HITL gates you built, you regressed — feature parity checklist first.
Why port at all
Hand-rolled loops teach; frameworks add:
- Persistent checkpoints — built-in pause/resume (HITL)
- Graph visualization — debug complex branching
- Community patterns — map-reduce, subgraphs (multi-agent preview)
- Maintained adapters — tool schema drift handled upstream
Stay hand-rolled if task is one loop file and team knows it cold — port when complexity or handoff cost rises.
Choosing a framework (course options)
| Framework | Strength | Port note |
|---|---|---|
| LangGraph | Explicit state graph, checkpoint SQLite | Verbose; industry common |
| smolagents | Lightweight HF ecosystem | Good for tool-heavy scripts |
| CrewAI | Role-based agents | Mind role overhead for single agent |
Pick one aligned with your portfolio target; depth beats sampling three shallowly.
Port mapping cheat sheet
| Hand-rolled | LangGraph-ish |
|---|---|
| messages state | StateGraph channel |
| tool executor node | @tool + ToolNode |
| stop / max_steps | conditional edge + recursion limit |
| HITL checkpoint | interrupt_before + checkpointer |
| trajectory log | callbacks or wrap nodes |
Document 1:1 mapping in PORT.md before coding — surprises surface in design review.
Feature parity checklist
Before declaring port done, verify:
- Same tool schemas and validation
- max_steps / timeout enforced
- Mutating tools gated (HITL) if implemented
- Memory injection if lesson 7.4 completed
- Trajectory or trace export still available
- Regression fixtures from 7.6 still pass
Run same task suite as lesson 7.3 comparison; scores within agreed tolerance.
Evals green after port
Framework internals differ; external behavior must match:
uv run pytest m7/tests/
uv run python m7/eval/run_tasks.py --agent frameworkCompare predictions.jsonl to hand-rolled baseline — flag new failures even if "mostly works."
Log framework version pin in requirements.txt — upgrades break graphs silently.
Callout — do not delete hand-rolled code immediately: Keep
react_min/as reference until framework port stable for two weeks of local dev.
Production-shaped packaging
Milestone folder layout:
m7/agent/
hand_rolled/ # reference implementation
framework/ # ported graph
tools/ # shared registry
memory/ # optional SQLite
eval/
README.md # architecture, run commands, parity notes
Dockerfile # optionalREADME sections:
- Problem domain and tools
- How to run CLI demo
- HITL instructions
- Eval results summary
- Known failures / next steps (skills module preview)
LangGraph port sketch (example)
Conceptual nodes for ticket agent:
# illustrative — adapt to installed LangGraph version
builder = StateGraph(AgentState)
builder.add_node("agent", call_model)
builder.add_node("tools", ToolNode(tools))
builder.add_conditional_edges("agent", should_continue)
builder.add_edge("tools", "agent")
graph = builder.compile(checkpointer=sqlite_checkpointer)Map your HITL gate to interrupt_before=["tools"] when pending call is mutating — exact API varies; read current LangGraph docs for interrupt patterns.
Packaging for handoff
Add pyproject.toml entry point:
[project.scripts]
shipai-agent = "m7.agent.framework.cli:main"Reviewer runs uv run shipai-agent "Refund order 8812" — professional polish for portfolio README.
Eval parity tolerance
Define acceptable drift after port:
- Task success rate within ±5% of hand-rolled
- No new HITL bypass failures on mutating tools
- Trajectory step count within ±2 median on fixed suite
If framework version fails parity, document known gap in PORT.md with issue link — honesty beats greenwashing evals.
Choosing framework for your capstone
If capstone later needs multi-agent graphs, LangGraph port now pays forward. If capstone stays single-agent with heavy custom tools, smolagents may stay out of your way. Document choice in one paragraph — future you remembers why.
Dependency pinning
Framework port requires locking versions:
langgraph==0.2.x
langchain-core==0.3.xUnpinned upgrades broke graph APIs in past course cohorts — pin and note upgrade procedure in PORT.md.
Common port pitfalls
- Hidden default prompts in framework — diff against your system.md
- Tool validation skipped by magic decorators — keep Pydantic layer
- Checkpoint format opaque — export JSONL each run for course grading
- Async/event loop conflicts in Jupyter — run CLI entrypoint
Milestone 7 closure
Reviewer can:
- Run framework agent on demo task with tool + memory + optional HITL
- See trajectory or trace output
- Run eval script with documented pass rate
- Read PORT.md explaining equivalence to hand-rolled
Single agent scope — multi-agent orchestration comes in workflows module.
Engineering problem (staff framing)
Frameworks compress boilerplate after you understand the loop. Package your agent like a library with tests.
Diagram — Hand-roll → framework
flowchart LR
HR[Hand-rolled loop] --> Tests
Tests --> FW[LangGraph/etc]
FW --> Same[Same evals]
Precise definitions & mental model
Graph state machines, dependency injection for tools, portable evals.
Tradeoffs — when to use what
Framework speed vs lock-in and opaque control flow.
Failure modes (interview + on-call)
Starting with framework magic; evals tied to vendor APIs.
Production & OSS practices
Keep driver interface thin; CI on hand-rolled + framework backends.
Deep dive (FAANG / OSS bar)
Push «framework-packaging» past tutorial depth: write the interface contract (inputs/outputs/invariants), list three measurable metrics, and name two degrade modes if the happy path fails. Add a short threat note: what an attacker or noisy tool result could do, and which layer catches it (schema, policy, HITL, or eval gate).
flowchart LR
Contract[Interface contract] --> Metrics
Metrics --> Degrade[Degrade modes]
Degrade --> Threat[Threat + control]
Micro-project: Port to a framework
In m7/agent/framework/:
- Port hand-rolled agent to chosen framework with shared tools.
PORT.mdmapping + parity checklist completed.- Re-run regression fixtures and task eval; commit results.
- Update milestone README — this closes the agents module.
Checklist
- Framework port runs end-to-end demo
- Parity checklist signed off
- Hand-rolled reference preserved
- Milestone 7 README complete
ShipAI delivery model is: