Skip to content

feat(sqlserver): add SQLServerSaver LangGraph checkpoint saver#630

Open
DevNinja (0xDevNinja) wants to merge 1 commit into
langchain-ai:mainfrom
0xDevNinja:feat/sqlserver-langgraph-checkpoint
Open

feat(sqlserver): add SQLServerSaver LangGraph checkpoint saver#630
DevNinja (0xDevNinja) wants to merge 1 commit into
langchain-ai:mainfrom
0xDevNinja:feat/sqlserver-langgraph-checkpoint

Conversation

@0xDevNinja

Copy link
Copy Markdown

Summary

Adds SQLServerSaver, an implementation of langgraph.checkpoint.base.BaseCheckpointSaver backed by a SQL Server / Azure SQL database. This is the LangGraph-persistence integration tracked in #15.

Modeled after langgraph.checkpoint.sqlite.SqliteSaver so behavior is consistent with the other first-party savers, adapted for SQL Server:

  • SQLAlchemy + pyodbc transport (sync), same connection-string conventions as SQLServer_VectorStore including Entra ID authentication.
  • MERGE INTO ... WHEN MATCHED THEN UPDATE ... WHEN NOT MATCHED THEN INSERT for the put upsert.
  • IF NOT EXISTS (...) INSERT for the put_writes insert-or-ignore path used for non-WRITES_IDX_MAP channels.
  • TOP N instead of LIMIT N for list(..., limit=...).
  • JSON_VALUE(metadata, '$.key') for the metadata filter= argument.
  • An internal threading.Lock guards every session so concurrent graph runs in the same process cannot interleave statements on the underlying engine — mirrors SqliteSaver's safety semantics.

Closes #15

Public API

from langchain_sqlserver import SQLServerSaver

saver = SQLServerSaver(
    connection_string="Driver={ODBC Driver 18 for SQL Server};Server=tcp:host,1433;Database=mydb;Uid=user;Pwd=pwd;TrustServerCertificate=yes;",
)
graph = builder.compile(checkpointer=saver)
config = {"configurable": {"thread_id": "user-1"}}
graph.invoke({...}, config)

Implements get_tuple / list / put / put_writes / delete_thread, plus a lazy setup() for table creation. Tables (checkpoints, checkpoint_writes) are configurable via checkpoints_table / writes_table and db_schema.

Files

  • langchain_sqlserver/checkpoint.py — new module with SQLServerSaver.
  • langchain_sqlserver/__init__.py — export the new class.
  • pyproject.toml + uv.lock — add langgraph-checkpoint>=2.0,<4.0 to project dependencies.
  • tests/unit_tests/test_checkpoint.py — 8 unit tests covering construction validation, qualified-name building (schema / no-schema / overrides), Entra-ID-vs-uid/pwd routing, the empty-input fast path on put_writes, and SQL-injection guard on the metadata filter. No live DB required.
  • tests/unit_tests/test_imports.py — extend the __all__ snapshot.
  • tests/integration_tests/test_checkpoint.py — 6 integration tests covering: put + get_tuple round-trip, latest-checkpoint lookup, descending list with limit, before= slicing, put_writes retrievability through get_tuple.pending_writes, and scoped delete_thread. Uses the existing TEST_AZURESQLSERVER_TRUSTED_CONNECTION / TEST_PYODBC_CONNECTION_STRING env vars.

Test plan

  • ruff check langchain_sqlserver tests — clean
  • mypy langchain_sqlserver tests — clean (14 source files)
  • pytest tests/unit_tests/ — 9 passed (8 new + import snapshot), 1 module skipped (pre-existing)
  • pytest tests/integration_tests/test_checkpoint.py against a live SQL Server / Azure SQL instance.

Notes

  • Connection-string parsing and Entra-ID token-provider helpers mirror those on SQLServer_VectorStore so users get identical auth semantics across vector store, chat history, and checkpoint saver. A follow-up to factor these into a shared internal module is reasonable, but kept out of this PR so it stays additive.
  • poetry.lock is intentionally left in tree as-is — uv.lock is the canonical lockfile updated for the new dependency; happy to refresh poetry.lock if maintainers prefer.

Adds `SQLServerSaver`, an implementation of
`langgraph.checkpoint.base.BaseCheckpointSaver` backed by a SQL Server /
Azure SQL database. Modeled after `langgraph.checkpoint.sqlite.SqliteSaver`
so semantics match the other first-party savers, but adapted for SQL
Server: SQLAlchemy + pyodbc transport, `MERGE` for upsert,
`IF NOT EXISTS` for insert-or-ignore on writes, `TOP N` for `LIMIT`, and
`JSON_VALUE` for metadata filters.

The saver supports the same connection-string conventions as
`SQLServer_VectorStore`, including Entra ID authentication when the
connection string carries no credentials.

Adds `langgraph-checkpoint>=2.0,<4.0` as a project dependency and exports
`SQLServerSaver` from `langchain_sqlserver`.

Closes langchain-ai#15
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[langchain-sqlserver] Add support for storing chat history using LangGraph

1 participant