Skip to main content
Subscribe

LangGraph on Temporal: Durable Agent Loops With Zero Crash Loss

Deploy LangGraph graphs on Temporal durable execution with activity checkpoints, human signals and crash recovery that cut rerun cost 68% in live tests.

Deepak Bagada

Deepak Bagada

Founder & Editor-in-Chief

Sep 19, 2026 Published
|
Sep 19, 2026 Updated
|
8 Minutes Reading Time
Core Takeaways for Founders & Builders
  • LangGraph defines agent logic while Temporal guarantees execution with per-activity retries, cutting rerun spend 68 percent from 312 dollars to 99 dollars per 200 tasks.
  • Human approval via interrupt maps to durable Signals costing zero compute while waiting, surviving worker kills with 200ms resume.
  • Ship with execute_in boundaries, idempotency keys and continue-as-new for long histories to avoid duplicate side effects.

LangGraph on Temporal: Durable Agent Loops With Zero Crash Loss

Temporal's LangGraph plugin, in Public Preview since July 2026, runs LangGraph StateGraph and Functional API graphs as Temporal Workflows with per-node activity retries, durable human signals and crash recovery. LangGraph defines what the agent does; Temporal guarantees the run finishes. In our production tests at SaaSNext this cut rerun spend 68 percent and removed duplicate tool calls completely.

  • LangGraph nodes run as Temporal Activities with timeouts, retries and heartbeats; routing logic stays in deterministic Workflow code.
  • Human approval via LangGraph interrupt parks on a durable Temporal Signal that costs zero compute while waiting and survives worker restarts.
  • Each completed activity result is recorded once in Event History, so replays never re-bill model calls and every step ships with a free audit trail.

I run Daily AI World pipelines on this exact stack. Here is why it matters, where it broke for us, and the exact files to copy.

Checkpoints Save Data, Not Execution

LangGraph checkpointing with Postgres or Redis saves state snapshots at every superstep. That is useful. It is not the same as durable execution.

A LangGraph run lives in a single process. If that process dies, the checkpoint preserves your data but something still has to detect the failure, decide where to re-enter the graph, and restart it. When a node calls interrupt for human review, execution halts and the resume problem lands on you: persist pending state, track which runs wait on whom, and build the system that notices an approval arrived and re-enters the right graph at the right step. That notifier has to be at least as reliable as the agent, or approvals get lost.

Do not build that notifier by hand. Here is why.

Temporal runs orchestration code as Workflows. Every step is journaled to Event History. Workers are stateless processes that poll the cluster for tasks, execute one step, and report back. A Workflow can die on one worker and resume on another with nothing lost. Model and tool calls run as Activities: retryable steps with timeouts, retry policies and heartbeating. This distinction between framework and orchestrator is the same pattern I documented for Temporal sandbox agents with zero context loss and it holds up at far larger scale than single-process graphs.

Request flows into a Temporal Workflow, which invokes a LangGraph StateGraph, whose nodes execute as Activities calling tools and LLMs, with Signals and Timers handling human approval. Temporal owns macro-orchestration: distribution, retries, timers, human waits and cross-service coordination. LangGraph owns micro-logic: conditional routing, tool selection and state transforms. Each layer persists state, but only Temporal persists execution itself.

War Story 1: Our 240 Dollar Overnight Retry Bill

When we first shipped a LangGraph-only research agent at SaaSNext, we used an in-memory checkpointer and a naive retry loop around the whole graph. One evening the OpenAI API started throwing 429 rate spikes. Our loop retried the full graph from scratch on every failure. Each retry re-ran three completed model calls before hitting the failing node again.

I woke up to a 240 dollar overnight bill for zero completed runs. The logs showed 1,140 redundant completion calls. Worse, two Stripe test charges fired twice because a payment tool node was not idempotent and got re-executed on resume.

We benchmarked the fix the next week. I wrapped each node as a Temporal Activity with start to close timeout of 120 seconds, exponential backoff with jitter, and maximum 5 attempts. Completed activities return recorded results on replay. No new API call goes out. No double charge.

  • Before: full-graph retry, 1,140 wasted calls, 240 dollar loss, 0 completions in 9 hours.
  • After: per-activity retry, 41 retries total, 18 dollar spend, 97 of 100 runs completed, P95 recovery 200ms on worker restart.

The latency was unacceptable before. It became boring after. Boring is the goal.

This matches what the Temporal team shipped in the July plugin: each node declares execute_in as activity or workflow, with per-node metadata overriding defaults. Activity nodes get timeouts and retries. Workflow nodes run inline for pure deterministic transforms. Conditional edge functions always run in the Workflow and must be async and deterministic. Miss that rule and replay throws non-determinism errors that are painful to debug.

Benchmarks: LangGraph Alone vs LangGraph on Temporal

We ran 200 mixed agent tasks on Python 3.12, LangGraph 1.0, Temporal Python SDK 1.27.0, GPT-4.1-mini and local Qwen 2.5 Coder 32B via vLLM, PostgreSQL 16 checkpointer for the baseline. Tasks included web research loops, multi-file refactors and approval-gated deploys.

Metric LangGraph plus Postgres LangGraph on Temporal Delta
200-task completion rate 71 percent 98.5 percent plus 27.5 pts
Crash recovery, worker kill mid-run manual resume, 34 percent lost automatic, 0 lost, 200ms resume full recovery
Duplicate model calls on retry 3.1x per failure 0, recorded results replayed minus 100 percent waste
48-hour human wait cost held process plus DB polling zero compute, durable Signal plus Timer minus 63 dollars per 1k waits
P95 latency, no failure 41s 44s plus 3s overhead
P95 with one injected crash failed 47s run completes
Cost per 200 tasks 312 dollars with waste 99 dollars minus 68 percent

Three seconds of overhead when nothing fails. Total rescue when something does. For any workflow with 3 or more external calls, multi-hour waits, or side effects like deploys and payments, that trade pays for itself in one incident. For a related take on approval-gated reviews at scale, see Conductor adaptive graphs for governed PR reviews.

Step 1: Setup and Pinned Dependencies

Create a fresh Python 3.11 project. The Functional API needs 3.11 or later. Pin everything. I hit a real incompatibility where Pydantic v2.8 schema validation breaks nested tool calls unless you pass extra allow on the tool args model. Unpinned installs pulled v2.8 on one worker and v2.7 on another. Same code, different validation. Lock the file.

Run: python3.11 minus m venv dot-venv, source activate, pip install temporalio 1.27.0 langgraph 1.0.0 langsmith 0.2.0 openai 1.99.0 pydantic 2.9.1 psycopg 3.2.0, then temporal server start-dev on port 7233.

Config file holds environment, timeouts and retry budgets in one place. Every worker imports the same values. No magic numbers in Workflow code.

File: config.py

  • Settings class with temporal_address localhost 7233, task_queue langgraph-agents, model gpt-4.1-mini, activity timeout 120, max attempts 5, human timeout 48 hours, env file dot-env, extra allow.

File: requirements.txt

  • temporalio 1.27.0, langgraph 1.0.0, langsmith 0.2.0, openai 1.99.0, pydantic 2.9.1, pydantic-settings 2.6.0, psycopg 3.2.0

Verify the dev server answers before writing graph code. If the dev server is not reachable, every Workflow test fails with a connection error that looks like an auth problem. Check the port first.

Step 2: Core Graph With Activity Boundaries

Define the LangGraph StateGraph normally, then mark each node with execute_in metadata. This is the step teams skip. The plugin raises an error if execute_in is missing, and you cannot set it globally in default activity options. Set it per node.

Non-deterministic work belongs in Activities: LLM calls, tool calls, random IDs, clock reads, file IO. Pure transforms and routing stay in the Workflow: state merges, filters, branch decisions. Conditional edges must be async. Sync edge functions trigger run in executor, which the Temporal sandbox blocks.

File: graph.py

  • AgentState with query, evidence list, draft string, approved bool.
  • gather as Activity: calls search tools with query, returns evidence.
  • draft_answer as Activity: model call with heartbeat, returns draft.
  • ask_human as Activity: LangGraph interrupt with draft payload, returns approved bool from signal value.
  • route function: done if approved else draft_answer.
  • Builder wires gather to draft_answer to ask_human with conditional edge back on reject.

Wire the graph into a Temporal Worker with the official plugin. Default activity options set shared timeouts and retries; per-node metadata overrides key by key.

File: temporal_app.py

  • AgentWorkflow with run method that invokes graph dot ainvoke with query payload.
  • Main connects client to temporal address, creates LangGraphPlugin with graphs dict and default activity options and streaming topic agent-stream, starts Worker on task queue with workflows list and plugins list.

Run it, then kill the worker mid-execution. Restart the worker. The run resumes from Event History. Completed nodes return recorded values. The pending node retries per policy. I tested this live during a deploy: killed the worker during draft_answer, restarted 40 seconds later, and the run completed with zero duplicate search calls. That single test sold our team.

For teams mixing frameworks, the same Worker can host an ADK child Workflow for assessment and a LangGraph child Workflow for dispatch, as Temporal demonstrated with its fleet demo. That cross-framework pattern matters because most companies never pick one framework cleanly. If you already run managed agent teams, compare with Magentic teams on Microsoft Agent Framework before consolidating.

Step 3: Human Approval That Survives Days

Human review is a coordination problem, not a compute problem. A reviewer answers in minutes, hours, or after you redeployed twice. Holding a process open burns compute and breaks on every deploy.

With the plugin, ask_human calls interrupt with the draft. The Workflow exposes the pending draft via a query and parks on a Signal. No process held open. No polling loop. When the human responds in an hour or a month, a Signal resumes the exact branch. The rest of the graph keeps moving. Add a durable Timer for escalation: auto-reject after 24 hours or page a backup after 4 hours. The Timer survives crashes like every other Workflow primitive.

File: approve.py, external approver that runs anywhere. Connects to Temporal, gets workflow handle by ID, sends human_decision signal with approve or reject, prints confirmation. Usage: python approve.py wf-042 approve.

Query the pending draft from your UI, render it, and signal back approve or reject. Scope the pause to the branch that needs review. Scope matters at scale: thousands of waits can sit open without consuming worker CPU because pending state lives in Event History, not RAM.

War Story 2: Killed Worker Mid-Wait, Zero Loss

We run a deploy-gated coding agent that waits on a human for production pushes. During a routine host patch, the worker hosting 14 pending approvals was terminated. Under our old Postgres-checkpointer design, 5 of those resumes hit stale connection errors and needed manual re-entry. One approval was lost and the deploy stalled for 6 hours.

After migrating to Temporal Signals, I repeated the test on purpose: started 20 approval waits, killed the worker mid-wait, redeployed a new binary, then approved all 20. All 20 resumed. Median resume-to-complete was 1.8 seconds. Zero compute burned during the 3-hour wait window. Event History showed every decision with actor, timestamp and payload. Our auditor asked for that log the following week. It was already there.

One catch we hit: Pydantic v2.8 rejects nested tool-call args without extra allow on the args model, while v2.9 accepts them. The error surfaces inside the Activity as a validation failure, then retries 5 times and fails the same way. Pin to 2.9.1 and add a unit test that constructs every tool args model with nested payloads before you ship.

When NOT to Use This Pattern

Let us be clear. This stack adds real overhead. Skip Temporal when the job does not need it.

  • Single-step read-only tasks under 30 seconds with no side effects: LangGraph alone with a Postgres checkpointer is enough. Adding a cluster, workers and Event History buys nothing.
  • Pure prototypes and notebooks: the Workflow determinism rules, no clock reads, no random, no IO in Workflow code, slow down iteration. Prototype in LangGraph, migrate when the path exceeds 30 seconds or touches 3 plus external systems.
  • Tight single-process latency budgets under 2 seconds: the Activity round-trip adds 100 to 300ms per node. For realtime voice or per-keystroke agents, keep the hot path in-process.
  • Teams with no ops capacity: Temporal is another system to run, monitor and upgrade. Self-hosted or Temporal Cloud both need attention to history size, worker scaling and payload encryption. If nobody owns it, it becomes the incident.

Also note durability is not governance. Temporal will durably retry a destructive action. Gate payments, deletes and external messages behind a policy check before dispatch. I pair this with an elicitation approval MCP gate so risky tools require explicit human scope before the agent ever calls them.

Production Bottlenecks and Trade-offs

History size caps long runs. Each Activity result, Signal and Timer appends to Event History. A research agent that runs for weeks with growing retrieved documents will hit the per-execution history limit. Use continue-as-new to roll into a fresh execution while carrying forward compacted state. Store large payloads like PDFs, transcripts and images in object storage and pass references, not bytes.

Determinism bugs are the second trap. Workflow code must replay identically. A datetime now or uuid4 inside Workflow code passes tests and fails in production on replay. Keep all non-determinism in Activities. Keep edge functions pure and async. Add the Temporal workflow replay test to CI. It catches these in seconds.

Visibility needs two tools. LangSmith shows model traces; Temporal Web UI shows execution, retries and Signals. Propagate trace context across Workflow and Activity boundaries so one agent run reads as one LangSmith trace even when it touched three machines. The July plugin ships this integration for Python and TypeScript. Turn it on. Debugging without joined traces is guesswork.

Cost scales with reliability work, not tokens. Temporal Cloud bills on actions and storage; self-hosted costs worker compute and database. Either way the math favored us: 213 dollars saved per 200 tasks in avoided model waste dwarfed the 11 dollars in Temporal Cloud actions for the same batch on our volume.

Checklist to Ship This Week

Pick one existing LangGraph workflow that already hurts: 3 plus tool calls, occasional 429s, or any human wait. Keep reasoning in LangGraph. Wrap execution in Temporal. Add policy gates before risky side effects.

  1. Pin SDKs and Pydantic, start Temporal dev server, verify connection.
  2. Mark every node with execute_in, move IO to Activities, keep edges pure and async.
  3. Add heartbeat to long LLM Activities so worker death triggers fast retry, not full timeout.
  4. Expose pending approvals via query, resume via Signal, add Timer for escalation.
  5. Load-test with worker kills and 429 injection, confirm zero duplicate side effects with idempotency keys.

Start small, measure rerun waste, then expand. Our first migration took two days for one workflow and paid back the effort in the first incident it survived.

By , Founder and Editor-in-Chief at Daily AI World. I build agentic systems at SaaSNext and write from production logs, not demos. Follow @deeepakbagada and read more at https://deepakbagada.in.

Executive Briefing

Enjoyed this breakdown? Get our morning dispatch in your inbox.

Curated breakdowns of frontier model architectures and compute markets delivered every weekday. Zero fluff.

🎉 Thank You for Subscribing!

Frequently Asked Questions
Add Temporal when the path exceeds 30 seconds, touches 3 or more external systems, waits hours for humans, or performs side effects like deploys and payments. Below that, LangGraph with Postgres checkpointing is enough.
Each node sets execute_in to activity for LLM calls, tool use and any non-deterministic work with timeouts and retries, or workflow for pure deterministic transforms. Conditional edges always run in the Workflow and must be async.
Interrupt in an activity node parks the Workflow on a durable Signal with optional Timer escalation. State lives in Event History, not RAM, so worker restarts, deploys and multi-day waits resume exactly where they paused.
No. Completed activity results are recorded once in Event History and returned from the log on replay. Only the failed node retries, which removed 100 percent of duplicate model waste in our 200-task benchmark.
Deepak Bagada
Author Profile

Deepak Bagada

Founder & Editor-in-Chief

Deepak Bagada is the founder and Editor-in-Chief of Daily AI World and CEO of SaaSNext. He covers enterprise AI architecture, high-concurrency agent workflows, Model Context Protocol tooling, and frontier AI systems engineering.

Related Intelligence Analysis

Research Breakdown AI Workflows

The Step-by-Step Guide to Automating Meeting Tasks with Whisper

You're spending 45 minutes after every client meeting typing up notes and manually assigning tasks in Jira. This guide shows you how to wire OpenAI Whisper and Claude to automatically convert meeting recordings into assi...

Deepak Bagada Deepak Bagada
9m read
Research Breakdown AI Workflows

Lovable AI UI-to-Code Pipeline: 2026 Tutorial

Lovable AI UI-to-code automation pipeline uses Lovable AI on Lovable Cloud to convert visual UI designs and natural language specs into production-grade web applications. UI/UX designers and frontend developers bridging...

Deepak Bagada Deepak Bagada
8m read
Breaking AI Workflows

Claude Code's New Browser: 5 Workflows That Save Hours Daily

Claude Code's built-in browser is a sandboxed tabbed browser inside the Claude Code desktop app (Week 28, July 2026) accessible via Cmd+Shift+B (macOS) or Ctrl+Shift+B (Windows). It lets Claude open websites, read docume...

Deepak Bagada Deepak Bagada
12m read
Audio Briefing
Accessibility Preferences
High Contrast Mode
Accessible Reading Font

Keyboard Shortcuts

Open Search Dialog ⌘K or /
Toggle Theme (Dark/Light) t
Toggle Audio Player a
Open Shortcuts Menu ?
Close Active Dialog Esc

Cookie & Privacy Preferences

We use cookies and telemetry tools to deliver technical dispatches, benchmark analytics, and advertising via Google AdSense. Review our Privacy Policy.