DEV Community

Cover image for LangGraph: Orchestrate a Swarm of AI Agents with One Graph
databufflabs
databufflabs

Posted on Originally published at databuff.ai

LangGraph: Orchestrate a Swarm of AI Agents with One Graph

A single AI assistant is already standard in many teams: ask a question, get an answer, like chatting with a seasoned hand. But the moment you want several AIs to work together — one checks metrics, one digs through logs, one draws the conclusion — it falls apart: who hands off to whom? Can they run in parallel? Should it stop and ask you midway? If it crashes halfway, is everything before it wasted?

LangGraph exists to answer those questions. It's LangChain's open-source multi-agent orchestration framework (MIT). But the essence first: it is, before anything else, a general-purpose graph execution engine — nodes, edges, conditional edges, parallelism, checkpointing, waiting on a human are all generic graph capabilities, with no inherent tie to AI; it just so happens that a node can hold an AI, and once it does, you're "orchestrating multiple AI agents." The core is simply: you draw the graph, it runs the graph.

This article uses a single case — a 2 a.m. alert: "order-service error rate spiking" — to explain it end to end: the graph first, then the code, then the execution model and context passing, and finally a comparison with Dify and Claude Code's dynamic workflow.

A case: 2 a.m., order-service error rate spikes

Your on-call phone buzzes. The alert says order-service error rate just hit 12%, and your AI assistant has to walk the whole investigation flow itself. This graph is the entire logic it will execute:

langgraph-case-diagram

Fig 1 · A late-night investigation: one graph exercises nodes, edges, conditional edges, Send, interrupt, and checkpoint.

A single run goes roughly like this: the AI diagnoses first, finds it's serious, and fans out 12 parallel subtasks to check instances one by one; after checking, it summarizes "these 3 are bad"; then it stops and asks whether to restart — you approve, and only then does it execute the fix, finally re-checking and reporting.

This graph uses almost every core capability LangGraph has: nodes (each box), edges (arrows), conditional edges (serious?), Send (batch checks), interrupt (await your approval), checkpoint (persist each step). Let's draw it in code.

Drawing this graph in code

Build a graph, register each box as a node, connect arrows as edges:

from langgraph.graph import StateGraph, START, END

def diagnose(state):   # 1 diagnose: check error rate, pull Trace, return severity
    error_rate = query_error_rate(state["service"])
    return {"abnormal": error_rate > 5}

def fan_out(state):    # 3 batch check: Send dispatches 12 subtasks at once
    return [Send("check_host", {"host": h}) for h in state["hosts"]]

def check_host(state): # 4 check one instance (each Send is its own small task)
    return {"results": [f"{state['host']}: ok"]}

def ask_human(state):  # 5 await your approval
    decision = interrupt("3 bad instances found — auto-restart?")
    return {"decision": decision}

def fix(state):        # 6 execute the fix
    restart(state["hosts"])
    return {}

def report(state):     # 7 produce the report
    return {"report": "handled"}

g = StateGraph(dict)
g.add_node("diagnose", diagnose)          # register nodes
g.add_node("fan_out", fan_out)
g.add_node("check_host", check_host)
g.add_node("ask_human", ask_human)
g.add_node("fix", fix)
g.add_node("report", report)

g.add_edge(START, "diagnose")             # start -> diagnose
g.add_conditional_edges("diagnose", route)# 2 conditional edge: serious? -> fan_out or report
g.add_conditional_edges("fan_out", fan_out)  # 3 Send fan-out
g.add_edge("check_host", "ask_human")     # checked -> await approval
g.add_edge("ask_human", "fix")            # approved -> fix
g.add_edge("fix", "report")               # fixed -> report
g.add_edge("report", END)

graph = g.compile(checkpointer=InMemorySaver())   # compile + enable persistence
Enter fullscreen mode Exit fullscreen mode

A few key points, one by one:

1 · A node is just a plain function. diagnose, check_host, fix are ordinary Python functions. Whether to call an LLM is entirely up to the function body — diagnose can call a model, check_host can be pure computation.

2 · A conditional edge picks the path. route returns "fan_out" or "report", and the graph walks to the matching node:

def route(state):
    return "fan_out" if state.get("abnormal") else "report"
Enter fullscreen mode Exit fullscreen mode

3 · Send = dispatch in bulk. fan_out returns 12 Send("check_host", {...}), executed in parallel within the same superstep, results auto-merged:

def fan_out(state):
    return [Send("check_host", {"host": h}) for h in state["hosts"]]
Enter fullscreen mode Exit fullscreen mode

langgraph-send-fanout

Fig 2 · Send zoomed: dispatch N independent subtasks in one superstep, then merge.

4 · interrupt = stop and wait for a human. Call interrupt() inside a node and the graph halts, surfacing the question to you; after you approve and resume with an answer, the graph resumes from its checkpoint:

decision = interrupt("3 bad instances found — auto-restart?")
# after you approve:
graph.invoke(Command(resume="yes"),
             {"configurable": {"thread_id": "t1"}})
Enter fullscreen mode Exit fullscreen mode

5 · checkpoint = persist every step. The graph stores progress after each step (the thread_id acts as a ticket id). If it crashes midway, re-invoke with the same thread_id and it resumes from the breakpoint — officially called durable execution.

How does LangGraph actually execute this graph?

Running the graph isn't a headlong dash from start to end; it moves forward round by round. The official term is superstep, and each round does four things:

langgraph-superstep

Fig 3 · One superstep: figure out who runs -> run in parallel -> refresh the board -> persist.

Nodes don't pass messages to each other. Everyone faces the same whiteboard: this round only reads what's already on the board, and writes are set aside — only after the whole round finishes does the board refresh. The source comment is one line: what step N writes, step N+1 sees.

langgraph-whiteboard

Fig 4 · How context passes: no talking between nodes, just read/write the same whiteboard.

Walk the Fig 1 on-call case through it, and the rhythm is:

langgraph-case-supersteps

Fig 5 · The on-call case unrolled by superstep: writes land on the board next round.

Chat history works the same way: put messages on the board, and the next step sees them.

Compared to other options — where's the difference?

Dify and Claude Code are both often called "multi-agent," but set beside LangGraph, one table each is enough.

Dify: visual platform vs code library. Dify is a web canvas where you drag nodes; LangGraph is a graph you draw in Python code.

Dimension Dify LangGraph
Form Web canvas, drag nodes Draw the graph in Python
Who it's for Non-developers / quick prototypes Developers / fine control
License Apache 2.0 modified (commercial conditions apply) MIT (commercial use OK)

Claude Code dynamic workflow: the AI writes a LangGraph on the spot. You just say what to do; in the background it auto-decomposes the task and spins up tens to hundreds of agents in parallel.

Dimension Claude Code dynamic workflow LangGraph
Who orchestrates The AI itself: reads the request, decomposes dynamically You: draw a fixed graph in code
Orchestration artifact An agent tree in memory, gone after the run A compilable, replayable graph definition
Predictability Same input may produce different graphs Graph fixed, behavior predictable

One line to remember: Dify hands you a ready-made car, Claude Code has the AI write the orchestration on the spot, LangGraph hands you the engine and the blueprint — the most freedom, and the most work.

Our open-source DataBuff — how do its agents collaborate?

Our open-source DataBuff (AI-native APM, GitHub: https://github.com/databufflabs/databuff) also does multi-agent collaboration. You talk to a single entry point; an AI brain dispatches the work to experts — query, inspection, ops, Q&A — in parallel, then assembles their findings into a conclusion with an evidence chain:

databuff-multi-agent

Fig 6 · You face one entry point; the complex collaboration happens behind it.

The core purpose

LangGraph's core purpose isn't "to hand you a ready-made multi-agent solution," but to provide a controllable runtime for agent flows that need to run long, hold state, persist, and loop in a human — it turns the low-level dirty work — parallelism, checkpointing, waiting, recovery — into primitives, so you only worry about the business flow itself.

Takeaway: copy those 6 functions and the graph structure from the case and run them locally, and you'll understand what multi-agent orchestration is about.


DataBuff

Open-source AI-native OpenTelemetry APM — metrics, traces, logs, and AI troubleshooting in one.

GitHub: https://github.com/databufflabs/databuff

Live demo: https://demo.databuff.ai

Top comments (0)