{"post":{"slug":"building-langgraph-agents-2026","title":"Building LangGraph agents in 2026: a code-first walkthrough","excerpt":"A working research agent built in LangGraph 0.4 — state, nodes, conditional edges, and the patterns that keep agents from spinning forever.","category":"ai","date":"February 3, 2026","author":"ByteLedger Team","content":"<span class=\"dropcap\">L</span>angGraph hit 0.4 in early 2026 with stable state checkpointing, durable execution, and a cleaner API. It's now the framework of choice when you need an agent that's more than a prompt-with-tools — when you need branches, retries, parallel work, and persistent state across runs. This walkthrough builds a research agent that takes a question, searches, reads, and produces a cited summary.\n\n## What changed in 2026\n\n- **Durable execution shipped stable.** Agents survive process restarts; long-running research tasks work.\n- **Streaming through the graph** — token-by-token output during multi-node runs.\n- **First-class human-in-the-loop** — `interrupt()` makes pausing for human review trivial.\n\n## Step 1: define state\n\n```python\nfrom typing import TypedDict, Annotated\nfrom langgraph.graph import StateGraph, END\nfrom operator import add\n\nclass ResearchState(TypedDict):\n    question: str\n    searches: Annotated[list[str], add]   # accumulated\n    docs: Annotated[list[dict], add]\n    answer: str\n    iterations: int\n```\n\nState is a typed dict — every field your nodes read or write goes here. Use `Annotated[..., add]` for fields that accumulate across runs (search history). Bare types overwrite. The `iterations` counter is the kill switch that stops infinite loops.\n\n## Step 2: define nodes\n\nEach node is a function that takes state and returns a partial state update. The planner decides what to search next; the searcher hits the web; the reader extracts facts; the writer composes the final answer. Keep nodes pure — no global state, no side effects beyond the explicit return.\n\n```python\ndef planner(state: ResearchState) -> dict:\n    plan = llm.invoke(PLANNER_PROMPT.format(question=state[\"question\"], history=state[\"searches\"]))\n    return {\"searches\": [plan[\"next_query\"]], \"iterations\": state.get(\"iterations\", 0) + 1}\n\ndef searcher(state: ResearchState) -> dict:\n    query = state[\"searches\"][-1]\n    results = tavily.search(query, max_results=5)\n    return {\"docs\": results}\n\ndef writer(state: ResearchState) -> dict:\n    answer = llm.invoke(WRITER_PROMPT.format(question=state[\"question\"], docs=state[\"docs\"]))\n    return {\"answer\": answer}\n```\n\n## Step 3: wire conditional edges\n\nThe interesting part. After each search, we ask: do we have enough to answer, or do we need more research? A conditional edge routes to either `writer` (done) or back to `planner` (more research). The kill switch lives here too — past 6 iterations, force-route to writer regardless.\n\n```python\ndef should_continue(state: ResearchState) -> str:\n    if state[\"iterations\"] >= 6:\n        return \"write\"\n    if needs_more_research(state[\"docs\"], state[\"question\"]):\n        return \"plan\"\n    return \"write\"\n\ngraph = StateGraph(ResearchState)\ngraph.add_node(\"plan\", planner)\ngraph.add_node(\"search\", searcher)\ngraph.add_node(\"write\", writer)\ngraph.set_entry_point(\"plan\")\ngraph.add_edge(\"plan\", \"search\")\ngraph.add_conditional_edges(\"search\", should_continue, {\"plan\": \"plan\", \"write\": \"write\"})\ngraph.add_edge(\"write\", END)\nagent = graph.compile()\n```\n\n## Comparison: LangGraph vs alternatives in 2026\n\n| Framework | Best for | Skip if |\n| --- | --- | --- |\n| LangGraph 0.4 | Stateful agents, human-in-loop | Simple chains |\n| LlamaIndex | RAG-heavy workflows | You're not retrieving |\n| OpenAI Swarm | Multi-agent handoff | You need durable state |\n| Anthropic SDK + custom | Full control, lean | Building a team |\n| CrewAI | Agent role-play patterns | You need rigor |\n\n## Common mistakes to avoid\n\n**No iteration cap.** The number-one source of \"my agent is burning credits and not stopping\". Always include a hard cap.\n\n**Putting prompts in code.** Externalize prompts to files or templates. You'll iterate them 100x more than the graph.\n\n**Skipping checkpointing in production.** Without checkpoints, a process restart loses all in-flight work. Use SQLite checkpointer for dev, Postgres for prod.\n\n**Mixing concerns in nodes.** A node that searches AND filters AND writes is a node that's hard to debug. One responsibility per node.\n\n## FAQ\n\n**LangGraph vs LangChain?**\nLangGraph is the runtime; LangChain is the tool/integration library. They compose. New code should use LangGraph as the orchestrator and LangChain only for integrations.\n\n**Can I use Claude or Gemini, not OpenAI?**\nYes — `ChatAnthropic` and `ChatGoogleGenerativeAI` work seamlessly. Pick by quality on your task.\n\n**How do I observe what the agent did?**\nLangSmith is the obvious answer, free tier is generous. Or wire OpenTelemetry directly.\n\n**When NOT to use LangGraph?**\nIf your task is \"one prompt, one tool, done\" — skip the framework. Use the model SDK directly.\n\n## Where to go next\n\nFor related guides see [AI coding agent workflows in 2026](/blog/ai-coding-agents-workflows-2026), [AI agents for business in 2026](/blog/ai-agents-for-business-2026), and [MCP servers in Claude Desktop in 2026](/blog/mcp-claude-desktop-setup-2026).","hue":205,"metaTitle":"Building LangGraph Agents in 2026 (Code Walkthrough)","metaDescription":"Working LangGraph 0.4 research agent in Python — state design, conditional edges, tool nodes, and the patterns that keep agents reliable in 2026.","keywords":["langgraph tutorial 2026","langgraph python","building ai agents","langgraph state","langgraph conditional edges","research agent ai","langgraph vs langchain","ai agent framework","python ai agent","langgraph 0.4"],"tldr":["**LangGraph is the right tool when you need explicit state.** Pure prompting falls apart past 5 turns.","**State is a typed dict.** Define what you carry across nodes — nothing else lives in memory.","**Conditional edges replace big if-statements.** Easier to debug than nested chains.","**Always cap iterations.** Agents that loop are agents you'll regret."],"readTime":"3 min read","wordCount":669},"related":[{"slug":"crewai-vs-autogen-vs-langgraph-2026","title":"CrewAI vs AutoGen vs LangGraph: a 2026 head-to-head with code","excerpt":"We built the same multi-agent research system in CrewAI, AutoGen, and LangGraph. Here is what each gets right, where they break in production, and which to pick.","category":"ai","date":"February 9, 2026","author":"ByteLedger Team","readTime":"3 min read","hue":192},{"slug":"langgraph-vs-crewai-2026","title":"LangGraph vs CrewAI: AI Agent Frameworks Compared 2026","excerpt":"Two ways to build AI agents in 2026 - LangGraph gives you explicit control, CrewAI gives you speed. Here is how to pick without regret.","category":"ai","date":"April 28, 2026","author":"ByteLedger Team","readTime":"4 min read","hue":215},{"slug":"ai-agent-frameworks-compared-2026","title":"AI agent frameworks compared in 2026: LangGraph, CrewAI, AutoGen, Agents SDK","excerpt":"An honest comparison of the four agent frameworks teams are actually shipping in 2026 — code patterns, debuggability, and which to pick by team size and use case.","category":"ai","date":"February 8, 2026","author":"ByteLedger Team","readTime":"3 min read","hue":198}],"sameCategory":[{"slug":"agent-cost-attribution-2026","title":"Agent Cost Attribution: Finding Where the Tokens Went","excerpt":"A single monthly API bill tells you that agents are expensive. It does not tell you which feature, which customer, or which retry loop is responsible. That gap is fixable.","category":"ai","date":"August 19, 2026","author":"ByteLedger Team","readTime":"5 min read","hue":220},{"slug":"human-in-the-loop-agents-2026","title":"Human-in-the-Loop Agents: Where to Put the Approval Gate","excerpt":"Approve everything and the agent is a slow autocomplete. Approve nothing and you have handed irreversible actions to a system that can be talked into things.","category":"ai","date":"August 19, 2026","author":"ByteLedger Team","readTime":"5 min read","hue":197},{"slug":"reasoning-effort-controls-2026","title":"Reasoning Effort Controls: Tuning How Hard a Model Thinks","excerpt":"Fixed thinking budgets gave way to effort levels, and the default is rarely the right setting. Here is how the dial behaves and where each level actually belongs.","category":"ai","date":"August 19, 2026","author":"ByteLedger Team","readTime":"5 min read","hue":210},{"slug":"retrieval-metrics-explained-2026","title":"Retrieval Metrics: Measuring the Half of RAG That Fails","excerpt":"When a RAG system answers badly, the retrieval usually failed before the model ever spoke. Measuring generation quality alone hides that entirely.","category":"ai","date":"August 19, 2026","author":"ByteLedger Team","readTime":"5 min read","hue":215}],"newer":{"slug":"best-multi-currency-accounts-2026","title":"Best multi-currency accounts 2026: Wise, Revolut, HSBC Global, Schwab compared","excerpt":"Best multi-currency accounts for 2026 — Wise, Revolut, HSBC Global, Schwab, and others compared by features, fees, and the right pick by use case.","category":"finance","date":"February 3, 2026","author":"ByteLedger Team","readTime":"4 min read","hue":310},"older":{"slug":"deepseek-r2-review-2026","title":"DeepSeek R2 review: open-weights reasoning at 1/10th the cost in 2026","excerpt":"DeepSeek R2 is the open-weights reasoning model that's actually competitive with frontier in 2026. Here is what it does well, where it falls short, and how to deploy it.","category":"ai","date":"February 3, 2026","author":"ByteLedger Team","readTime":"3 min read","hue":188}}