LangGraph

@rekall/langgraph is a LangGraph checkpointer backed by Rekall execution memory. Give your LangGraph agents durable, server-persisted state — resume after a crash, time-travel, and human-in-the-loop — in one line.

Overview

LangGraph ships in-memory and SQLite savers; production agents need a durable, multi-host store. RekallSaver makes Rekall that store, reusing its execution-memory layer — the same one that powers Rekall's HITL pause/resume. Benchmarked, crash-recovery repeats 0% of completed work versus 33% for a stateless agent.

restart_alt

Crash recovery

Resume exactly where the graph left off — state lives in Rekall, not memory.

history

Time-travel

Full checkpoint history per thread, so list and parent lineage work.

pan_tool

HITL

Pending writes (putWrites) persist for human-in-the-loop pauses.

Installation

Terminal
npm install @rekall/langgraph @langchain/langgraph-checkpoint

@langchain/langgraph-checkpoint is a peer dependency — you already have it transitively via @langchain/langgraph.

Usage

Build a saver with RekallSaver.fromApi and pass it to compile. The thread_id is the persistence key — one Rekall blob per thread.

graph.ts
import { StateGraph } from '@langchain/langgraph';
import { RekallSaver } from '@rekall/langgraph';
const checkpointer = RekallSaver.fromApi({
apiUrl: 'https://api.rekall.app', // or http://localhost:9876 in dev
apiKey: process.env.REKALL_API_KEY, // rk_… key, or accessToken: 'rat_…'
});
const graph = workflow.compile({ checkpointer });
// thread_id is the persistence key — one Rekall blob per thread.
await graph.invoke(input, { configurable: { thread_id: 'user-42' } });
// …process restarts / crashes…
// Resumes exactly where it left off — state lives in Rekall, not memory.
await graph.invoke(null, { configurable: { thread_id: 'user-42' } });

That's it. Every checkpoint LangGraph emits is persisted to Rekall and read back on resume.

How It Maps

  • check_circleEach LangGraph thread (configurable.thread_id) maps to one Rekall external-state blob (provider: "langgraph", providerAgentId: thread_id).
  • check_circleThe blob holds the full checkpoint history per checkpoint namespace, so getTuple, list (time-travel), parent lineage, and putWrites (pending writes) all work.
  • check_circleNo Rekall backend changes — it's a pure client of the existing POST /api/v1/execution-memory/external/save and GET …/external/load endpoints.

Authentication

Pass apiKey (rk_…) or accessToken (rat_…) — sent as Authorization: Bearer. For local dev against a server using header auth, pass headers instead:

dev auth
const checkpointer = RekallSaver.fromApi({
apiUrl: 'http://localhost:9876',
headers: { 'x-user-id': 'dev-user' },
});

Advanced

Inject any store (e.g. for tests). The store must implement load(key) / save(key, blob) / delete(key):

custom store
import { RekallSaver, InMemoryCheckpointStateStore } from '@rekall/langgraph';
const saver = new RekallSaver(new InMemoryCheckpointStateStore());

Notes

Single-runner-per-thread

Persistence is read-modify-write on the per-thread blob; ideal for the common single-runner-per-thread pattern. For high-concurrency writes to one thread, front it with your own locking.

Next Steps

Rekall
rekall