Sprint 4 · Frameworks + MCP

Orchestration frameworks and the Model Context Protocol: building the same agent three ways

Build

Concept

Why frameworks exist — and what they cost

Once you have built an agent from scratch (Sprint 0), implemented tool use by hand (Sprint 1), designed memory stores (Sprint 2), and wired a supervisor–worker graph manually (Sprint 3), a framework starts to look attractive: it eliminates the boilerplate you have been writing by hand. But every framework is also a commitment — a vocabulary, an abstraction layer, and a set of opinions about how orchestration should work. Understanding those opinions before you pick up a framework is what makes the difference between a tool that helps you and one that constrains you.

This sprint looks at three orchestration philosophies through a concrete lens: re-implementing the same small file-analysis agent in LangGraph and CrewAI, and exposing its tools as a custom MCP server. The goal is not to find a winner — each framework optimises for something different. The goal is to make the choice legible.

LangGraph: explicit state machines

LangGraph models an agent as a directed graph. Nodes are Python callables; edges encode control flow, including conditional branching. State is a TypedDict that threads through every node — each node reads the current state and returns a partial dict that the framework merges back in. The graph is compiled once, then invoked repeatedly with different inputs.

The key property LangGraph adds beyond raw Python is durable execution via checkpointing. By passing a MemorySaver or SqliteSaver to compile(), you get an agent that can be interrupted at any node boundary and resumed from exactly that point — across process restarts, across days. This matters for long-running agentic tasks where a single runtime cannot be relied on to stay alive.

LangGraph is the right choice when orchestration logic is complex enough that explicit state transitions matter: loops that may or may not execute, conditional branches based on tool results, and the ability to pause and resume a mid-flight agent. For a simple sequential pipeline with no branching, the graph machinery is overhead that a direct function call does not incur.

CrewAI: role-based crews

CrewAI organises agents around roles and goals: each Agent carries a role string, a goal, and a backstory that frames how the underlying model reasons about its work. Agents are assigned Task objects; a Crew sequences (or hierarchically delegates) those tasks and passes outputs as context from one task to the next.

The design trades explicitness for readability. A CrewAI configuration reads like an org chart with job descriptions — useful when the agent decomposition maps naturally onto human-like roles with genuinely distinct responsibilities. The role framing adds prompt overhead per agent; when the "roles" in your system don't actually require different reasoning postures, that overhead produces no benefit over a plain function call.

CrewAI's Process.sequential is the right default for most pipelines. Process.hierarchical introduces a manager agent that delegates dynamically to workers at runtime — closer in spirit to the supervisor–worker pattern from Sprint 3, but expressed through role framing rather than explicit graph edges.

Microsoft Agent Framework (AutoGen)

Microsoft's agent infrastructure has converged on AutoGen, which unifies the earlier AutoGen conversational-agent work with Semantic Kernel's enterprise orchestration capabilities. AutoGen's design emphasis is multi-agent conversation: agents communicate through structured message exchanges, and the framework handles turn-taking, termination conditions, and integrations with enterprise tools (Azure OpenAI, Microsoft 365) out of the box.

Where LangGraph expresses orchestration as a graph and CrewAI expresses it as a crew with roles, AutoGen expresses it as a conversation between agents. The conversational metaphor makes it natural to implement negotiation, critique, and iterative refinement patterns — agents can push back on each other's outputs within a managed dialogue. The enterprise-integration focus makes it a practical choice when the target deployment is an Azure-heavy stack.

MCP: standardising the tool layer

All three frameworks above provide their own tool-definition APIs. The result, without a standard, is that a tool written for LangGraph cannot be directly consumed by CrewAI, and neither can be consumed by Claude Desktop or a custom agent framework without adaptation. The Model Context Protocol is an attempt to fix this at the protocol level.

MCP defines a uniform JSON-RPC 2.0 contract for exposing tools and resources to any MCP-aware client. A server advertises its capabilities during an initialize handshake, then responds to tools/list (return the manifest with JSON Schema input schemas) and tools/call (execute a named tool and return structured content). Because the protocol is client-agnostic, the same MCP server can be wired into LangGraph, CrewAI, Claude Desktop, AutoGen, or any other client without modification.

MCP is the right abstraction when client diversity is the constraint: you want a tool to be usable by multiple different agent frameworks or end-user clients. For a single-framework codebase with no external consumers, a plain function call is leaner — the JSON-RPC serialisation layer adds overhead that has no payoff when the caller and server are in the same process.

The Golden Rule

Never ask an LLM to do something a deterministic function can do reliably. Applied to frameworks: the framework's job is to handle orchestration boilerplate — state threading, conditional routing, turn-taking. The deterministic operations (counting lines, validating schemas, routing by keyword) still belong in code, not in a model prompt, regardless of which framework you choose. A framework is overhead; reach for one when the orchestration complexity justifies it, not by default.

Choosing a framework: the three questions

Before picking up an orchestration framework, ask three questions. First: does my orchestration have conditional branching, loops, or resumability requirements? If yes, LangGraph's explicit graph is worth its weight. Second: does my agent decomposition map naturally onto roles with genuinely different reasoning postures? If yes, CrewAI's role framing pays off. Third: do I need the same tools accessible from multiple different clients or frameworks? If yes, wrapping them in an MCP server buys you real interoperability. If the answer to all three is no, a direct function call is still the right call.

Build

What to build this sprint

The reference implementations at projects/sprint-4/ show the same file-analysis agent in three forms: a LangGraph StateGraph, a CrewAI Crew, and a stdlib-only MCP server. Read all three before building your own versions.

  1. Run the MCP server self-test. The MCP server uses only Python's standard library — no pip install required. Run it now to see the JSON-RPC handshake in action:
    bash
    $ python agentic-engineering/projects/sprint-4/mcp-server/server.py
    --- MCP server self-test ---
    
      ok: initialize returns protocolVersion
      ok: initialize returns serverInfo
      ok: initialize returns capabilities
      ok: tools/list returns list
      ok: count_lines in manifest
      ok: list_functions in manifest
      ok: each tool has inputSchema
      ok: count_lines returns lines key
      ok: count_lines line count > 0
      ok: list_functions returns functions key
      ok: list_functions found handle()
      ok: list_functions found run_stdio()
      ok: unknown tool returns JSON-RPC error
      ok: missing file returns error key
    
    All 14 checks passed.
    Confirm all 14 checks pass. Then open server.py and trace the handle() function: identify the three MCP methods it dispatches, and verify that neither tool implementation calls eval() or makes a network request.
  2. Read the LangGraph agent. Open projects/sprint-4/langgraph/agent.py. Find the three structural elements that make it a LangGraph agent: the AgentState TypedDict, the node functions (call_model, call_tool), and the conditional edge (should_continue). Draw the graph on paper: entry point, reason node, act node, terminal edge. Confirm that the loop exits when the model produces no tool calls — this is the stop condition you implemented by hand in Sprint 0, now expressed as a graph edge.
  3. Read the CrewAI agent. Open projects/sprint-4/crewai/agent.py. Find the two Agent definitions and note their roles. Find the Task definitions and the context=[analyse_task] argument on the reporter task — this is how CrewAI passes output from one task to the next. Compare this to the LangGraph version: in CrewAI, inter-task context flows through the context parameter; in LangGraph, it flows through the shared AgentState.
  4. Add a third tool to the MCP server. Add a detect_imports tool that returns the list of top-level modules imported by a Python file (use ast.Import and ast.ImportFrom nodes). Add it to TOOL_MANIFEST and TOOL_HANDLERS, write a handler that uses pathlib and ast, and add two self-test assertions that verify it works on the server file itself. Run the server again and confirm all checks still pass.
  5. Write your qualitative comparison. In projects/sprint-4/README.md, add a short paragraph (or update the table) answering: for your tool-analysis use case, which framework would you reach for if you needed (a) a resumable agent that could survive a process restart mid-task, and (b) a tool that multiple different agent frameworks needed to call? Explain the reasoning for each choice in one sentence. State no benchmark numbers — describe the trade-off qualitatively.
When you are done

You have run the MCP server self-test and all checks pass. You can trace the structure of both the LangGraph and CrewAI agents and explain what each structural element does. You have added a third tool to the MCP server and the server still passes all checks. Your README contains a short qualitative comparison — no invented numbers — explaining which framework you would pick for each scenario and why. That is the Sprint 4 ship condition.