Spaces:
Running
Running
File size: 2,890 Bytes
c07ec17 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 | ---
kind: comparison
compared: [agent/loop.py, agent/graph.py]
date: 2026-07-06
verdict: manual loop for now; LangGraph when checkpointing / parallelism / human-in-the-loop arrives
---
# Manual loop vs. LangGraph β same agent, two control flows
Both implementations drive the **identical** three tools (`search_docs`,
`read_page`, `ask_source`), the same planner prompt, the same budgets
(6/2/1), and end in the same `answer_from_sections`. Only the control flow
differs: a Python `while` loop vs. an explicit `StateGraph`.
## Numbers
| | `agent/loop.py` | `agent/graph.py` |
|---|---|---|
| Code lines (non-comment) | **90** | 98 |
| External dependency | none (stdlib) | `langgraph` |
| State | local variables in one function | a `TypedDict` threaded through nodes |
| Control flow | `for step in range(MAX_STEPS)` + `if/elif` | nodes + a conditional edge (`_route`) |
LoC is nearly identical β the graph's node signatures and explicit state
dict cost ~8 lines over plain locals. At this size the manual loop is
slightly smaller and has zero dependency.
## Debuggability
- **Manual loop**: a stack trace points at the exact line; you can drop a
`print`/breakpoint anywhere and read the local `transcript`. Nothing
between you and the code. Easiest to reason about at this scale.
- **LangGraph**: the flow is *inspectable as data* β you can render the
graph, and (with a checkpointer) replay a run node-by-node. That visibility
is worth little for a 3-node graph but grows with complexity.
## Latency
Both make the same LLM calls (one planner call per step + one final
generation), so wall-clock is dominated by the network, not the framework.
LangGraph's per-node overhead is microseconds β immeasurable next to a
free-tier LLM call that can wait 30s on a rate limit. **No practical
difference.**
## When LangGraph earns its dependency
Nothing in *this* agent needs a graph β which is exactly why the manual loop
is the default. LangGraph becomes the right tool the moment we add any of:
- **Checkpointing** β pause a run and resume after a restart (multi-turn
sessions, long jobs). The manual loop would have to serialize its locals
by hand; LangGraph gives it for free.
- **Human-in-the-loop** β interrupt before an action (e.g. approve running
code) and continue. A native graph feature; a manual bolt-on otherwise.
- **Parallel fan-out** β run several `search_docs` queries concurrently for a
recipe question. Natural as parallel edges; awkward in a linear loop.
## Verdict
Ship the **manual loop** (`agent/loop.py`): fewer lines, no dependency,
trivially debuggable, same behavior. Keep `agent/graph.py` as the drop-in
upgrade β identical tools and prompt β for when checkpointed sessions,
approval steps, or parallel retrieval arrive. Building it twice proved the
control flow is understood, not delegated to a framework on faith.
|