LangChain & LangGraph Best Practices
Ten practices for structuring graphs, state, and checkpoints so LangGraph agents stay debuggable, resumable, and safe under real traffic.
Use this checklist when you leave the tutorial graph and before you expose tools with side effects.
How to Use This Checklist
- Work top to bottom; topology and state before streaming polish.
- Tick items that are true in production, not only in a notebook.
- Re-run after adding tools, HITL, or a new subgraph.
- Pair each unchecked item with an owner and a date.
A - Graph and State Design
- 1. One concern per node. Plan, retrieve, tool, approve, and format as separate nodes so traces, timeouts, and HITL gates have clear attachment points.
- 2. Type state and choose reducers deliberately. Use
TypedDict/Pydantic; attachadd_messagesor other reducers only where merge semantics are required; keep secrets out of checkpointed fields. - 3. Encode policy in edges, not only prompts. Conditional routers enforce allowlisted paths (escalate, tools, end); never trust free-form model text as a raw goto target without validation.
B - Durability and Control
- 4. Checkpointer + thread_id on every long-lived run. Durable backend for multi-worker prod;
InMemorySaveronly for local demos. - 5. Gate irreversible work with
interrupt(). Side effects after resume; idempotent code before interrupt; never bare-except around interrupt control flow. - 6. Bound every loop. Max steps, recursion limits, per-node timeouts (async, LangGraph 1.2+), and dollar/token budgets stop runaway agents.
C - Runtime Quality
- 7. Stream with an explicit version contract. Prefer
version="v2"stream parts for UIs; test consumers against multi-mode and subgraphnsfields. - 8. Trace node paths in LangSmith (or equivalent). Enable tracing in all environments that matter; wrap non-LangChain I/O; tag releases and tenants.
- 9. Retry transient I/O, not logic bugs.
RetryPolicyon tool/model nodes; route permanent failures to error handlers or escalate branches.
D - Evolution
- 10. Version graphs like code. Pin LangGraph; review state schema migrations; load-test checkpoint growth; document path maps and approval rules next to the builder.
Applying the Habits in Order
| Stage | Habits | Exit criterion |
|---|---|---|
| Design | 1-3 | Named nodes, typed state, allowlisted routes |
| Harden | 4-6 | Durable threads, HITL on danger, hard stops |
| Operate | 7-9 | Stable streams, traces, smart retries |
| Evolve | 10 | Pins, migrations, and docs owned |
Quick Anti-Patterns
- One mega-node that plans, calls tools, and emails customers.
- Overwriting message history by forgetting reducers.
- Production multi-pod deploy with only
InMemorySaver. - Approval UX built solely on
interrupt_beforedebug flags. - Infinite agent <-> tools cycles with no step counter.
- Catching
Exceptionaroundinterrupt(). - Shipping without a single golden-path trace in LangSmith.
- Putting API keys inside state that gets logged.
Minimal Reference Skeleton
from typing import Annotated, Literal, TypedDict
from langgraph.graph import StateGraph, START, END
from langgraph.graph.message import add_messages
from langgraph.checkpoint.memory import InMemorySaver # swap for durable saver
class State(TypedDict):
messages: Annotated[list, add_messages]
steps: int
def agent(state: State) -> dict: ...
def tools(state: State) -> dict: ...
def route(state: State) -> Literal["tools", "__end__"]:
if state.get("steps", 0) >= 8:
return "__end__"
last = state["messages"][-1]
return "tools" if getattr(last, "tool_calls", None) else "__end__"
g = (
StateGraph(State)
.add_node("agent", agent)
.add_node("tools", tools)
.add_edge(START, "agent")
.add_conditional_edges("agent", route, {"tools": "tools", "__end__": END})
.add_edge("tools", "agent")
.compile(checkpointer=InMemorySaver())
)FAQs
Which three habits are non-negotiable for production?
Durable checkpoints with thread ids (4), stop conditions (6), and tracing (8). Without those, branching polish will not save incidents.
Should every agent use HITL?
No. Use interrupts for irreversible or high-risk actions. Low-risk reads can run automatically with strong logging.
How often should we revisit path maps?
Whenever product policy changes, and after any incident where the wrong branch ran. Treat maps as reviewed config.
Do these practices replace evals?
No. Graphs structure execution; evals prove task success across paths and prompt/model changes.
When is LangGraph the wrong tool?
Fixed single-path jobs with no resume needs may be simpler as scripts or plain chains. See framework comparison guidance.
How do LangChain and LangGraph split responsibilities?
LangChain: models, tools, parsers. LangGraph: durable multi-step orchestration. Keep the boundary clean in imports and mental models.
What should we monitor weekly?
Branch mix, interrupt wait times, tool error rate, checkpoint storage growth, cost per successful thread, and timeout/retry counts.
How do we migrate state schemas?
Add fields as optional, deploy readers first, backfill or default on read, and avoid renaming hot keys without a migration plan.
Related
Related: The LangGraph Mental Model
Related: LangChain & LangGraph Basics
Related: Building Your First Stateful Agent Graph
Related: Persistence and Checkpoints
Related: Human-in-the-Loop Approval Nodes
Related: Observability with LangSmith
Stack versions: Pins from the category manifest (verify at build): OpenRouter (~315+ models, July 2026 pricing/fees); LangGraph 1.0+; CrewAI 1.14+; Microsoft Agent Framework 1.0; Vercel AI SDK 6; Pydantic AI (latest); LlamaIndex (latest); OpenAI Agents SDK (latest + MCP); MCP (Linux Foundation governance); A2A (HTTP+SSE+JSON-RPC 2.0); Solana
@solana/web3.js+@solana/spl-token.