LangGraph/APIs & Tooling
★ OverviewIntermediate15 min

Functional API

The Functional API is LangGraph's decorator-based alternative to StateGraph. It gives you the same checkpointing, streaming, and human-in-the-loop guarantees with plain Python functions — but only works for linear and branching workflows. This article covers when to use it, how it fails in production, and the one deployment gotcha that silently breaks task caching.

Quick Reference

  • @entrypoint(checkpointer=saver): marks a function as a LangGraph workflow — automatic checkpointing, streaming, human-in-the-loop
  • @task: marks a unit of work — independently checkpointed, returns a future, caches result on resume
  • Deployment gotcha: always pass checkpointer= at compile time — the API server's runtime-injected checkpointer is invisible to @task caching
  • entrypoint.final(value=X, save=Y): decouple what the caller receives from what gets saved to the checkpoint
  • Injectable params: previous (last return value), store (long-term memory), writer (custom streaming), config (RunnableConfig)
  • Determinism rule: wrap all randomness and side effects inside @task — not in the entrypoint body
  • Security: langgraph-checkpoint >= 4.0.0 required — earlier versions have RCE vulnerabilities in the cache/checkpoint serializer

Should I Use the Functional API?

Should I Use the Functional API?UseStateGraphCycles ✓Send() fan-out ✓Multi-agent ✓Need cycles or agent loops?NoYesNeed dynamic fan-out (Send())?NoYesMulti-agent orchestration?NoYes✓ Use Functional APILinear / branching workflow

Use Functional API for linear/branching workflows. Upgrade to StateGraph when you need cycles, Send(), or multi-agent.

The Functional API is the right choice when your workflow is a linear pipeline or a branching pipeline without cycles. If you need loops (an agent that retries until it gets a good answer), dynamic parallelism (Send() fan-out over a variable-length list), or multi-agent coordination (multiple specialized agents handing off to each other), you need StateGraph. For everything else — data pipelines, RAG chains, approval flows, simple chatbots — the Functional API is less boilerplate with the same guarantees.

FeatureFunctional APIStateGraph
SyntaxDecorated functions (@entrypoint, @task)add_node() + add_edge() + compile()
State schemaInferred from function params and returnsExplicit TypedDict or Pydantic BaseModel
Cycles / loopsNot supported — linear and branching onlyFirst-class: edges can loop back to earlier nodes
Conditional routingPython if/else inside the entrypointadd_conditional_edges() with path maps
Dynamic fan-outNot supported (no Send() equivalent)Send() API maps work across variable-length inputs
Human-in-the-loopinterrupt() works inside @task functionsinterrupt() + interrupt_before/interrupt_after
SubgraphsCall other @entrypoint functions directlyCompiled graph added as a node
Best forLinear workflows, branching, data pipelinesAgents with cycles, multi-agent systems, Send()
Start here, graduate when needed

Most workflows (data pipelines, RAG, simple chatbots, approval chains) don't need cycles. Start with the Functional API. Migrate to StateGraph only when you actually hit a limitation — cycles, Send(), or complex multi-agent routing. Premature migration adds 50–100 lines of boilerplate without benefit.