OpenAI Agents, LangChain, and More
The moment you decide to build a real agent, you face a decision you cannot postpone: which framework do you build it on? The space moves fast, and every option is loudly marketed. This article is a grounded tour of the frameworks people use to build production-grade agents — the OpenAI Agents SDK, LangChain and LangGraph, plus a few serious challengers — and, more importantly, how to choose among them without being swayed by hype. The honest truth is that the framework matters far less than the loop you are wrapping, but the differences that do exist can save you weeks of pain or hand you a box of sharp-edged abstractions.
A Quick Map of the Landscape
Before comparing, let us get the geography straight. The frameworks fall into three broad camps. The model-first camp centers agent capabilities in the model and its native tool calling, with the framework staying thin around it. The orchestration camp supplies graph-based control flow, memory, and state management. And the full-stack platform camp adds hosting, observability, and evaluation on top. Knowing which camp a framework lives in tells you more than any feature list, because it tells you where the design's center of gravity sits — and where you will be spending your effort.
"Pick a framework for its default discipline, not its demo reel. The demo shows you the happy path. The defaults show you what will happen when it goes wrong."
OpenAI Agents SDK: Thin, Model-First, Fast to Production
OpenAI's Agents SDK is a good example of the model-first camp, and it reflects a sensible philosophy: the loop is simple, the model is powerful, and the framework should get out of the way. It centers on Agent objects that hold system instructions and a list of tools, and it supports handoffs between agents, which is a lightweight way to get multi-agent behavior without building a whole orchestration graph. Because it leans on the model's native function calling, the amount of bespoke code you write is small.
from agents import Agent, Runner, function_tool
@function_tool
def fetch_balance(account_id: str) -> dict:
return {"balance": api.get_balance(account_id)}
agent = Agent(
name="Teller",
instructions="Check balances and answer account questions. Never move money.",
tools=[fetch_balance],
)
result = Runner.run_sync(agent, "what's the balance on acct-442?")
print(result.final_output)
The strengths here are speed and clarity: the mental model maps directly to the three-phase loop you build by hand, so debugging is straightforward and the library is light. The trade-offs are real. Because it is thin, heavier capabilities like complex branching and long-lived state are things you assemble rather than things the framework hands you. Dependency on one vendor's model tool-calling conventions is a consideration if you want to move between providers freely.
LangChain and LangGraph: Orchestration as a First-Class Citizen
LangChain grew into an ecosystem and a famously deep stack of abstractions for connecting models to tools and data. LangGraph is its orchestration layer, built to model agents as explicit graphs of nodes and edges with a shared state object. This is the correct tool when your agent is genuinely a workflow — multiple stages, branching decisions, human checkpoints, and a state that must persist reliably across them.
from langgraph.graph import StateGraph, END
builder = StateGraph(AgentState)
builder.add_node("triage", triage_node)
builder.add_node("research", research_node)
builder.add_node("review", review_node)
builder.add_edge("triage", "research")
builder.add_conditional_edges("research", route_to_review_or_end)
builder.add_edge("review", END)
app = builder.compile()
The payoff is control and durability. LangGraph's explicit state and checkpointing make multi-step, long-running agents tractable, and its human-in-the-loop interrupts let you halt the graph at a node for approval. The price is complexity: there is a real learning curve, and it is easy to build a graph whose behavior no single person fully holds in their head. Teams that pick LangGraph because they actually need durable multi-step orchestration love it. Teams that pick it because it is the famous name spend a lot of time fighting abstractions they did not need.
The Serious Also-Rans Worth Knowing
Beyond the two headliners, several frameworks earn genuine respect in production. Langroid offers a pragmatic, multi-agent take with clean retry and error handling. Pydantic AI is beloved by anyone who wants type-safe agent definitions and structured outputs, because it leans on Pydantic for every boundary. CrewAI focuses on role-based crews. And Smolagents, from Hugging Face, takes the intriguing stance of writing tool calls directly as executable Python rather than JSON.
- Pydantic AI: choose it when schema safety and structured I/O are your top pain points.
- Langroid: choose it when you want multi-agent coordination without a heavyweight graph.
- Smolagents: choose it when your tool calls are genuinely code-shaped and you trust the model to write them.
- Platform DSLs: from any vendor, choose when you need hosted evaluation and monitoring baked in from day one.
Notice the theme: no framework is the "best." Each one is the best at a particular tension your project has. The job is to name your tension before you shop.
How to Actually Choose
Here is a practical decision procedure, and it is deliberately boring. Start by drawing your agent as a loop on paper and marking which parts are genuinely hard: long state? many steps? branching? human approval? structured output? Then map those parts to camps. If nothing is especially hard, pick the thinnest option — the model-first camp — because you can always add abstraction later, and you cannot remove it easily once you have built your whole system on it.
All frameworks converge. Pick the one whose failure modes you are readiest to debug, because that is where you will spend your weekends.
If you need durable multi-step orchestration and checkpoints, that is a graph problem, so LangGraph or a platform with similar semantics earns its place. If you need strict typed contracts with external systems, Pydantic AI's guarantees pay for themselves. And evaluate a framework the way you evaluate any dependency: read its defaults, its failure modes, its escape hatches. A framework with a clean escape hatch — the ability to step down to raw tool calls and plain prompts — is one you can unwind out of later. A framework that forces you through its abstractions for even trivial things will trap you.
The Bottom Line
The framework war is mostly theater. What actually determines whether your agent works is the discipline of your loop: how you perceive, how you constrain actions, how you handle state, and how you evaluate changes. The framework you choose is a way of expressing that discipline, and the honest differences are practical ones — how much control you hold, how much boilerplate you write, and how gracefully you can evolve. Build your first agent by hand so you understand the loop, then adopt a framework because it removes a specific pain, not because it is famous. Choose for your defaults, debug the failure modes you can handle, and keep an escape hatch.


