Frameworks
Pick a framework, or pick a loop
Most agent frameworks are a while-loop with opinions. Here is how to tell whether you need the opinions, and what you give up when you take them.
- Published
- 30 Jun 2026
- Reading
- 8 min
- Class
- frameworks
half-life 120dfrom 30 Jun 2026
Every few months someone writes the post arguing you don't need an agent framework, and every few months someone writes the rebuttal. Both are right about different projects, which is why the argument never resolves. The useful question isn't whether frameworks are good — it's which specific problem you're outsourcing.
What you're actually buying
Strip the marketing and agent frameworks sell some subset of five things:
- Provider abstraction — one interface across model vendors.
- Control flow — graphs, state machines, handoffs between agents.
- Durability — checkpointing, resuming, surviving a restart.
- Typed boundaries — validated structured output and tool arguments.
- Observability — traces, replay, a UI for looking at runs.
Notice what isn't on that list: making the model better at the task. No framework does that. The quality of your agent comes from your tools, your context and your evals, and a framework is neutral on all three. If your agent is underperforming, switching frameworks is almost never the fix — which is worth knowing before you spend a fortnight on the migration.
The honest case for writing the loop
For a single-agent system with a handful of tools and a human in the loop, the raw SDK is genuinely less code than the framework wrapper — and every layer you remove is a layer you don't have to reason about when something goes wrong at 2am.
messages = [user_turn]
while True:
reply = model.create(messages=messages, tools=tools)
messages.append(reply)
calls = [b for b in reply.content if b.type == "tool_use"]
if not calls:
return reply
messages.append(run_tools(calls))
That's the whole pattern. What a framework adds on top of it is the retry policy, the checkpoint, the token accounting and the trace — real work, but work you can also see and control. Teams that write this themselves tend to understand their systems better, and the understanding pays off every time behaviour surprises them.
The failure mode to watch for: you write the loop, then over eight months you rebuild a worse framework inside your application, without documentation or tests. That's a real cost, and it's the strongest argument on the other side.
The honest case for the framework
Three situations where a framework stops being overhead and starts being leverage:
The control flow is genuinely a graph
Not "the agent calls tools in a loop" but: a research step fans out to five parallel workers, results merge, a critic node routes back to research or forward to drafting, and a human approves before publish. That's a real state machine, and expressing it as nested conditionals in a loop gets ugly fast. This is what LangGraph is for, and when the shape fits, it fits well.
Runs are long and must survive restarts
If a run takes an hour, a deploy in the middle of it must not destroy the work. You need durable state: checkpoint after each step, resume from the last one, make steps idempotent. Building that correctly is a project. Frameworks that offer it — or durable-execution engines like Temporal underneath your own loop — are earning their place.
Typed boundaries across a large team
When ten engineers add tools to the same agent, a typed contract for tool arguments and outputs stops a category of bug at the boundary rather than in production. Pydantic AI and similar exist for this and are pleasant if your codebase already thinks in schemas.
Load-bearing
Adopt a framework for a constraint you can name — durability, a graph-shaped control flow, a team-scale contract. Adopting one because it's what people use is how you end up debugging someone else's abstraction to find out why your tool call didn't fire.
Questions worth asking before you commit
- Can I see the exact request being sent? If the framework won't show you the assembled prompt, you cannot debug context problems, and context problems are most of them.
- What happens when the model returns something unexpected? Does it raise, retry, or hand the error back to the model? All three are defensible; not knowing which is not.
- How do I get out? If the abstraction stops fitting in month six, what does the exit cost? Frameworks that stay close to the underlying message format are cheap to leave. Ones with their own conversation representation are not.
- Who maintains it, and at what pace? This layer moves fast. A framework that lagged the last two model releases will lag the next one.
A reasonable default
Start with the raw SDK and write the loop. You'll understand the system, and for a lot of products you will never need more. Add a framework at the first named constraint — the day you need durable resumption, or the day the control flow stops being a loop. Adopt it for that specific thing, keep your tools and context assembly framework-agnostic, and you'll retain the option to change your mind.
The loop is forty lines. The judgement about when forty lines stops being enough is the actual skill.