mirror of
https://github.com/langchain-ai/langgraph.git
synced 2026-08-22 23:52:23 +02:00
## Summary Add a user-facing design doc and `get_delta_channel_keepset` helper for third-party `BaseCheckpointSaver` authors who need to support graphs using `DeltaChannel`. **Deliverables:** 1. ~~**`docs/delta-channel-checkpointer-guide.md`** — comprehensive guide covering~~: moved to docs repo 2. **`BaseCheckpointSaver.get_delta_channel_keepset` / `aget_delta_channel_keepset`** — returns the minimum set of ancestor `checkpoint_id`s that must survive deletion for a given head's `DeltaChannel` reconstruction to remain intact. Enables safe `prune` implementations without silently corrupting delta history. 3. **Docstring warnings** on `prune`, `aprune`, `delete_for_runs`, `adelete_for_runs`, `copy_thread`, `acopy_thread` explaining the DeltaChannel pitfall (silent data loss if ancestor writes/snapshots are deleted). 4. **Three new conformance capabilities** in `libs/checkpoint-conformance`: - `delta_channel_history` — validates the `aget_delta_channel_history` walk contract - `delta_channel_keepset` — validates the keep-set contract - `delta_channel_reconstruction` — end-to-end round-trip (aput + aput_writes + history + reconstruct) ## Test plan - [x] `make format lint` passes in `libs/checkpoint`, `libs/checkpoint-conformance` - [x] All three new conformance capabilities pass against `InMemorySaver` - [x] Run conformance against SQLite saver - [x] Run conformance against Postgres saver --------- Co-authored-by: Cursor <cursoragent@cursor.com>
LangGraph SQLite Checkpoint
Implementation of LangGraph CheckpointSaver that uses SQLite DB (both sync and async, via aiosqlite)
Security
Important
Set
LANGGRAPH_STRICT_MSGPACK=trueor pass an explicitallowed_msgpack_moduleslist when creating your checkpointer. This restricts checkpoint deserialization to known-safe types, preventing code execution if the database is compromised. See the langgraph-checkpoint README for details.
Usage
from langgraph.checkpoint.sqlite import SqliteSaver
write_config = {"configurable": {"thread_id": "1", "checkpoint_ns": ""}}
read_config = {"configurable": {"thread_id": "1"}}
with SqliteSaver.from_conn_string(":memory:") as checkpointer:
checkpoint = {
"v": 4,
"ts": "2024-07-31T20:14:19.804150+00:00",
"id": "1ef4f797-8335-6428-8001-8a1503f9b875",
"channel_values": {
"my_key": "meow",
"node": "node"
},
"channel_versions": {
"__start__": 2,
"my_key": 3,
"start:node": 3,
"node": 3
},
"versions_seen": {
"__input__": {},
"__start__": {
"__start__": 1
},
"node": {
"start:node": 2
}
},
}
# store checkpoint
checkpointer.put(write_config, checkpoint, {}, {})
# load checkpoint
checkpointer.get(read_config)
# list checkpoints
list(checkpointer.list(read_config))
Async
from langgraph.checkpoint.sqlite.aio import AsyncSqliteSaver
async with AsyncSqliteSaver.from_conn_string(":memory:") as checkpointer:
checkpoint = {
"v": 4,
"ts": "2024-07-31T20:14:19.804150+00:00",
"id": "1ef4f797-8335-6428-8001-8a1503f9b875",
"channel_values": {
"my_key": "meow",
"node": "node"
},
"channel_versions": {
"__start__": 2,
"my_key": 3,
"start:node": 3,
"node": 3
},
"versions_seen": {
"__input__": {},
"__start__": {
"__start__": 1
},
"node": {
"start:node": 2
}
},
}
# store checkpoint
await checkpointer.aput(write_config, checkpoint, {}, {})
# load checkpoint
await checkpointer.aget(read_config)
# list checkpoints
[c async for c in checkpointer.alist(read_config)]