Files
langgraph/libs/checkpoint-postgres
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
97249656b2 chore(deps): bump the minor-and-patch group in /libs/checkpoint-postgres with 3 updates (#7371)
Bumps the minor-and-patch group in /libs/checkpoint-postgres with 3
updates: [orjson](https://github.com/ijl/orjson),
[ruff](https://github.com/astral-sh/ruff) and
[mypy](https://github.com/python/mypy).

Updates `orjson` from 3.11.7 to 3.11.8
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/ijl/orjson/releases">orjson's
releases</a>.</em></p>
<blockquote>
<h2>3.11.8</h2>
<h3>Changed</h3>
<ul>
<li>Build and compatibility improvements.</li>
</ul>
</blockquote>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/ijl/orjson/blob/master/CHANGELOG.md">orjson's
changelog</a>.</em></p>
<blockquote>
<h2>3.11.8 - 2026-03-31</h2>
<h3>Changed</h3>
<ul>
<li>Build and compatibility improvements.</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/ijl/orjson/commit/5cbb3d0398a2f42de51210270286fecd798c5d78"><code>5cbb3d0</code></a>
3.11.8</li>
<li><a
href="https://github.com/ijl/orjson/commit/4195d7f263e33076295b75efdcbaf6a55af8674e"><code>4195d7f</code></a>
writer::half</li>
<li><a
href="https://github.com/ijl/orjson/commit/d00641b69410728a735f0855eb1c2843b0a5819b"><code>d00641b</code></a>
writer::uuid</li>
<li><a
href="https://github.com/ijl/orjson/commit/c84d9b4ba4853781af943fa5c493e261e2f82b84"><code>c84d9b4</code></a>
build and compatibility misc</li>
<li><a
href="https://github.com/ijl/orjson/commit/4547234b681fac5e0e0734cf44c21e75f9654e43"><code>4547234</code></a>
ffi::numpy</li>
<li><a
href="https://github.com/ijl/orjson/commit/0d4a5ad1f17a72528ba027554466fdec6580cdeb"><code>0d4a5ad</code></a>
datetime PyRef idiom</li>
<li><a
href="https://github.com/ijl/orjson/commit/e93a13d372ec956d027e71d023eb534b8445ac85"><code>e93a13d</code></a>
Cross-compile avoids maturin v1.12 build-details.json error</li>
<li>See full diff in <a
href="https://github.com/ijl/orjson/compare/3.11.7...3.11.8">compare
view</a></li>
</ul>
</details>
<br />

Updates `ruff` from 0.15.7 to 0.15.8
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/astral-sh/ruff/releases">ruff's
releases</a>.</em></p>
<blockquote>
<h2>0.15.8</h2>
<h2>Release Notes</h2>
<p>Released on 2026-03-26.</p>
<h3>Preview features</h3>
<ul>
<li>[<code>ruff</code>] New rule <code>unnecessary-if</code>
(<code>RUF050</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/24114">#24114</a>)</li>
<li>[<code>ruff</code>] New rule <code>useless-finally</code>
(<code>RUF072</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/24165">#24165</a>)</li>
<li>[<code>ruff</code>] New rule <code>f-string-percent-format</code>
(<code>RUF073</code>): warn when using <code>%</code> operator on an
f-string (<a
href="https://redirect.github.com/astral-sh/ruff/pull/24162">#24162</a>)</li>
<li>[<code>pyflakes</code>] Recognize <code>frozendict</code> as a
builtin for Python 3.15+ (<a
href="https://redirect.github.com/astral-sh/ruff/pull/24100">#24100</a>)</li>
</ul>
<h3>Bug fixes</h3>
<ul>
<li>[<code>flake8-async</code>] Use fully-qualified
<code>anyio.lowlevel</code> import in autofix (<code>ASYNC115</code>)
(<a
href="https://redirect.github.com/astral-sh/ruff/pull/24166">#24166</a>)</li>
<li>[<code>flake8-bandit</code>] Check tuple arguments for partial paths
in <code>S607</code> (<a
href="https://redirect.github.com/astral-sh/ruff/pull/24080">#24080</a>)</li>
<li>[<code>pyflakes</code>] Skip <code>undefined-name</code>
(<code>F821</code>) for conditionally deleted variables (<a
href="https://redirect.github.com/astral-sh/ruff/pull/24088">#24088</a>)</li>
<li><code>E501</code>/<code>W505</code>/formatter: Exclude nested pragma
comments from line width calculation (<a
href="https://redirect.github.com/astral-sh/ruff/pull/24071">#24071</a>)</li>
<li>Fix <code>%foo?</code> parsing in IPython assignment expressions (<a
href="https://redirect.github.com/astral-sh/ruff/pull/24152">#24152</a>)</li>
<li><code>analyze graph</code>: resolve string imports that reference
attributes, not just modules (<a
href="https://redirect.github.com/astral-sh/ruff/pull/24058">#24058</a>)</li>
</ul>
<h3>Rule changes</h3>
<ul>
<li>[<code>eradicate</code>] ignore <code>ty: ignore</code> comments in
<code>ERA001</code> (<a
href="https://redirect.github.com/astral-sh/ruff/pull/24192">#24192</a>)</li>
<li>[<code>flake8-bandit</code>] Treat <code>sys.executable</code> as
trusted input in <code>S603</code> (<a
href="https://redirect.github.com/astral-sh/ruff/pull/24106">#24106</a>)</li>
<li>[<code>flake8-self</code>] Recognize <code>Self</code> annotation
and <code>self</code> assignment in <code>SLF001</code> (<a
href="https://redirect.github.com/astral-sh/ruff/pull/24144">#24144</a>)</li>
<li>[<code>pyflakes</code>] <code>F507</code>: Fix false negative for
non-tuple RHS in <code>%</code>-formatting (<a
href="https://redirect.github.com/astral-sh/ruff/pull/24142">#24142</a>)</li>
<li>[<code>refurb</code>] Parenthesize generator arguments in
<code>FURB142</code> fixer (<a
href="https://redirect.github.com/astral-sh/ruff/pull/24200">#24200</a>)</li>
</ul>
<h3>Performance</h3>
<ul>
<li>Speed up diagnostic rendering (<a
href="https://redirect.github.com/astral-sh/ruff/pull/24146">#24146</a>)</li>
</ul>
<h3>Server</h3>
<ul>
<li>Warn when Markdown files are skipped due to preview being disabled
(<a
href="https://redirect.github.com/astral-sh/ruff/pull/24150">#24150</a>)</li>
</ul>
<h3>Documentation</h3>
<ul>
<li>Clarify <code>extend-ignore</code> and <code>extend-select</code>
settings documentation (<a
href="https://redirect.github.com/astral-sh/ruff/pull/24064">#24064</a>)</li>
<li>Mention AI policy in PR template (<a
href="https://redirect.github.com/astral-sh/ruff/pull/24198">#24198</a>)</li>
</ul>
<h3>Other changes</h3>
<ul>
<li>Use trusted publishing for NPM packages (<a
href="https://redirect.github.com/astral-sh/ruff/pull/24171">#24171</a>)</li>
</ul>
<h3>Contributors</h3>
<ul>
<li><a href="https://github.com/bitloi"><code>@​bitloi</code></a></li>
<li><a href="https://github.com/Sim-hu"><code>@​Sim-hu</code></a></li>
</ul>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/astral-sh/ruff/blob/main/CHANGELOG.md">ruff's
changelog</a>.</em></p>
<blockquote>
<h2>0.15.8</h2>
<p>Released on 2026-03-26.</p>
<h3>Preview features</h3>
<ul>
<li>[<code>ruff</code>] New rule <code>unnecessary-if</code>
(<code>RUF050</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/24114">#24114</a>)</li>
<li>[<code>ruff</code>] New rule <code>useless-finally</code>
(<code>RUF072</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/24165">#24165</a>)</li>
<li>[<code>ruff</code>] New rule <code>f-string-percent-format</code>
(<code>RUF073</code>): warn when using <code>%</code> operator on an
f-string (<a
href="https://redirect.github.com/astral-sh/ruff/pull/24162">#24162</a>)</li>
<li>[<code>pyflakes</code>] Recognize <code>frozendict</code> as a
builtin for Python 3.15+ (<a
href="https://redirect.github.com/astral-sh/ruff/pull/24100">#24100</a>)</li>
</ul>
<h3>Bug fixes</h3>
<ul>
<li>[<code>flake8-async</code>] Use fully-qualified
<code>anyio.lowlevel</code> import in autofix (<code>ASYNC115</code>)
(<a
href="https://redirect.github.com/astral-sh/ruff/pull/24166">#24166</a>)</li>
<li>[<code>flake8-bandit</code>] Check tuple arguments for partial paths
in <code>S607</code> (<a
href="https://redirect.github.com/astral-sh/ruff/pull/24080">#24080</a>)</li>
<li>[<code>pyflakes</code>] Skip <code>undefined-name</code>
(<code>F821</code>) for conditionally deleted variables (<a
href="https://redirect.github.com/astral-sh/ruff/pull/24088">#24088</a>)</li>
<li><code>E501</code>/<code>W505</code>/formatter: Exclude nested pragma
comments from line width calculation (<a
href="https://redirect.github.com/astral-sh/ruff/pull/24071">#24071</a>)</li>
<li>Fix <code>%foo?</code> parsing in IPython assignment expressions (<a
href="https://redirect.github.com/astral-sh/ruff/pull/24152">#24152</a>)</li>
<li><code>analyze graph</code>: resolve string imports that reference
attributes, not just modules (<a
href="https://redirect.github.com/astral-sh/ruff/pull/24058">#24058</a>)</li>
</ul>
<h3>Rule changes</h3>
<ul>
<li>[<code>eradicate</code>] ignore <code>ty: ignore</code> comments in
<code>ERA001</code> (<a
href="https://redirect.github.com/astral-sh/ruff/pull/24192">#24192</a>)</li>
<li>[<code>flake8-bandit</code>] Treat <code>sys.executable</code> as
trusted input in <code>S603</code> (<a
href="https://redirect.github.com/astral-sh/ruff/pull/24106">#24106</a>)</li>
<li>[<code>flake8-self</code>] Recognize <code>Self</code> annotation
and <code>self</code> assignment in <code>SLF001</code> (<a
href="https://redirect.github.com/astral-sh/ruff/pull/24144">#24144</a>)</li>
<li>[<code>pyflakes</code>] <code>F507</code>: Fix false negative for
non-tuple RHS in <code>%</code>-formatting (<a
href="https://redirect.github.com/astral-sh/ruff/pull/24142">#24142</a>)</li>
<li>[<code>refurb</code>] Parenthesize generator arguments in
<code>FURB142</code> fixer (<a
href="https://redirect.github.com/astral-sh/ruff/pull/24200">#24200</a>)</li>
</ul>
<h3>Performance</h3>
<ul>
<li>Speed up diagnostic rendering (<a
href="https://redirect.github.com/astral-sh/ruff/pull/24146">#24146</a>)</li>
</ul>
<h3>Server</h3>
<ul>
<li>Warn when Markdown files are skipped due to preview being disabled
(<a
href="https://redirect.github.com/astral-sh/ruff/pull/24150">#24150</a>)</li>
</ul>
<h3>Documentation</h3>
<ul>
<li>Clarify <code>extend-ignore</code> and <code>extend-select</code>
settings documentation (<a
href="https://redirect.github.com/astral-sh/ruff/pull/24064">#24064</a>)</li>
<li>Mention AI policy in PR template (<a
href="https://redirect.github.com/astral-sh/ruff/pull/24198">#24198</a>)</li>
</ul>
<h3>Other changes</h3>
<ul>
<li>Use trusted publishing for NPM packages (<a
href="https://redirect.github.com/astral-sh/ruff/pull/24171">#24171</a>)</li>
</ul>
<h3>Contributors</h3>
<ul>
<li><a href="https://github.com/bitloi"><code>@​bitloi</code></a></li>
<li><a href="https://github.com/Sim-hu"><code>@​Sim-hu</code></a></li>
<li><a
href="https://github.com/mvanhorn"><code>@​mvanhorn</code></a></li>
</ul>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/astral-sh/ruff/commit/c2a8815842f9dc5d24ec19385eae0f1a7188b0d9"><code>c2a8815</code></a>
Release 0.15.8 (<a
href="https://redirect.github.com/astral-sh/ruff/issues/24217">#24217</a>)</li>
<li><a
href="https://github.com/astral-sh/ruff/commit/d444d52e2b9cc8bc9a078c2bd4ff6ff993290209"><code>d444d52</code></a>
[ty] Infer lambda expressions with <code>Callable</code> type context
(<a
href="https://redirect.github.com/astral-sh/ruff/issues/22633">#22633</a>)</li>
<li><a
href="https://github.com/astral-sh/ruff/commit/9622285ed0081fc688149f6efca87f127d9b18dd"><code>9622285</code></a>
[ty] Autocomplete arguments if in arguments node (<a
href="https://redirect.github.com/astral-sh/ruff/issues/24167">#24167</a>)</li>
<li><a
href="https://github.com/astral-sh/ruff/commit/d81266252aaf0820346d55edbed79c4f25ba13d2"><code>d812662</code></a>
Use the <code>release</code> environment in <code>publish-docs</code>
(<a
href="https://redirect.github.com/astral-sh/ruff/issues/24214">#24214</a>)</li>
<li><a
href="https://github.com/astral-sh/ruff/commit/eda2355832f7a9c58aef6febd3e061dc9c87509a"><code>eda2355</code></a>
[ty] Show <code>Final</code> source in final assignment diagnostic (<a
href="https://redirect.github.com/astral-sh/ruff/issues/24194">#24194</a>)</li>
<li><a
href="https://github.com/astral-sh/ruff/commit/929eb5238c82bfadad4549ff526f02efc0163dd0"><code>929eb52</code></a>
[ty] Enforce Final attribute assignment rules for annotated and
augmented wri...</li>
<li><a
href="https://github.com/astral-sh/ruff/commit/34998be22ec3a77d398bbd55234ef8740f768329"><code>34998be</code></a>
[ty] Fix typo in comment (<a
href="https://redirect.github.com/astral-sh/ruff/issues/24211">#24211</a>)</li>
<li><a
href="https://github.com/astral-sh/ruff/commit/560aca0b2828ee2ff1b4bcc5c5ef1ef4ced229d2"><code>560aca0</code></a>
[ty] Minor simplifications to some benchmark code (<a
href="https://redirect.github.com/astral-sh/ruff/issues/24209">#24209</a>)</li>
<li><a
href="https://github.com/astral-sh/ruff/commit/683bae512d03d3727a7bcdbc5a0170dafa049583"><code>683bae5</code></a>
[ty] Track non-terminal-call constraints in global scope (<a
href="https://redirect.github.com/astral-sh/ruff/issues/23245">#23245</a>)</li>
<li><a
href="https://github.com/astral-sh/ruff/commit/4704c2a4ff3dde2fd29324346720e9516b4fe387"><code>4704c2a</code></a>
[ty] Remove unnecessary intermediate collection in
`StaticClassLiteral::field...</li>
<li>Additional commits viewable in <a
href="https://github.com/astral-sh/ruff/compare/0.15.7...0.15.8">compare
view</a></li>
</ul>
</details>
<br />

Updates `mypy` from 1.19.1 to 1.20.0
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/python/mypy/blob/master/CHANGELOG.md">mypy's
changelog</a>.</em></p>
<blockquote>
<h1>Mypy Release Notes</h1>
<h2>Next Release</h2>
<h2>Mypy 1.20</h2>
<p>We’ve just uploaded mypy 1.20.0 to the Python Package Index (<a
href="https://pypi.org/project/mypy/">PyPI</a>).
Mypy is a static type checker for Python. This release includes new
features, performance
improvements and bug fixes. You can install it as follows:</p>
<pre><code>python3 -m pip install -U mypy
</code></pre>
<p>You can read the full documentation for this release on <a
href="http://mypy.readthedocs.io">Read the Docs</a>.</p>
<h3>Planned Changes to Defaults and Flags in Mypy 2.0</h3>
<p>As a reminder, we are planning to enable
<code>--local-partial-types</code> by default in mypy 2.0, which
will likely be the next feature release. This will often require at
least minor code changes. This
option is implicitly enabled by mypy daemon, so this makes the behavior
of daemon and non-daemon
modes consistent.</p>
<p>Note that this release improves the compatibility of
<code>--local-partial-types</code> significantly to
make the switch easier (see below for more).</p>
<p>This can also be configured in a mypy configuration file (use
<code>False</code> to disable):</p>
<pre><code>local_partial_types = True
</code></pre>
<p>For more information, refer to the
<a
href="https://mypy.readthedocs.io/en/stable/command_line.html#cmdoption-mypy-local-partial-types">documentation</a>.</p>
<p>We will also enable <code>--strict-bytes</code> by default in mypy
2.0. This usually requires at most
minor code changes to adopt. For more information, refer to the
<a
href="https://mypy.readthedocs.io/en/stable/command_line.html#cmdoption-mypy-strict-bytes">documentation</a>.</p>
<p>Finally, <code>--allow-redefinition-new</code> will be renamed to
<code>--allow-redefinition</code>. If you want
to continue using the older <code>--allow-redefinition</code> semantics
which are less flexible (e.g.
limited support for conditional redefinitions), you can switch to
<code>--allow-redefinition-old</code>,
which is currently supported as an alias to the legacy
<code>--allow-redefinition</code> behavior.
To use <code>--allow-redefinition</code> in the upcoming mypy 2.0, you
can't use <code>--no-local-partial-types</code>.
For more information, refer to the
<a
href="https://mypy.readthedocs.io/en/stable/command_line.html#cmdoption-mypy-allow-redefinition-new">documentation</a>.</p>
<h3>Better Type Narrowing</h3>
<p>Mypy's implementation of narrowing has been substantially reworked.
Mypy will now narrow more
aggressively, more consistently, and more correctly. In particular, you
are likely to notice new
narrowing behavior in equality expressions (<code>==</code>),
containment expressions (<code>in</code>),</p>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/python/mypy/commit/770d3ca4997032dc3a1c4f0b468e9f58e8f38505"><code>770d3ca</code></a>
Remove +dev from version</li>
<li><a
href="https://github.com/python/mypy/commit/4738ffafc56a0d175cba06e893ffa62e756fc7e0"><code>4738ffa</code></a>
Changelog updates for 1.20 (<a
href="https://redirect.github.com/python/mypy/issues/21109">#21109</a>)</li>
<li><a
href="https://github.com/python/mypy/commit/b4f07a717c3a239a9c77808c5550fff5f2638c96"><code>b4f07a7</code></a>
Use 'native-parser' instead of 'native-parse' for optional dependency
(<a
href="https://redirect.github.com/python/mypy/issues/21115">#21115</a>)</li>
<li><a
href="https://github.com/python/mypy/commit/7bec7b7f791790b1c925cdcc573ced564fbbf065"><code>7bec7b7</code></a>
[mypyc] Document librt and librt.base64 (<a
href="https://redirect.github.com/python/mypy/issues/21114">#21114</a>)</li>
<li><a
href="https://github.com/python/mypy/commit/c4825969450385cf3eb91a4fc02f273b369bc301"><code>c482596</code></a>
--allow-redefinition-new is no longer experimental (<a
href="https://redirect.github.com/python/mypy/issues/21110">#21110</a>)</li>
<li><a
href="https://github.com/python/mypy/commit/c916ca3fa79d9324dcbe130b18e24e2b5e2d1eb5"><code>c916ca3</code></a>
sdist: include <code>misc/{diff-cache,apply-cache-diff}.py</code> for
`mypy/test/test_di...</li>
<li><a
href="https://github.com/python/mypy/commit/b137e4ed41d6178f6dbd0e609db56b8c1ad5384a"><code>b137e4e</code></a>
[mypyc] Speed up native-to-native imports within the same group (<a
href="https://redirect.github.com/python/mypy/issues/21101">#21101</a>)</li>
<li><a
href="https://github.com/python/mypy/commit/978b711c21adadf5dae4db80127ddf270d79af5f"><code>978b711</code></a>
[mypyc] Fix range loop variable off-by-one after loop exit (<a
href="https://redirect.github.com/python/mypy/issues/21098">#21098</a>)</li>
<li><a
href="https://github.com/python/mypy/commit/67ada30918d1a32e1935e9ac468113e0aa002b79"><code>67ada30</code></a>
[stubtest] Check runtime availability of private types not marked
`@type_chec...</li>
<li><a
href="https://github.com/python/mypy/commit/bdef6ef8734af07cab1bf0acadc1d8ab9add93c3"><code>bdef6ef</code></a>
librt cache tests: build respecting MYPY_TEST_PREFIX (<a
href="https://redirect.github.com/python/mypy/issues/21097">#21097</a>)</li>
<li>Additional commits viewable in <a
href="https://github.com/python/mypy/compare/v1.19.1...v1.20.0">compare
view</a></li>
</ul>
</details>
<br />


Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore <dependency name> major version` will close this
group update PR and stop Dependabot creating any more for the specific
dependency's major version (unless you unignore this specific
dependency's major version or upgrade to it yourself)
- `@dependabot ignore <dependency name> minor version` will close this
group update PR and stop Dependabot creating any more for the specific
dependency's minor version (unless you unignore this specific
dependency's minor version or upgrade to it yourself)
- `@dependabot ignore <dependency name>` will close this group update PR
and stop Dependabot creating any more for the specific dependency
(unless you unignore this specific dependency or upgrade to it yourself)
- `@dependabot unignore <dependency name>` will remove all of the ignore
conditions of the specified dependency
- `@dependabot unignore <dependency name> <ignore condition>` will
remove the ignore condition of the specified dependency and ignore
conditions


</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-04-03 19:07:10 -07:00
..
2026-03-18 13:31:46 -07:00
2026-03-18 13:31:46 -07:00

LangGraph Checkpoint Postgres

Implementation of LangGraph CheckpointSaver that uses Postgres.

Dependencies

By default langgraph-checkpoint-postgres installs psycopg (Psycopg 3) without any extras. However, you can choose a specific installation that best suits your needs here (for example, psycopg[binary]).

Usage

Important

When using Postgres checkpointers for the first time, make sure to call .setup() method on them to create required tables. See example below.

Important

When manually creating Postgres connections and passing them to PostgresSaver or AsyncPostgresSaver, make sure to include autocommit=True and row_factory=dict_row (from psycopg.rows import dict_row). See a full example in this how-to guide.

Why these parameters are required:

  • autocommit=True: Required for the .setup() method to properly commit the checkpoint tables to the database. Without this, table creation may not be persisted.
  • row_factory=dict_row: Required because the PostgresSaver implementation accesses database rows using dictionary-style syntax (e.g., row["column_name"]). The default tuple_row factory returns tuples that only support index-based access (e.g., row[0]), which will cause TypeError exceptions when the checkpointer tries to access columns by name.

Example of incorrect usage:

# ❌ This will fail with TypeError during checkpointer operations
with psycopg.connect(DB_URI) as conn:  # Missing autocommit=True and row_factory=dict_row
    checkpointer = PostgresSaver(conn)
    checkpointer.setup()  # May not persist tables properly
    # Any operation that reads from database will fail with:
    # TypeError: tuple indices must be integers or slices, not str
from langgraph.checkpoint.postgres import PostgresSaver

write_config = {"configurable": {"thread_id": "1", "checkpoint_ns": ""}}
read_config = {"configurable": {"thread_id": "1"}}

DB_URI = "postgres://postgres:postgres@localhost:5432/postgres?sslmode=disable"
with PostgresSaver.from_conn_string(DB_URI) as checkpointer:
    # call .setup() the first time you're using the checkpointer
    checkpointer.setup()
    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.postgres.aio import AsyncPostgresSaver

async with AsyncPostgresSaver.from_conn_string(DB_URI) 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)]