Build real AI agents

Framework packaging

Port your hand-rolled agent to LangGraph or smolagents or CrewAI

65 min7/7 in module

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 framework

Compare 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       # optional

README 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.x

Unpinned 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:

  1. Run framework agent on demo task with tool + memory + optional HITL
  2. See trajectory or trace output
  3. Run eval script with documented pass rate
  4. 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/:

  1. Port hand-rolled agent to chosen framework with shared tools.
  2. PORT.md mapping + parity checklist completed.
  3. Re-run regression fixtures and task eval; commit results.
  4. 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
Project checklist0/3 done

ShipAI delivery model is: