Compare commits

...
717 Commits
Author SHA1 Message Date
William FHandGitHub a03cb0b16d CLI: Ensure correct api version is used (#4237)
Signed-off-by: William Fu-Hinthorn <13333726+hinthornw@users.noreply.github.com>
2025-04-10 15:56:07 +00:00
David DuongandGitHub 06e660a845 chore(docs,cli): remove python-only label for custom auth, add test for custom auth in CLI (#4233) 2025-04-10 16:02:12 +02:00
Tat Dat Duong 794dc1ae92 docs(api): add custom auth docs 2025-04-10 15:06:55 +02:00
Tat Dat Duong 6e7bfecbbc chore(docs,cli): remove python-only label for custom auth, add test for custom auth in CLI 2025-04-10 14:34:52 +02:00
fa080ea689 updates prereq banner (#4220)
<img width="796" alt="Screenshot 2025-04-09 at 1 20 14 PM"
src="https://github.com/user-attachments/assets/fe7409ed-c4cb-42d1-9e34-5adf4ca237e7"
/>

---------

Co-authored-by: Vadym Barda <vadim.barda@gmail.com>
2025-04-09 20:22:36 -04:00
David DuongandGitHub 9fb06fc5af feat(sdk-js): use event key instead of action, prevent retrying on HTTP 409 (#4223) 2025-04-10 01:54:54 +02:00
Tat Dat Duong 5debbb23ca feat(sdk-js): use event key instead of action, clean up interfaces 2025-04-10 01:52:44 +02:00
Nuno CamposandGitHub 7dcc760fd8 Validate other types in model_construct (#4200)
Resolves:
https://github.com/langchain-ai/langgraph/issues/4184
https://github.com/langchain-ai/langgraph/issues/4198 <- tested on
python 3.9 and 3.10
2025-04-09 15:58:11 -07:00
Vadym BardaandGitHub fdb9b9b8e0 checkpoint-postgres: add deprecation warning for ShallowPostgresSaver (#4219) 2025-04-09 11:31:33 -04:00
William FHandGitHub 2f51a15064 Update CLI (#4213) 2025-04-08 19:23:59 -07:00
Nuno CamposandGitHub d2acacfc8f Merge branch 'main' into wfh/_validate_more 2025-04-08 18:03:19 -07:00
Nuno CamposandGitHub 622a15b89e Remove pip from image (#4208)
After user installs, removes pip, setuptools, and wheel from the
resulting image.
2025-04-08 18:01:24 -07:00
Nuno CamposandGitHub bf50938de5 Update poetry version used in ci (#4212) 2025-04-08 18:00:28 -07:00
Nuno Campos d67a500cd9 Fix 2025-04-08 17:57:09 -07:00
Nuno Campos c6f5e561ec Update poetry version used in ci 2025-04-08 17:52:24 -07:00
William FHandGitHub 288fe12933 docs: Fix link (#4211) 2025-04-08 17:31:00 -07:00
William Fu-Hinthorn 5b58efc8d7 Update tests 2025-04-08 17:08:24 -07:00
David DuongandGitHub 2e1e582991 feat(sdk-js): add support for registering multiple events at once (#4209) 2025-04-09 01:58:49 +02:00
Tat Dat Duong 72260e64d5 Prevent casting 2025-04-09 01:57:50 +02:00
Tat Dat Duong 3193f5d063 feat(sdk-js): add support for registering multiple events at once 2025-04-09 01:56:32 +02:00
William Fu-Hinthorn 1b9093459c Remove pip from image
Signed-off-by: William Fu-Hinthorn <13333726+hinthornw@users.noreply.github.com>
2025-04-08 15:52:58 -07:00
Nuno Campos 392805938e 0.3.27 2025-04-08 15:04:46 -07:00
Nuno CamposandGitHub 4fb2aeacc7 Add checkpoint_during arg (#4169)
- This provides a new mode of execution where only the last checkpoint
is saved
- We save the last checkpoint no matter how the agent run is terminated
(success, error, interrupt, etc)
- This cuts down on cpu time spent on checkpointing, while not losing
any resilience benefits, given individual task writes are still saved
- If an error occurs and the run is retried, any tasks that completed
successfully before will be skipped (as currently)
- checkpoint_during=True is useful when you want to time-travel to inner
steps of a run
- The default value will remain the current behavior, ie.
checkpoint_during=True
2025-04-08 15:03:06 -07:00
David DuongandGitHub 8252668bcc release(sdk-js): 0.0.64 (#4207) 2025-04-08 23:46:23 +02:00
Tat Dat Duong 27e4b0fcfe release(sdk-js): 0.0.64 2025-04-08 23:45:03 +02:00
David DuongandGitHub ba388e25b3 feat(sdk-js): add auth types (#4199) 2025-04-08 23:44:33 +02:00
Nuno Campos 947a233fc5 Fix 2025-04-08 14:20:29 -07:00
Nuno Campos b76dc8ae0a Fix 2025-04-08 14:15:13 -07:00
Nuno Campos cbbfaba1fd Add comments 2025-04-08 14:07:08 -07:00
Nuno Campos e9aec77893 Add more tests 2025-04-08 14:07:02 -07:00
William FH 44691b69a3 Merge branch 'main' into wfh/_validate_more
Signed-off-by: William Fu-Hinthorn <13333726+hinthornw@users.noreply.github.com>
2025-04-08 13:57:37 -07:00
Nuno CamposandGitHub 067c4dd246 Implement simpler filtering of config keys in RemoteGraph (#4205) 2025-04-08 13:51:11 -07:00
Nuno Campos ccc21974e0 Implement simpler filtering of config keys in RemoteGraph 2025-04-08 13:44:31 -07:00
Nuno CamposandGitHub a6e66746f7 Make compatible with langchain-core 0.1 by conditionally importing _StreamingCallbackHandler (#4203) 2025-04-08 13:28:01 -07:00
Vadym BardaandGitHub 3a17df6106 langgraph: release 0.3.26 (#4204) 2025-04-08 14:53:10 -04:00
William Fu-Hinthorn 52c2837e42 Lint & handle arb types
Test on pydantic < 2

Signed-off-by: William Fu-Hinthorn <13333726+hinthornw@users.noreply.github.com>
2025-04-08 11:49:37 -07:00
Nuno Campos cee6a450dc Lint 2025-04-08 10:52:28 -07:00
Nuno Campos 0b3bf37a55 Fix the rest 2025-04-08 10:47:55 -07:00
Nuno CamposandGitHub 305a676675 langgraph: raise GraphInterrupt only if used as a subgraph (#4202) 2025-04-08 10:45:45 -07:00
Nuno Campos 5b73e38c38 Make compatible with langchain-core 0.1 by conditionally importing _StreamingCallbackHandler 2025-04-08 10:44:12 -07:00
vbarda 41fb5ec77c Revert "add warning"
This reverts commit cff349e22e.
2025-04-08 13:38:49 -04:00
vbarda cff349e22e add warning 2025-04-08 13:34:47 -04:00
vbarda 8f32fc4819 update tests 2025-04-08 13:28:35 -04:00
vbarda 5690555394 langgraph: raise GraphInterrupt only if used as a subgraph 2025-04-08 12:51:36 -04:00
William Fu-Hinthorn 933d6aa8f5 Validate types.
My be too slow though. V1 handling is ugly.
Signed-off-by: William Fu-Hinthorn <13333726+hinthornw@users.noreply.github.com>
2025-04-08 09:31:54 -07:00
Tat Dat Duong 7d5621a84f Default type for TExtra 2025-04-08 17:10:43 +02:00
Tat Dat Duong 5f1213a1c7 Remove extra 2025-04-08 17:07:04 +02:00
Tat Dat Duong a98f9542fa Add unused extra generic for future typing of metadata 2025-04-08 17:06:51 +02:00
William Fu-Hinthorn d2e854b04f Merge branch 'main' into wfh/_validate_more 2025-04-08 06:34:38 -07:00
William FHandGitHub c5b118a672 Add admonitions about managed checkpointers (#4197)
If you're deploying with langgraph API, you don't need to manually
define a checkpointer. For folks who already know they'll be developing
with the api server, I'd like to save everyone time by making this more
clear in the docs on checkpointing.
2025-04-08 12:16:24 +00:00
Tat Dat Duong aee39605e0 Add missing types 2025-04-08 14:13:59 +02:00
lc-arjunandGitHub 72bec9161a Release js sdk 0.0.63 (#4192) 2025-04-07 18:40:59 -07:00
Nuno CamposandGitHub ae17e77522 feat: add assistant description to js sdk (#4191) 2025-04-07 18:37:49 -07:00
Arjun Natarajan a96fc75c55 add assistant description to js sdk 2025-04-07 21:06:34 -04:00
Nuno Campos d541ed90d5 Save Sends unconditionally 2025-04-07 16:45:26 -07:00
William Fu-Hinthorn 7d7708fe42 Validate more 2025-04-07 11:29:32 -07:00
Tat Dat Duong c757247858 feat(sdk-js): add auth types 2025-04-07 20:29:14 +02:00
Nuno Campos 5a0228cb13 Add test 2025-04-04 16:00:28 -07:00
Nuno Campos 4abfc7702d Subgraphs inherit checkpoint mode 2025-04-04 16:00:22 -07:00
Nuno Campos a5495e84c8 Add another test 2025-04-04 15:42:11 -07:00
Nuno Campos 4f353dac31 Fix assignment of pending writes 2025-04-04 14:41:10 -07:00
Nuno CamposandGitHub 4c89bb39d4 Add benchmark script for typed dict version of existing wide state benchmark (#4174)
- to easily compare perf impact of using pydantic, data class, or typed
dict for same workload
2025-04-04 18:37:57 +00:00
Eugene YurtsevandGitHub 05a4fcc8bb cli: release 0.1.89 (#4173)
Release to pick up this: https://github.com/langchain-ai/langgraph/pull/4164
2025-04-04 13:46:47 -04:00
Nuno Campos 7ebd6f5e1f Better test 2025-04-04 10:01:35 -07:00
Eugene YurtsevandGitHub adac016e33 cli: support dict format for graph specification in langgraph.json (#4164)
Allow the CLI to work with dict format for the graph specification.

```json
{
  "dependencies": ["./my_agent"],
  "graphs": {
    "agent": {
      "path": "./my_agent/agent.py:graph",
      "description": "this is my agent description"
    }
  },
  "env": ".env"
}
```

And backwards compatible with:

```json
{
  "dependencies": ["./my_agent"],
  "graphs": {
    "agent": "./my_agent/agent.py:graph",
  },
  "env": ".env"
}
```
2025-04-04 10:16:20 -04:00
Nuno Campos 0a1dd7a01a Do same thing for writes 2025-04-03 17:31:34 -07:00
Nuno Campos 7e08339335 mypy is dumb 2025-04-03 16:55:23 -07:00
Nuno Campos e1d4b5552d Add checkpoint_during arg
- This provides a new mode of execution where only the last checkpoint is saved
- We save the last checkpoint no matter how the agent run is terminated (success, error, interrupt, etc)
- This cuts down on cpu time spent on checkpointing, while not losing any resilience benefits, given individual task writes are still saved
- If an error occurs and the run is retried, any tasks that completed successfully before will be skipped (as currently)
- checkpoint_during=True is useful when you want to time-travel to inner steps of a run
- The default value will remain the current behavior, ie. checkpoint_during=True
2025-04-03 16:51:53 -07:00
David DuongandGitHub 2d13904abf release(langgraph): 0.3.25 (#4167) 2025-04-03 22:20:03 +02:00
Tat Dat Duong dfeb9d3b46 release(langgraph): 0.3.25 2025-04-03 22:12:16 +02:00
David DuongandGitHub 81935a73d8 feat(langgraph): Add UI messages API (#4157)
Sample usage:

```python
from typing import Annotated, Sequence, TypedDict

from langchain_core.messages import BaseMessage
from langchain_openai import ChatOpenAI
from langgraph.graph import StateGraph
from langgraph.graph.message import add_messages

from langgraph.graph.ui import AnyUIMessage, ui_message_reducer, push_ui_message


class AgentState(TypedDict):  # noqa: D101
    messages: Annotated[Sequence[BaseMessage], add_messages]
    ui: Annotated[Sequence[AnyUIMessage], ui_message_reducer]


async def agent(state: AgentState):  # noqa: D103
    message = await ChatOpenAI(model="gpt-4o-mini", temperature=0).ainvoke(
        state["messages"]
    )

    # Also directly writes the message to `ui`
    push_ui_message("simple", {"hello": "123"}, message=message, state_key="ui")

    return {"messages": [message]}

```
2025-04-03 22:10:18 +02:00
Tat Dat Duong 615fc8b4ae Update naming 2025-04-03 21:58:16 +02:00
William FHandGitHub 13e6f6cbde Add algolia site verification (#4165) 2025-04-03 12:53:40 -07:00
Vadym BardaandGitHub e89633f30b prebuilt: release 0.1.8 (#4161) 2025-04-03 12:01:18 -04:00
Vadym BardaandGitHub 0bbf5829e8 docs: add a how-to guide for managing message history in create_react_agent (#4149) 2025-04-03 16:00:11 +00:00
David DuongandGitHub 7ed5288f8f release(cli): 0.1.84 (#4158) 2025-04-03 15:25:12 +02:00
Tat Dat Duong cba240e70e release(cli): 0.1.84 2025-04-03 15:15:52 +02:00
Tat Dat Duong e9b5046076 Update docs to include Python API 2025-04-03 14:39:45 +02:00
Tat Dat Duong af6552a17e Move to langgraph/graph 2025-04-03 14:13:26 +02:00
Tat Dat Duong e38c30a434 Other docstring changes 2025-04-03 14:13:26 +02:00
Tat Dat Duong e41dea4cf9 Remove unnecessary return value 2025-04-03 14:13:26 +02:00
Tat Dat Duong f9f8c19ec4 Update docstrings 2025-04-03 14:13:26 +02:00
Tat Dat Duong 64ab3217f6 Add UI messages API 2025-04-03 14:13:26 +02:00
David DuongandGitHub 9af243d138 feat(cli): pass ui and ui config to inmem server, handle Docker setup for UI (#4100) 2025-04-03 14:11:30 +02:00
David DuongandGitHub 3f1d440aee fix(sdk-js): send accepts any input (#4099) 2025-04-03 14:00:31 +02:00
Tat Dat Duong 78901599e6 Add test for UI config 2025-04-03 13:48:14 +02:00
Tat Dat Duong 958c0df2d7 Install Node.js runtime and run the build process to get the UI 2025-04-03 13:48:14 +02:00
Tat Dat Duong 6919de8b3e feat(cli): pass ui and ui config to inmem server 2025-04-03 13:48:14 +02:00
Nuno CamposandGitHub e9a66cef46 Update jinja2 dev dep (#4150) 2025-04-02 16:02:25 -07:00
Nuno CamposandGitHub 728679e48e Bump langchain-core from 0.3.0 to 0.3.15 in /libs/checkpoint-sqlite (#3978)
Bumps [langchain-core](https://github.com/langchain-ai/langchain) from
0.3.0 to 0.3.15.
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/langchain-ai/langchain/commit/25a103187137077d4331e7153fe119e1c0c3ffb6"><code>25a1031</code></a>
community: Fix a validation error for MoonshotChat (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/27801">#27801</a>)</li>
<li><a
href="https://github.com/langchain-ai/langchain/commit/e4e2aa0b78e6662bb5cebb06b15c19ddbe96ae43"><code>e4e2aa0</code></a>
core[patch]: update image util err msg (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/27803">#27803</a>)</li>
<li><a
href="https://github.com/langchain-ai/langchain/commit/181bcd05778ff08688ea22f8dab81a6bd27501fd"><code>181bcd0</code></a>
core[patch]: Release 0.3.15 (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/27802">#27802</a>)</li>
<li><a
href="https://github.com/langchain-ai/langchain/commit/c1e742347f9701aadba8920e4d1f79a636e50b68"><code>c1e7423</code></a>
core[patch]: rm image loading (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/27797">#27797</a>)</li>
<li><a
href="https://github.com/langchain-ai/langchain/commit/ad0387ac97e0c8feee4272f4ed98f0d65bd616ba"><code>ad0387a</code></a>
Improvement [docs] Improve api docs (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/27787">#27787</a>)</li>
<li><a
href="https://github.com/langchain-ai/langchain/commit/d9163e7afa0e5e975d36b7482c6a101e5c5dc375"><code>d9163e7</code></a>
community[docs]: Add content for the Lora adapter in the VLLM page. (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/27788">#27788</a>)</li>
<li><a
href="https://github.com/langchain-ai/langchain/commit/0172d938b4bf1e9da9f3b796dbfce64c565ce565"><code>0172d93</code></a>
community: add AzureOpenAIWhisperParser (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/27796">#27796</a>)</li>
<li><a
href="https://github.com/langchain-ai/langchain/commit/b631b0a5964bcdd46cf30fa0e91925d724ec7ae8"><code>b631b0a</code></a>
community[patch]: cap SQLAlchemy and update deps (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/27792">#27792</a>)</li>
<li><a
href="https://github.com/langchain-ai/langchain/commit/8ad7adad8784d01ad1cbbb8b4c5f8102dbf11a63"><code>8ad7ada</code></a>
infra: build api docs from package listing (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/27774">#27774</a>)</li>
<li><a
href="https://github.com/langchain-ai/langchain/commit/3952ee31b8fc95b1ed74b83429002a7b5da630a3"><code>3952ee3</code></a>
ollama: add pydocstyle linting for ollama (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/27686">#27686</a>)</li>
<li>Additional commits viewable in <a
href="https://github.com/langchain-ai/langchain/compare/langchain-core==0.3.0...langchain-core==0.3.15">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=langchain-core&package-manager=pip&previous-version=0.3.0&new-version=0.3.15)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

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 merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after
your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge
and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating
it. You can achieve the same result by closing it manually
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)
You can disable automated security fix PRs for this repo from the
[Security Alerts
page](https://github.com/langchain-ai/langgraph/network/alerts).

</details>
2025-04-02 15:57:14 -07:00
Nuno CamposandGitHub f90c81f280 Bump langchain-core from 0.2.38 to 0.2.43 in /libs/checkpoint (#3979)
Bumps [langchain-core](https://github.com/langchain-ai/langchain) from
0.2.38 to 0.2.43.
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/langchain-ai/langchain/commit/9fdeb74d9965258ad077d535681d9bae84b58e08"><code>9fdeb74</code></a>
core[patch]: Release 0.2.43 (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/27808">#27808</a>)</li>
<li><a
href="https://github.com/langchain-ai/langchain/commit/7d481f10102f43559cc57bcad7eba291067939ee"><code>7d481f1</code></a>
core[patch]: remove prompt img loading (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/27807">#27807</a>)</li>
<li><a
href="https://github.com/langchain-ai/langchain/commit/33a53970e1eb9a515d0d38809dd0d7f2e556c4ae"><code>33a5397</code></a>
infra: turn off release attestations (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/27766">#27766</a>)</li>
<li><a
href="https://github.com/langchain-ai/langchain/commit/283cb50ea69d03d082db5607b68f6d13aa4e65a1"><code>283cb50</code></a>
core[patch]: Release 0.2.42 (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/27763">#27763</a>)</li>
<li><a
href="https://github.com/langchain-ai/langchain/commit/5e3cee6c98a55d5303847c6f22256e0671caa83f"><code>5e3cee6</code></a>
core[patch]: make get_all_basemodel_annotations public (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/27762">#27762</a>)</li>
<li><a
href="https://github.com/langchain-ai/langchain/commit/807314661dbd8933d18a0289df05bd381ffbbc4f"><code>8073146</code></a>
Added mapping to fix CI for #langchain-aws:227. (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/27114">#27114</a>)</li>
<li><a
href="https://github.com/langchain-ai/langchain/commit/6cfd1e846a3f7369d33a77c3fb60314e3e60e202"><code>6cfd1e8</code></a>
core[patch]: Release 0.2.41 (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/26687">#26687</a>)</li>
<li><a
href="https://github.com/langchain-ai/langchain/commit/c5eca37262132b7b88d0f68835af5fea49d13494"><code>c5eca37</code></a>
core[patch]: Fixed bedrock chat model load. (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/26643">#26643</a>)</li>
<li><a
href="https://github.com/langchain-ai/langchain/commit/70c992bd61c48ebb4f60bde0ff9bfd7b54393678"><code>70c992b</code></a>
community: poetry lock for cffi dep (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/26674">#26674</a>)</li>
<li><a
href="https://github.com/langchain-ai/langchain/commit/51fd70be63afeaecf0eff78c2a6f6d3f34330203"><code>51fd70b</code></a>
infra: 0.2 release checkout ref for release note (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/26604">#26604</a>)</li>
<li>Additional commits viewable in <a
href="https://github.com/langchain-ai/langchain/compare/langchain-core==0.2.38...langchain-core==0.2.43">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=langchain-core&package-manager=pip&previous-version=0.2.38&new-version=0.2.43)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

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 merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after
your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge
and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating
it. You can achieve the same result by closing it manually
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)
You can disable automated security fix PRs for this repo from the
[Security Alerts
page](https://github.com/langchain-ai/langgraph/network/alerts).

</details>
2025-04-02 15:56:20 -07:00
Nuno Campos f118a61101 Update jinja2 dev dep 2025-04-02 15:56:00 -07:00
dependabot[bot]andNuno Campos 8963bb2b68 Bump langchain-core from 0.3.0 to 0.3.15 in /libs/checkpoint-sqlite
Bumps [langchain-core](https://github.com/langchain-ai/langchain) from 0.3.0 to 0.3.15.
- [Release notes](https://github.com/langchain-ai/langchain/releases)
- [Commits](https://github.com/langchain-ai/langchain/compare/langchain-core==0.3.0...langchain-core==0.3.15)

---
updated-dependencies:
- dependency-name: langchain-core
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-04-02 15:50:49 -07:00
dependabot[bot]andNuno Campos 499a1812e8 Bump langchain-core from 0.2.38 to 0.2.43 in /libs/checkpoint
Bumps [langchain-core](https://github.com/langchain-ai/langchain) from 0.2.38 to 0.2.43.
- [Release notes](https://github.com/langchain-ai/langchain/releases)
- [Commits](https://github.com/langchain-ai/langchain/compare/langchain-core==0.2.38...langchain-core==0.2.43)

---
updated-dependencies:
- dependency-name: langchain-core
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-04-02 15:49:49 -07:00
Nuno Campos 2cb81201b2 0.3.24 2025-04-02 15:45:06 -07:00
Nuno Campos 494cd4f6ad checkpoint 2.0.24 2025-04-02 15:44:58 -07:00
Nuno CamposandGitHub 9226b42150 Add checkpoint migrations for state graph internal channels (#4125) 2025-04-02 15:42:28 -07:00
Eugene YurtsevandGitHub 5e0a843423 sdk-py: release 0.1.61 (#4148) 2025-04-02 15:34:36 -07:00
6e54f74fa9 sdk-py: Add option to set description via client sdk (#4147)
Co-authored-by: William FH <13333726+hinthornw@users.noreply.github.com>
2025-04-02 21:26:14 +00:00
Nuno Campos ffb8400b19 Disable tests in 3.9 2025-04-02 14:05:15 -07:00
Nuno Campos b6b40149a9 Fix 2025-04-02 13:56:29 -07:00
Nuno Campos 5eecd2ac3a Update 2025-04-02 13:31:36 -07:00
Nuno Campos c38f7be89c Migrate quadratic channels too 2025-04-02 13:24:20 -07:00
Nuno Campos 2d406f03a2 Lint 2025-04-02 12:56:09 -07:00
Nuno Campos 1c48ec0aba Lint 2025-04-02 12:48:10 -07:00
Nuno Campos 4dda404da3 Implement checkpoint migration
- Migrate start:{node} channels to branch:to:{node}
- Migrate {node} channels to branch:to:{node}
2025-04-02 12:44:59 -07:00
Mahmut CAVDARandGitHub cce9801a8b docs: fixed indentation (#4078)
"Copy the clipboard" doesn't return valid Python code.
2025-04-02 13:44:45 -04:00
Vadym BardaandGitHub 67e8f8fc11 prebuilt: add optional pre-model hook that runs before calling LLM in create_react_agent (#4059)
Example:

```python
from typing import Any
from langchain_openai import ChatOpenAI
from langchain_community.tools.tavily_search import TavilySearchResults
from langchain_core.messages import AnyMessage
from langchain_core.messages.utils import count_tokens_approximately

from langgraph.graph import MessagesState
from langgraph.prebuilt.chat_agent_executor import create_react_agent, AgentState
from langgraph.checkpoint.memory import InMemorySaver

from langmem.short_term import SummarizationNode, RunningSummary


class State(MessagesState):
    context: dict[str, Any]

search = TavilySearchResults(max_results=3)
tools = [search]

model = ChatOpenAI(model="gpt-4o")
summarization_model = model.bind(max_tokens=256)

summarization_node = SummarizationNode(
    token_counter=count_tokens_approximately,
    model=summarization_model,
    max_tokens=2048,
    max_summary_tokens=256,
    output_messages_key="messages"
    # output_messages_key="llm_input_messages"
)

checkpointer = InMemorySaver()


class State(AgentState):
    user_language: str

    # summarization-related keys
    context: dict[str, Any]


def prompt(state):
    language = state["user_language"]
    system_msg = f"Always respond in {language}"
    return [{"role": "system", "content": system_msg}] + state["messages"]


graph = create_react_agent(
    model,
    tools,
    prompt=prompt,
    pre_model_hook=summarization_node,
    state_schema=State,
    checkpointer=checkpointer
)
```
2025-04-02 15:41:31 +00:00
RohitandGitHub 3a9247728b Fix missing colon in function definition in langchain-ai.github docum… (#4142)
…entation.

This commit fixes a syntax error in the "langchain-ai.github"
documentation. The function called "some_node_inside_alice" was missing
a colon (:) after the function, which is required for valid Python
syntax.
2025-04-02 08:04:22 -07:00
33766eb2ff docs: add missing MemorySaver import for unexpanded example (#4133)
Import `MemorySaver` for the code to run without expanding the example

---------

Co-authored-by: Eugene Yurtsev <eugene@langchain.dev>
2025-04-02 14:37:51 +00:00
Nuno CamposandNuno Campos 6fe319ed1b WIP: Add migrate_checkpoint 2025-04-02 07:24:55 -07:00
Andrew NguonlyandGitHub 3878addbe0 docs: Refactor content for new LangGraph Platform deployment options (#4118)
### Summary
This is a large refactor of the content for the LangGraph Platform
deployment options. Although there are a lot of changes, I do feel
fairly confident that this is safe to merge and won't have any negative
impact related to confusion around deployment options. However, please
review thoroughly (i.e. run the docs locally).

### Goals and Non-Goals
Just wanted to explicitly state goals and non-goals so that we're clear
about what needs to be done now versus what can be done in a smaller
follow-up PR.

Goals
1. Add new content for the new deployment options (Self-Hosted Data
Plane, Self-Hosted Control Plane).
1. Hide old content for deprecated deployment options (BYOC).
1. Create a pair of "conceptual" and "how-to" pages for each deployment
option. As much as possible, the pages should have consistent headings.
1. Introduce the terms "control plane" and "data plane" and define them
plainly without hiding/abstracting information.

Non-Goals
1. Do not change the navigation of the existing deployment options. As
much as possible, update content in-place or add new pages. Changing the
navigation is a bigger task that can be done later.
1. Do not remove old content for deprecated deployment options. We may
need to refer to this later. There are only ~2 pages (I think).

### Next Steps
1. Update the architecture diagrams for each deployment option. Commit
Excalidraw file to source control.
1. Create a "how-to" page for the Control Plane UI. This page pertains
to 3/4 deployment options. Most of the content lives in the "how-to"
page for Cloud SaaS deployment.
1. Document required RBAC permissions for K8s for Self-Hosted Data Plane
and Self-Hosted Control Plane (and update links).
1. Figure out how to consolidate plan information.
1. Figure out where to document licensing, telemetry, custom
Postgres/Redis.
1. Update autoscaling content.
2025-04-02 06:51:14 -07:00
Vadym BardaandGitHub 55f922cf2f langgraph: release 0.3.23 (#4141) 2025-04-02 09:50:18 -04:00
William FHandGitHub 9a5dc5d8f2 Update link (#4131) 2025-04-01 23:18:54 -07:00
William FHandGitHub 90b3da5959 TTL How-to (#4129)
Signed-off-by: William Fu-Hinthorn <13333726+hinthornw@users.noreply.github.com>
2025-04-01 22:54:31 -07:00
William FHandGitHub d2275a6727 Update cli.md to mention ttl (#4128)
Signed-off-by: William Fu-Hinthorn <13333726+hinthornw@users.noreply.github.com>
2025-04-01 22:21:55 -07:00
Nuno CamposandGitHub 0c590afb27 Maintain checkpoint LATEST_VERSION constant in langgraph lib (#4126)
- This should be controlled by the langgraph version, not the version of
langgraph-checkpoint installed
2025-04-01 21:53:12 -07:00
Nuno Campos 6efeefe424 Maintain checkpoint LATEST_VERSION constant in langgraph lib
- This should be controlled by the langgraph version, not the version of langgraph-checkpoint installed
2025-04-01 21:46:38 -07:00
William FHandGitHub da8b8c606a Release CLI (#4124)
Signed-off-by: William Fu-Hinthorn <13333726+hinthornw@users.noreply.github.com>
2025-04-01 21:28:58 -07:00
William FHandGitHub dcda8c24d6 Add checkpointer configuration support in langgraph.json (#4122)
Signed-off-by: William Fu-Hinthorn <13333726+hinthornw@users.noreply.github.com>
2025-04-01 21:16:12 -07:00
Vadym BardaandGitHub e3d697620b langgraph: support removing all messages with RemoveMessage (#4117) 2025-04-01 17:51:54 -04:00
Nuno Campos 30883729f0 0.3.22 2025-04-01 07:54:24 -07:00
William FHandGitHub 1c403f34c8 Allow blocking in dev (#4109) 2025-04-01 05:52:25 -07:00
William Fu-Hinthorn 9bd78ed483 Allow blocking in dev
Signed-off-by: William Fu-Hinthorn <13333726+hinthornw@users.noreply.github.com>
2025-04-01 05:45:47 -07:00
Nuno CamposandGitHub a77db7d73d Avoid creating checkpoint unless we're saving it (#4106)
- When checkpointing is disabled don't call create_checkpoint in
PregelLoop
- In local_read apply writes directly to copies of updated channels
- Add BaseChannel.copy() method to create channel copies with less
overhead
2025-03-31 19:13:36 -07:00
Nuno Campos e85b7e6cd9 Lint 2025-03-31 18:46:51 -07:00
Nuno Campos 94fa46f9fa Avoid creating checkpoint unless we're saving it
- When checkpointing is disabled don't call create_checkpoint in PregelLoop
- In local_read apply writes directly to copies of updated channels
- Add BaseChannel.copy() method to create channel copies with less overhead
2025-03-31 18:37:13 -07:00
Nuno CamposandGitHub e50110ba91 Avoid raise-catch strategy in BaseChannel.checkpoint() (#4105)
- This mirrors the work done earlier on BaseChannel.get()
- Comparing to a sentinel value is significantly faster than raising and
catching an exception
2025-03-31 18:10:15 -07:00
Nuno Campos fd64ada9de Avoid raise-catch strategy in BaseChannel.checkpoint()
- This mirrors the work done earlier on BaseChannel.get()
- Comparing to a sentinel value is significantly faster than raising and catching an exception
2025-03-31 17:48:19 -07:00
Nuno CamposandGitHub b15ec09c3b Add fast path to serialize None values (#4103)
- If the value to serialize is None we can use encode it in the string
type, and skip msgpack encoding
- Use None value for edge/branch channels in StateGraph
2025-03-31 17:42:26 -07:00
Nuno Campos 5e9e7b79fe Lint 2025-03-31 17:36:00 -07:00
Nuno Campos c49a077789 Lint 2025-03-31 17:24:26 -07:00
Nuno Campos 881b07cf7f Lint 2025-03-31 16:36:16 -07:00
Nuno Campos 0425d4e65d Update 2025-03-31 16:29:07 -07:00
Nuno Campos 118016a21c Add fast path to serialize None values 2025-03-31 16:15:56 -07:00
Nuno CamposandGitHub bda3c3add9 Lazily create atomic counters in pregel scratchpad (#4101)
- many times these aren't actually used, so makes sense to delay
creation until needed
2025-03-31 15:44:00 -07:00
Nuno Campos 067b99c789 Lazily create atomic counters in pregel scratchpad
- many times these aren't actually used, so makes sense to delay creation until needed
2025-03-31 15:19:53 -07:00
Tat Dat Duong aef463c633 fix(sdk-js): send accepts any input 2025-04-01 00:15:32 +02:00
Nuno CamposandGitHub 673cc5ad1a Reduce perf impact of pregel scratchpad creation (#4098)
- make scratchpad class frozen now that its members are never reassigned
- replace next(gen expr) with for-loop to avoid allocating generator
objects
2025-03-31 15:13:38 -07:00
Nuno Campos e9e9a96a0d Reduce perf impact of pregel scratchpad creation
- make scratchpad class frozen now that its members are never reassigned
- replace next(gen expr) with for-loop to avoid allocating generator objects
2025-03-31 14:50:10 -07:00
Andrew NguonlyandGitHub cf7136297e docs: Add docs for more environment variables (#4080) 2025-03-28 15:40:16 -07:00
David DuongandGitHub e5aae80e3a feat(cli): add support for gen ui config (#4079) 2025-03-28 23:14:56 +01:00
Tat Dat Duong f629f68ec3 feat(cli): add support for gen ui config 2025-03-28 23:05:04 +01:00
Andrew NguonlyandGitHub 575de221fe docs: Update Cloud SaaS and CLI documentation pages (#4077)
### Summary
1. Update API spec.
2. Clarify how to specify `requirements.txt` in `dependencies` list.
3. Clarify deletion policy for database.
4. Clarify resource allocation for `Production` type deployments.
5. Update supported Python versions.
2025-03-28 14:21:24 -07:00
David DuongandGitHub d2fc5f0a0f feat(sdk-js): run optimistic values mutator before any network request (#4070) 2025-03-28 21:57:33 +01:00
Tat Dat Duong 8e4b8b11ff Add docs about optimistic updates 2025-03-28 21:52:37 +01:00
Tat Dat Duong 2808a7859a Bump to 0.0.62 2025-03-28 21:39:44 +01:00
Tat Dat Duong fb3c61ea4f feat(sdk-js): run optimistic values mutator before any network request 2025-03-28 21:39:35 +01:00
David DuongandGitHub 69cecd872c release(sdk-js): 0.0.61 (#4069) 2025-03-28 15:24:38 +01:00
Tat Dat Duong 9abc1c8174 release(sdk-js): 0.0.61 2025-03-28 15:23:25 +01:00
David DuongandGitHub de90ced29d fix(sdk-js): do not await for client.runs.stream, as it is already async generator (#4068) 2025-03-28 15:22:20 +01:00
Tat Dat Duong b8b973fc0c fix(sdk-js): do not await for client.runs.stream, as it is already async generator 2025-03-28 15:15:54 +01:00
David DuongandGitHub 89e3709a2a feat(docs): cloning traces locally (#4057) 2025-03-28 14:41:00 +01:00
Arjun Natarajan a7f012a19c fix link 2025-03-28 09:37:05 -04:00
Arjun Natarajan 9b05ab6453 mkdocs yaml 2025-03-28 09:27:30 -04:00
David DuongandGitHub 5401d2ea81 feat(sdk-js): add option to manually provide implementation for shared modules (#4042) 2025-03-28 14:04:09 +01:00
Nuno CamposandGitHub 4401612aa6 Reduce the number of channels created for each node by 50% (#4064)
- Used to be 2 channels per node, it is now one per node, which is the
minimum
- Now both hard edges, conditional edges, entrypoint and conditional
entrypoint all use the same channel to trigger a node
2025-03-27 18:05:04 -07:00
Nuno Campos 49bb08a3f9 Update prebuilt test 2025-03-27 17:58:29 -07:00
Nuno Campos 4f2e9b838f Reduce the number of channels created for each node by 50%
- Used to be 2 channels per node, it is now one per node, which is the minimum
- Now both hard edges, conditional edges, entrypoint and conditional entrypoint all use the same channel to trigger a node
2025-03-27 17:47:34 -07:00
Nuno Campos d30da72f6e Reduce the number of channels created for each node by 50%
- Used to be 2 channels per node, it is now one per node, which is the minimum
- Now both hard edges, conditional edges, entrypoint and conditional entrypoint all use the same channel to trigger a node
2025-03-27 17:47:11 -07:00
William FHandGitHub 7f079adfee Update auth user type (#4062) 2025-03-27 16:09:54 -07:00
William Fu-Hinthorn 4c74af606f Update auth user type 2025-03-27 16:03:11 -07:00
Eugene YurtsevandGitHub 900824089b docs: disable link checking on push and workflow dispatch (#4061) 2025-03-27 17:33:36 -04:00
Nuno CamposandGitHub 522caa643f In Python 3.12 or above, use asyncio eager task factory (#4055)
- This is a performance improvement when calling async functions that do
not use await, as they are run immediately and never scheduled in the
loop
2025-03-27 13:36:04 -07:00
Nuno Campos ef71656f05 Fix 2025-03-27 13:14:39 -07:00
Tat Dat Duong 3ba7c7fbed Do not throw error if window is undefined due to Next 2025-03-27 21:03:54 +01:00
Tat Dat Duong 5cdab86d48 Fix object assignment 2025-03-27 20:58:39 +01:00
Nuno CamposandGitHub f5fe7e5195 Remove internal frames from stack traces (#4054)
- For exceptions raised in user code (ie. nodes or edges) remove
internal frames from the stack trace
2025-03-27 12:41:54 -07:00
Arjun Natarajan 2b728410e9 spell check 2025-03-27 14:47:27 -04:00
Arjun Natarajan 30221da4a8 docs for cloning traces locally 2025-03-27 14:38:20 -04:00
Nuno Campos 1c5a354a7d In Python 3.12 or above, use asyncio eager task factory
- This is a performance improvement when calling async functions that do not use await, as they are run immediately and never scheduled in the loop
2025-03-27 11:00:37 -07:00
Nuno Campos bfd271e00e Remove internal frames from stack traces
- For exceptions raised in user code (ie. nodes or edges) remove internal frames from the stack trace
2025-03-27 10:58:13 -07:00
Vadym BardaandGitHub 9647b1e55f langgraph: use correct type for node destination annotations (#4053)
Fixes https://github.com/langchain-ai/langgraph/issues/4051
2025-03-27 16:57:39 +00:00
Eugene YurtsevandGitHub e4aa204110 docs: add langchain llms.txt to the overview (#4047) 2025-03-27 12:33:42 -04:00
Vadym BardaandGitHub 2c29edadec langgraph: release 0.3.21 (#4050) 2025-03-27 11:38:37 -04:00
Vadym BardaandGitHub 96847e644b langgraph: add tests for remote graph interrupts (#4048) 2025-03-27 15:17:29 +00:00
Tat Dat Duong 4b102638c2 feat(sdk-js): add option to manually provide implementation for shared modules 2025-03-26 22:46:59 +01:00
7021ce3742 patch: fix return type of Topic.update (#4029)
This PR fixes the return type annotation of the `update` method from
`None` to `bool`, as the method returns a boolean value indicating
whether self.values has changed

Co-authored-by: kakaogames <kakaogames@Justin-MacBook-Pro.local>
2025-03-26 16:57:35 -04:00
Nuno CamposandGitHub d0c0aa9697 benchmark: remove some benchmarks (#4039)
Remove some benchmarks temporarily so we can fit more stuff into the
annotation
2025-03-26 13:50:53 -07:00
Vadym BardaandGitHub 520de30350 langgraph: fix interrupt deserialization in RemoteGraph (#4040) 2025-03-26 16:42:21 -04:00
Eugene Yurtsev 81c0d47363 x 2025-03-26 15:16:44 -04:00
87603d8a00 docs: add version admonitions for Interrupt and RetryPolicy (#3988)
This pull request includes changes to add version admonitions to the
documentation and update the styling for these admonitions. The most
important changes include the addition of version information to the
documentation, updates to the CSS for version admonitions, and
modifications to the `mkdocs.yml` configuration file to include the new
stylesheets.
this should solve this #3991

---------

Co-authored-by: Eugene Yurtsev <eugene@langchain.dev>
2025-03-26 13:48:54 -04:00
Vadym BardaandGitHub 7ad7329c7d docs: add codeact prebuilt (#4036) 2025-03-26 17:25:17 +00:00
Vadym BardaandGitHub e981d27f84 prebuilt: release 0.1.7 (#4034) 2025-03-26 09:22:09 -04:00
Vadym BardaandGitHub 71db4f2ad5 prebuilt: ignore updates when combining parent commands with Send (#4033) 2025-03-26 09:20:37 -04:00
Nuno CamposandGitHub 4ced277e2d Update adopters.md (#4025) 2025-03-25 18:40:02 -07:00
jessicaouandGitHub 34738fa566 Update adopters.md 2025-03-25 17:27:53 -07:00
Nuno CamposandGitHub 0286c38784 fix(sdk-js): mark schema as nullable to match python (#3928) 2025-03-25 16:11:35 -07:00
David DuongandGitHub fb5a1c4028 feat(cli): add packageManager and devEngines detection (#4024) 2025-03-25 23:43:36 +01:00
Tat Dat Duong 39d85466f8 Bump to 0.1.80 2025-03-25 23:36:33 +01:00
Tat Dat Duong 3c797529bb Avoid frozen lockfile 2025-03-25 23:32:40 +01:00
Tat Dat Duong 0d185d43ed feat(cli): add packageManager and devEngines detection 2025-03-25 23:26:04 +01:00
Eugene YurtsevandGitHub 70b8391a89 ci: use fast benchmark (#4017) 2025-03-25 17:59:18 -04:00
Eugene YurtsevandGitHub 1a37f2d5a2 sdk-py: release 0.1.59 (#4018) 2025-03-25 17:58:51 -04:00
Really HimandGitHub 949af8abe5 docs(pregel): One-line markdown formatting quick-fix (#4023)
## Description

I noticed a very minor issue in the formatting of the Concepts > Pregel
doc:
(https://langchain-ai.github.io/langgraph/concepts/pregel/#high-level-api)
(https://github.com/langchain-ai/langgraph/blob/main/docs/docs/concepts/pregel.md)

You can see in the image below that there is a python codeblock, then a
pycon block, and inside that block there is an extra
triple-backtick/code fence, and then text at the bottom, which it
appears like it is supposed to be a separate python block, like the one
above it. I.e., clearly:

```
```python
print(graph.channels)
```

is intended to be:

```python
print(graph.channels)
```

I'm pretty sure this is due to an extra whitespace character before the preceding closing code fence, which is throwing off the formatting.


![image](https://github.com/user-attachments/assets/616d72d6-652b-4599-be3e-55c47766861d)

My VS-Code/extensions can't really render the Markdown the way it appears on the Website, I think because of the tabs (Graph API vs. Functional API), but I noticed that if I remove the extra whitespace, the highlighting on the python codeblock is corrected:

BEFORE:
<img width="605" alt="Screenshot 2025-03-25 at 5 02 41 PM" src="https://github.com/user-attachments/assets/8474f103-c5ab-4c02-b22f-3d54b3363331" />

AFTER:
<img width="277" alt="Screenshot 2025-03-25 at 5 02 50 PM" src="https://github.com/user-attachments/assets/a311b87b-859c-4aba-a4d8-6b063a155d90" />


## Fix
* Remove one whitespace character that was throwing off markdown rendering
2025-03-25 17:58:37 -04:00
Eugene YurtsevandGitHub 094255c3fe docs: remove langmanus temporarily (#4022)
there's no pypi package
2025-03-25 16:46:07 -04:00
Nuno CamposandGitHub b6055ff3fe Warn when get_graph tries to draw edge that doesn't exist (#4021) 2025-03-25 12:57:31 -07:00
Nuno Campos e082ba4f85 Warn when get_graph tries to draw edge that doesn't exist 2025-03-25 12:50:47 -07:00
Vadym BardaandGitHub f36b7f61fb prebuilt: release 0.1.6 (#4020) 2025-03-25 15:49:02 -04:00
Vadym BardaandGitHub 4095f0a927 prebuilt: only combine Command.PARENT for Send gotos in ToolNode (#4019) 2025-03-25 15:47:46 -04:00
8af09714ff docs: remove unused imports from guide (#4014)
Not included in index page, and currently re-directs:
https://github.com/langchain-ai/langgraph/blob/01fed0fae27a8d71490a7f94a74942af5626da97/docs/_scripts/notebook_hooks.py#L24

---------

Co-authored-by: Eugene Yurtsev <eyurtsev@gmail.com>
2025-03-25 15:35:54 -04:00
Eugene YurtsevandGitHub 5d7e818882 sdk: Add headers to sync client (#4012)
Add ability to pass run time headers to the sync client.
2025-03-25 14:58:33 -04:00
Eugene YurtsevandGitHub 37429ff73b docs: remove old code from workflow (#4016) 2025-03-25 14:20:04 -04:00
Vadym BardaandGitHub af7515c37a prebuilt: release 0.1.5 (#4015) 2025-03-25 13:52:35 -04:00
Vadym BardaandGitHub b97cda4290 prebuilt: add support for multiple Command(graph=Command.PARENT) returned by tools (#4003) 2025-03-25 13:51:05 -04:00
YkohandGitHub 01fed0fae2 Docs fix example docs (#3971) 2025-03-25 11:02:20 -04:00
Nuno Campos 2ac22f8246 0.3.20 2025-03-24 18:09:56 -07:00
William FHandGitHub ae2e8d7e5e Use 128bit hash for task ids (#4005) 2025-03-24 18:09:25 -07:00
Nuno Campos 5526486a0b Use 128bit hash for task ids 2025-03-24 18:04:26 -07:00
William FHandGitHub 0f8fc4fe68 Handle Sends (#4004)
In the json-mode deserializer
2025-03-24 17:17:52 -07:00
William Fu-Hinthorn 10859da99a Handle sneds 2025-03-24 17:12:50 -07:00
Nuno CamposandGitHub b285a118a7 Log and continue for subgraph schema issues (#3997) 2025-03-24 16:31:42 -07:00
William FHandGitHub 6853d045b6 Add HTTP deserialization option (#4002) 2025-03-24 16:28:53 -07:00
William Fu-Hinthorn d8cc9c9680 merge with ormsgpack 2025-03-24 16:21:59 -07:00
William Fu-Hinthorn 723d6f8a84 Add json mode msgpack unpacker 2025-03-24 16:15:48 -07:00
Nuno CamposandGitHub 696a922241 Switch serialization lib to ormsgpack (#3953)
- faster for large states
- supports tuples as dict keys
2025-03-24 16:08:57 -07:00
Eugene YurtsevandGitHub c598fee7d6 sdk-py: Propagate headers in the async client (#4001)
Propagate headers in the async client
2025-03-24 16:30:40 -04:00
William FHandGitHub 6da6c4443a Merge branch 'main' into wfh/log_and_continue 2025-03-24 12:25:47 -07:00
Eugene YurtsevandGitHub addb491cfd sdk: allow specifying run time headers in http client (#4000)
This PR only allows this in the HTTP client. 

I can follow up with a PR to allow throughout the entire API.

The use case is to allow instantiating the client once (w/ a single connection pool), but allowing changing api keys and any other headers at run time
2025-03-24 14:47:35 -04:00
Eugene YurtsevandGitHub c84f35eff5 add langmanus to prebuilt (#3999) 2025-03-24 13:26:53 -04:00
Eugene YurtsevandGitHub f178e4205f docs: add xxhash explicitly to docs pyproject.toml (#3998)
It's not getting picked up from the dev requirements for some reason.
2025-03-24 12:58:33 -04:00
Nuno Campos 3f4d1c66c2 0.3.19 2025-03-24 09:45:54 -07:00
Nuno Campos 2ee5b8e9d1 Bump 2025-03-24 09:03:23 -07:00
Nuno Campos aadbcb443a Bump 2025-03-24 09:03:23 -07:00
Nuno Campos a88794b74e Update ormsgpack 2025-03-24 09:03:23 -07:00
Nuno Campos 556733c77c Bump 2025-03-24 09:01:55 -07:00
Nuno Campos 3d16acf3f5 Switch serialization lib to ormsgpack
- faster for large states
- supports tuples as dict keys
2025-03-24 09:01:55 -07:00
Nuno CamposandGitHub 87cbc4942d Switch task ids to use xxhash3 (#3954)
- much faster / less memory allocations
- backwards compat by applying only to checkpoint versions 2 or above
2025-03-24 08:42:50 -07:00
Nuno CamposandGitHub 6d63300c9a benchmarks: Add 1st event latency (#3909) 2025-03-24 07:58:47 -07:00
Nuno Campos a5dd181138 Update 2025-03-24 07:57:02 -07:00
William Fu-Hinthorn ad63b730b3 Log and continue for subgraph schema issues 2025-03-24 07:50:25 -07:00
Nuno Campos 528d3946c6 Lock 2025-03-24 07:49:24 -07:00
Nuno Campos 037d9d1402 Lock 2025-03-24 07:49:24 -07:00
Nuno Campos 6aee213f3c Switch task ids to use xxhash3
- much faster / less memory allocations
- backwards compat by applying only to checkpoint versions 2 or above
2025-03-24 07:49:24 -07:00
Lance MartinandGitHub f690f4244e Remove failing links (#3994)
Anthropic links for blog post and docs are failing CI -- 

https://github.com/langchain-ai/langgraph/actions/runs/14024926642/job/39261981682

Remove to unblock docs build; we may add back to ignore later.
2025-03-23 19:53:11 -07:00
Lance MartinandGitHub d6856131b6 Fix broken links in ntbks (#3993)
A number of Anthropic links recently changed
2025-03-23 17:59:14 -07:00
Lance MartinandGitHub 7d90440035 Update llms.txt for langgraph (#3987) 2025-03-23 15:39:09 -07:00
alxdr3kandGitHub fed785eabd docs: fix typo in low_level.md (#3968)
- Fix typo
2025-03-21 16:40:41 -04:00
YkohandGitHub 765b04adfd Docs: fix example (#3972) 2025-03-21 16:39:39 -04:00
7085b149e5 fix(docs): Update deprecated methods and add validator (#3920)
- Added a validator to sanitize 'name' fields and prevent
string_pattern_mismatch errors.
- Replaced deprecated `dict` method with `model_dump` in line with
Pydantic v2.0 migration guidelines.
- Updated gen_perspectives_chain and gen_queries_chain to ensure
compatibility with structured output and include raw data where needed.
This allows use of fast_llm across the notebook.

---------

Co-authored-by: Eugene Yurtsev <eyurtsev@gmail.com>
2025-03-21 15:51:13 -04:00
11c71fef89 chore(docs): Improve documentation for AsyncSqliteSaver (#3858)
**Description:**
Make AsyncSqliteSaver examples workable.

**Issue:**
For "Usage within StateGraph" example,
SyntaxError: 'async with' outside async function

For "Raw usage" example
KeyError: 'checkpoint_ns' and KeyError: 'id'

**Dependencies:**
N/A

Co-authored-by: Eugene Yurtsev <eyurtsev@gmail.com>
2025-03-21 15:50:51 -04:00
Eugene Yurtsev 8be0fb675a x 2025-03-21 15:25:28 -04:00
William FHandGitHub 1b4f335ffe Add studio URL flag (#3980) 2025-03-21 11:23:05 -07:00
William Fu-Hinthorn 9c36a7de85 Add studio URL flag 2025-03-21 11:20:29 -07:00
Eugene Yurtsev d166dea4f0 Merge branch 'main' into eugene/add_latency 2025-03-21 12:55:37 -04:00
Vadym BardaandGitHub 8e922b859c prebuilt: release 0.1.4 (#3977) 2025-03-21 12:05:15 -04:00
Vadym BardaandGitHub 9a4c30135f prebuilt: pass last message to structured response model in create_react_agent (#3976) 2025-03-21 11:58:27 -04:00
William FHandGitHub bc6651f34c Studio cli command (#3962) 2025-03-20 17:57:56 -07:00
William Fu-Hinthorn 23bb5369b9 Studio cli command 2025-03-20 17:51:08 -07:00
Nuno CamposandGitHub 85b81371f7 Use incremental storage in memory checkpointer (#3960)
- This makes our checkpoint benchmarks more closely resemble the
behavior of our prod checkpointers
- Also found and fixed a bug w multiple subgraphs in same node
accidentally sharing checkpoints
2025-03-20 16:33:47 -07:00
Nuno Campos 54ab833b74 Lint 2025-03-20 16:26:52 -07:00
Nuno Campos 4ea936eaf4 Lint 2025-03-20 16:24:57 -07:00
Nuno Campos 9d81ec9ffd Lint 2025-03-20 16:22:24 -07:00
Nuno Campos 46b652a74c Use incremental storage in memory checkpointer
- This makes our checkpoint benchmarks more closely resemble the behavior of our prod checkpointers
- Also found and fixed a bug w multiple subgraphs in same node accidentally sharing checkpoints
2025-03-20 16:11:36 -07:00
Vadym BardaandGitHub 7013ca9a3f docs: use hosted logo (#3959) 2025-03-20 18:17:22 -04:00
William FHandGitHub 0c04aec664 Include enum in check for pydantic state (#3955) 2025-03-20 12:03:22 -07:00
Eugene YurtsevandGitHub 1650c8508e benchmark: Add compilation only (#3932)
Add compilation benchmark alone
2025-03-20 14:51:31 -04:00
Eugene YurtsevandGitHub e176b98fe7 Add llms-txt resources (#3935) 2025-03-20 14:44:21 -04:00
William Fu-Hinthorn eb1e1aa010 Include enum in check for pydantic state 2025-03-20 10:29:16 -07:00
Nuno CamposandGitHub 77c833e1e5 Use fast path for prepare_next_tasks on input (#3931)
- When there are no values in checkpoint no need to run through all the
PULL candidates
- When there are input writes save updated_channels to use on the next
call to prepare_next_tasks
2025-03-20 08:46:48 -07:00
Nuno Campos 0ac29434a7 Lint 2025-03-20 08:40:05 -07:00
Nuno Campos 43f5a17416 Lint 2025-03-20 08:24:51 -07:00
Nuno Campos 7d0857f263 Lint 2025-03-20 08:24:31 -07:00
Nuno Campos b82d70a66a Lint 2025-03-20 08:22:16 -07:00
Nuno CamposandGitHub 5fb037171d Small perf improvements (#3949)
- RunnableCallable: Skip signature checks for internal callables where
we know the signatures ahead of time
- PregelNode: Avoid redoing subgraphs serarch when copying it
- CompiledStateGraph: Avoid copying PregelNode when attaching writers
2025-03-20 08:19:02 -07:00
Nuno Campos d3bb2b9aa0 Lint 2025-03-20 08:18:17 -07:00
Nuno Campos ea765b4134 More small perf improvements
- RunnableCallable: Skip signature checks for internal callables where we know the signatures ahead of time
- PregelNode: Avoid redoing subgraphs serarch when copying it
- CompiledStateGraph: Avoid copying PregelNode when attaching writers
2025-03-20 08:11:28 -07:00
William FHandGitHub 66ff83dca9 Lock (#3947) 2025-03-20 08:04:53 -07:00
William FHandGitHub 254e398345 Merge branch 'main' into wfh/reloack 2025-03-20 08:04:38 -07:00
Vadym BardaandGitHub c7567ea219 docs: improve search (#3948) 2025-03-20 11:02:59 -04:00
William Fu-Hinthorn 8c0306c3f4 Lock 2025-03-20 07:59:30 -07:00
William FHandGitHub 992b05a196 langgraph-checkpoint-postgres 2.0.19 (#3945) 2025-03-20 07:25:41 -07:00
William Fu-Hinthorn 893a9646d3 langgraph-checkpoint-postgres 2.0.19 2025-03-20 07:25:14 -07:00
William FHandGitHub eaa37a2ce9 Increase pg->checkpoint minbound (#3944) 2025-03-20 07:24:43 -07:00
William Fu-Hinthorn daee8d88bb Increase pg->checkpoint minbound 2025-03-20 07:24:15 -07:00
Nuno Campos eaa18cc2dd Use fast path for prepare_next_tasks on input
- When there are no values in checkpoint no need to run through all the PULL candidates
- When there are input writes save updated_channels to use on the next call to prepare_next_tasks
2025-03-19 18:14:04 -07:00
Nuno CamposandGitHub b2d9a36308 langgraph: incorporate information about previously updated channels to identify which tasks to execute next (#3916)
Leverage information about which channels were updated in the previous
step to determine which tasks should be triggered. This can result in
significant speed up in prepare_next_tasks in some situations.
2025-03-19 16:22:12 -07:00
Tat Dat Duong dd733a3389 fix(sdk-js): mark schema as nullable to match python 2025-03-19 22:40:55 +01:00
William FHandGitHub 03fc695d60 Add refcount test (#3910) 2025-03-19 14:33:43 -07:00
William Fu-Hinthorn 9994b09304 merge 2025-03-19 14:27:19 -07:00
William FHandGitHub 53f8558914 Release 0.3.18 (#3925)
Includes:
- Explicit unsetting of runnable context var
- Weakref for PregelExecutableTask

both to reduce the chance of keeping a reference to an internal object
and preventing garbage collection
2025-03-19 14:11:46 -07:00
William Fu-Hinthorn 4bfcd84cee Cleanup ref count check 2025-03-19 14:10:01 -07:00
David DuongandGitHub cd1d7be05f feat(sdk): add bulk_update_state in SDK (#3923) 2025-03-19 22:09:53 +01:00
Really HimandGitHub 939a426a2e DOCS: Update state-model.ipynb to use "AnyMessage" (#3926)
## Description
The documentation for working with Pydantic and graph State recommends
to use `AnyMessage` when working with LangChain types, but the code
example uses `BaseMessage`.
2025-03-19 21:08:14 +00:00
William Fu-Hinthorn 94c815f226 Release 0.3.18
Includes:
- Explicit unsetting of runnable context var
- Weakref for PregelExecutableTask

both to reduce the chance of keeping a reference to an internal object and preventing
garbage collection
2025-03-19 14:04:01 -07:00
Tat Dat Duong ef345aac5f Fix typo 2025-03-19 22:02:55 +01:00
William FHandGitHub e306258525 Reference to PregelExecutableTask (#3924) 2025-03-19 14:00:43 -07:00
William Fu-Hinthorn 05cd317486 Update snapshots more 2025-03-19 13:54:10 -07:00
Tat Dat Duong 6dfed31a5e Update parameters 2025-03-19 21:39:35 +01:00
ThaparandGitHub ee8374c4c0 docs: Update bad link in libs/cli README.md (#3919)
Fixed reference hyperlink
2025-03-19 16:27:37 -04:00
William Fu-Hinthorn 2066894b5f Update snapshots 2025-03-19 13:25:02 -07:00
William Fu-Hinthorn 6a2d20fd5b Reference to PregelExecutableTask 2025-03-19 13:19:02 -07:00
Eugene Yurtsev 5b8b9f1067 Update doc-string 2025-03-19 16:10:50 -04:00
Eugene Yurtsev c9cb8165d4 x 2025-03-19 16:08:25 -04:00
Tat Dat Duong 1f0348a5ca Fix docstring 2025-03-19 21:07:07 +01:00
Tat Dat Duong 442ef0788e Add graph_id back 2025-03-19 21:05:43 +01:00
Eugene Yurtsev 73f9ef0ef8 add type 2025-03-19 16:00:49 -04:00
Tat Dat Duong 1f7a380548 Fix typo 2025-03-19 20:54:15 +01:00
Eugene Yurtsev 8959f2aec5 lint 2025-03-19 15:54:07 -04:00
Eugene Yurtsev 0e7869eba4 Merge branch 'main' into ey/optimize_triggers 2025-03-19 15:52:29 -04:00
William FHandGitHub d3f8478054 Unset config context after function end (#3922) 2025-03-19 12:51:39 -07:00
Tat Dat Duong 0cb1893475 Update for JS as well 2025-03-19 20:46:22 +01:00
Tat Dat Duong e779c8e0b1 Merge into create 2025-03-19 20:42:48 +01:00
Eugene Yurtsev 18b82cb8e2 x 2025-03-19 15:29:50 -04:00
Tat Dat Duong 972ab1a935 Revert docstring for update_state 2025-03-19 20:22:05 +01:00
William Fu-Hinthorn 9cc2f37cca Unset config context after function end 2025-03-19 12:14:29 -07:00
Tat Dat Duong a2d7631f47 Fix in async client 2025-03-19 20:10:42 +01:00
Tat Dat Duong 1e767c0653 feat(sdk): add bulk_update_state in SDK 2025-03-19 20:05:08 +01:00
David DuongandGitHub d4c569cb7c feat(sdk-js): add bulkUpdateState method (#3878) 2025-03-19 19:25:37 +01:00
David DuongandGitHub a146df7f6a release(langgraph): 0.3.17 (#3918) 2025-03-19 19:10:01 +01:00
Tat Dat Duong c52cc03e4b release(langgraph): 0.3.17 2025-03-19 19:02:51 +01:00
Nuno CamposandGitHub f206cfad8f Store all triggers in task (#3912)
- These are used to update seen version
2025-03-19 09:47:06 -07:00
Nuno Campos d4c8b219c4 Update tests 2025-03-19 09:40:34 -07:00
Tat Dat Duong 00855999d2 Bump to 0.0.59 2025-03-19 17:02:19 +01:00
Tat Dat Duong 24bd0e1c1f Fix formatting 2025-03-19 16:59:53 +01:00
David DuongandGitHub 3b59055192 feat(pregel): add bulk update state method (#3737)
This method is useful for recreating a thread from a list of checkpoint
writes. A new method is needed to clone a checkpoint that has been
created from multiple writes (functional API, map-reduce)

Port of https://github.com/langchain-ai/langgraphjs/pull/969 and
https://github.com/langchain-ai/langgraphjs/pull/1007
2025-03-19 16:59:07 +01:00
Eugene Yurtsev 67a16bec53 more typos 2025-03-19 11:48:31 -04:00
Eugene Yurtsev f97802eed5 x 2025-03-19 11:44:42 -04:00
Eugene Yurtsev bccb796ccc x 2025-03-19 11:38:46 -04:00
Eugene Yurtsev 4068e9d135 x 2025-03-19 11:27:56 -04:00
Eugene Yurtsev a951334f7f qxqx 2025-03-19 11:18:00 -04:00
lc-arjunandGitHub 75a727877f feat: add docs for prompt engineering (#3846) 2025-03-19 10:51:54 -04:00
Tat Dat Duong 1cece3228c Fix indent bug 2025-03-19 15:37:43 +01:00
Tat Dat Duong 7ba48d75c9 Another merge issue 2025-03-19 15:05:22 +01:00
Tat Dat Duong 7fb0628957 Remove duplicated test 2025-03-19 14:44:07 +01:00
Tat Dat Duong 6edf29f043 Fix rebase artifacts 2025-03-19 14:39:59 +01:00
Tat Dat Duong c8a605cbc8 Update PregelProtocol 2025-03-19 14:29:11 +01:00
Tat Dat Duong fbec207446 Apply formatting 2025-03-19 14:29:09 +01:00
Tat Dat Duong 2223c82606 Update to match JS 2025-03-19 14:28:55 +01:00
Tat Dat Duong 06f2eef74c Fix bug with stale task_id 2025-03-19 14:22:25 +01:00
Tat Dat Duong 62aa66cd4b Add better docstrings 2025-03-19 14:22:25 +01:00
Tat Dat Duong 8ffe9634b7 Clearer breakdown 2025-03-19 14:22:25 +01:00
Tat Dat Duong 4b1d6d2aeb Rename to StateUpdate 2025-03-19 14:22:25 +01:00
Tat Dat Duong 199ab46429 Avoid using checkpointer.list in async 2025-03-19 14:22:25 +01:00
Tat Dat Duong c758954519 Use awith_checkpointer instead 2025-03-19 14:22:25 +01:00
Tat Dat Duong 5bfb3bb882 Avoid running with shallow checkpointer 2025-03-19 14:22:24 +01:00
Tat Dat Duong 68a5c3f4c7 Implement batch events for RemotePregel 2025-03-19 14:22:04 +01:00
Tat Dat Duong b7fb8e6afb Fix types 2025-03-19 14:22:04 +01:00
Tat Dat Duong c34c798763 Add tests 2025-03-19 14:22:04 +01:00
Tat Dat Duong 792cd805a7 Fix tests 2025-03-19 14:21:44 +01:00
Tat Dat Duong 764929afd9 Fix lint issues 2025-03-19 14:21:43 +01:00
Tat Dat Duong 1e751a2256 Fix typo 2025-03-19 14:21:43 +01:00
Tat Dat Duong e6726802f7 feat(pregel): add bulk update state method
This method is useful for recreating a thread from a list of checkpoint writes. A new method is needed to clone a checkpoint that has been created from multiple writes (functional API, map-reduce)

Port of https://github.com/langchain-ai/langgraphjs/pull/969
2025-03-19 14:21:43 +01:00
Nuno Campos a541376d10 Store all triggers in task
- These are used to update seen version
2025-03-18 21:17:26 -07:00
William Fu-Hinthorn f9780330a6 Add refcount test 2025-03-18 20:13:40 -07:00
Eugene Yurtsev 347ab0165e x 2025-03-18 22:23:39 -04:00
Eugene Yurtsev cb95821eb0 x 2025-03-18 22:20:18 -04:00
Eugene Yurtsev 4b9cdb4107 add compilation benchmark 2025-03-18 22:16:10 -04:00
Eugene Yurtsev b440b14fa7 x 2025-03-18 21:53:56 -04:00
Nuno CamposandGitHub 24f7d7c439 Add pydantic state benchmark case (#3872) 2025-03-18 18:10:50 -07:00
William FHandGitHub 9533d35a84 0.3.16 (#3908) 2025-03-18 17:37:16 -07:00
William FHandGitHub 48de4a7234 Fix reference cycle btwn PregelLoop and PregelRunner (#3907) 2025-03-18 17:37:01 -07:00
William Fu-Hinthorn 67ac35c5bc 0.3.16 2025-03-18 17:35:53 -07:00
William Fu-Hinthorn 12c7ddf3a3 Update kafka 2025-03-18 17:30:21 -07:00
William Fu-Hinthorn d6caa3b00a lint 2025-03-18 17:18:07 -07:00
William Fu-Hinthorn 3d48526c16 Methods are weak 2025-03-18 17:17:04 -07:00
Nuno Campos 2f3bd69bf5 Add pydantic benchmark 2025-03-18 16:12:34 -07:00
Nuno Campos f10a0c6f32 Simpler runner 2025-03-18 15:15:26 -07:00
2eba27b01f docs: fix typo in hil how to doc (#3850)
Current text in the doc is incorrect:
```
Use the search tool to ask the user where they are, then look up the weather there
```

The search tool is not the one to use. Instead should just tell the
model to ask the user.

In addition, an important step is missing and makes the code seem less
impactful:
```python
location = interrupt("Please provide your location:")
```

The question to ask the human is actually coming from the LLM, there is
no need to hardcode it:
```python
...
location = interrupt(ask.question)
```

Before merging, someone who validates this should push an update to cell
outputs. I cleared it out from my branch because it made too many
updates to the file and would make it harder to review.

Co-authored-by: Eugene Yurtsev <eyurtsev@gmail.com>
2025-03-18 18:00:49 -04:00
c0245a6ee9 docs: fix typo (#3854)
probably > properly

Co-authored-by: Vadym Barda <vadym@langchain.dev>
2025-03-18 18:00:39 -04:00
9e82d23252 docs: fix typos (#3823)
This pull request corrects a couple of typographical errors in the
documentation.

---------

Co-authored-by: Eugene Yurtsev <eyurtsev@gmail.com>
Co-authored-by: Vadym Barda <vadym@langchain.dev>
2025-03-18 17:58:47 -04:00
460c522902 docs: fix typo (#3856)
Added "a" to make paragraph correct.

Co-authored-by: Eugene Yurtsev <eyurtsev@gmail.com>
2025-03-18 17:58:30 -04:00
298a19b573 docs: add missing word 'in' in the docs related to passing runtime args to tools (#3900)
- Adds missing word 'in'
- Sentence should read -> "The core technique **in** the examples below
is"

Co-authored-by: Eugene Yurtsev <eyurtsev@gmail.com>
2025-03-18 21:56:33 +00:00
d2ec46b927 add ai-data-science-team to third party packages (#3719)
I'd like to add my AI Data Science Team to the LangGraph Prebuilt 3rd
Party Packages.

Repo: https://github.com/business-science/ai-data-science-team

Prebuilt Agent Guidelines:
https://langchain-ai.github.io/langgraph/prebuilt/

Co-authored-by: Eugene Yurtsev <eyurtsev@gmail.com>
2025-03-18 17:55:31 -04:00
Rafayet HabibandGitHub 22e4bf74fc Update importing HumanMessage in add-summary-conversation-history.ipynb (#3751) 2025-03-18 21:30:32 +00:00
khnealandGitHub 96a0536ec4 doc: remove Python max version limit from example pyproject.toml (#3843)
LangGraph officially supported Python 3.13 back in October 2024: 

https://changelog.langchain.com/announcements/langgraph-is-now-compatible-with-python-3-13

But why suggest restricting the version of Python at all? The app/agent
owner will be in control of the runtime version anyway, so don't add
unnecessary restrictions.

Note this example from Poetry:
https://python-poetry.org/docs/pyproject/#requires-python

I did not refactor pyproject.toml to the newer Poetry 2 / uv format, but
I can do that in a future PR if it will help... please don't let that
block approval+merging this PR.
2025-03-18 21:30:06 +00:00
8d33938173 Improve documentation string for SqliteSaver (#3857)
* Document that `check_same_thread` as an option when creating sqlite
connection.
* Document why it's OK to do that.

---------

Co-authored-by: Eugene Yurtsev <eyurtsev@gmail.com>
2025-03-18 21:29:05 +00:00
William FHandGitHub 1c73b1e45a Schema coercer should never throw (#3871)
- pydantic will do that for us if needed
2025-03-18 14:17:08 -07:00
William FHandGitHub 465d5d648b libs: pregel: find_subgraph_pregel: Do not cache introspection (#3894)
When searching for subgraphs stop caching inspection for the graph drawing & subgraph inference.

Fixes #3842
2025-03-18 14:09:55 -07:00
William Fu-Hinthorn b751e8bcee _evaluate() forward ref 2025-03-18 14:07:23 -07:00
Nuno CamposandGitHub 8ec3982056 Enable larger cases of sequential bench graph (#3905)
- Now that we're a lot faster on this case, we can enable some larger
test cases
2025-03-18 14:05:27 -07:00
William FHandGitHub f17f264a7a Merge branch 'main' into fix_subgraph_tools 2025-03-18 13:49:30 -07:00
William Fu-Hinthorn 086443472f Drop cache 2025-03-18 13:46:41 -07:00
William Fu-Hinthorn 936e69404e Revert "libs: pregel: find_subgraph_pregel: Do not search via introspection"
This reverts commit 2458f2d2e0.
2025-03-18 13:43:08 -07:00
Tat Dat Duong b1a25abc73 Add command 2025-03-18 21:22:40 +01:00
Nuno Campos 0e70b8d94f Enable larger cases of sequential bench graph
- Now that we're a lot faster on this case, we can enable some larger test cases
2025-03-18 13:13:20 -07:00
Nuno CamposandGitHub e1aa1a4510 0.3.15 2025-03-18 13:11:37 -07:00
Hamza KyamanywaandGitHub ae7dbd1fa5 docs: correct the word "every" (#3902)
- PR fix the word "every" in the sentence "It will be called every time
the LLM is called"
2025-03-18 19:58:28 +00:00
Vadym BardaandGitHub 3ec95153ce ci: don't use real secrets in notebook runner (#3572) 2025-03-18 15:57:40 -04:00
Nuno CamposandGitHub 4836f8b18b Speed up prepare_single_task (#3893)
- sequential(2000) goes from 8.4s to 4.1s
- replace UUID(str).bytes with faster binascii.unhexlify, and do it only
once per step
- find only the first active trigger, instead of the full list
- use a dedicated function for checking active trigger
2025-03-18 10:15:17 -07:00
Vadym BardaandGitHub e7fbdeeb13 docs: fix formatting (#3901) 2025-03-18 13:00:36 -04:00
William Fu-Hinthorn ee650ab85f Only throw if in union 2025-03-18 09:58:07 -07:00
Nuno Campos 7a959f62cc Fix assertion 2025-03-18 09:54:20 -07:00
Yassin NouhandGitHub 82905297fd docs: Add Pydantic usage examples and runtime coercion documentation (#3588)
## Description
This PR enhances the state-model documentation by adding comprehensive
examples for advanced Pydantic usage in LangGraph. It addresses issue
#2745 regarding the need for better documentation of Pydantic schema
behavior.

### Changes
- Added new section on Advanced Pydantic Model Usage
- Added examples for serialization behavior with nested models
- Added section on runtime type coercion with examples
- Added documentation for proper message type handling (BaseMessage vs
AnyMessage)
- Updated Pydantic error URLs to latest version

### Related Issues
Closes #2745

### Testing
- All notebook cells have been executed and outputs verified
- Examples demonstrate proper usage patterns
- Error cases are properly documented

### Documentation
The changes are documentation-focused and include:
- New examples for complex Pydantic models
- Runtime coercion behavior examples
- Message type handling best practices

### Reviewers 
@eyurtsev
2025-03-18 09:47:17 -07:00
Nuno Campos 9b5549f759 Fix flaky assertion 2025-03-18 09:43:56 -07:00
Nuno Campos fa96c0ac76 One more 2025-03-18 09:34:52 -07:00
Nuno Campos 98b8ff904c Update test assertions for triggers 2025-03-18 09:30:29 -07:00
Nuno Campos 951131c8ec Lint 2025-03-18 09:15:43 -07:00
Nuno CamposandNuno Campos 8bcdba822e Reduce to 4.1s 2025-03-18 09:15:28 -07:00
Nuno CamposandNuno Campos 60fc49b448 Speed up prepare_single_task
- sequential(2000) goes from 8.4s to 4.7s
- replace UUID(str).bytes with simpler str.encode()
- find only the first active trigger, instead of the full list
- use a dedicated function for checking active trigger
2025-03-18 09:15:11 -07:00
Nuno CamposandGitHub 1d21b4ba08 Improve prepare_single_task trigger checks to linear complexity (#3891)
- Was O(n^2) due to individual channels created for every conditional
edge, including the default cond edge created for Command
- Now using a single channel per node for all conditional edge / command
triggers, reducing to linear complexity
- Improves run time on sequential(200) from 1.8s to 0.14s
2025-03-18 09:13:54 -07:00
Nuno CamposandGitHub 55ec0d3d2a Speed up task triggers check (#3890)
- Using a sentinel value is faster than raising-catching an exception
2025-03-18 09:10:38 -07:00
Nuno CamposandGitHub c7dd7be030 benchmarks: add sequential graph of a few hundred nodes (#3882)
Performance is poor due to state graph utilizing n^2 entries right now
to accommodate Command. Adding benchmark prior to updating
implementation.
2025-03-18 08:19:52 -07:00
Nuno Campos 47d38a3022 Replace get_catch w is_available 2025-03-18 08:19:22 -07:00
Nuno Campos 8e829f38af Smaller sizes until we merge the fixes 2025-03-18 08:05:25 -07:00
Nuno Campos 3f241d00a3 Fix bench 2025-03-18 06:45:41 -07:00
Hamza KyamanywaandGitHub f0abf582dd docs: make sentence relating to how to navigate between sub graphs clearer in the docs (#3896)
- fix typo / add missing word
- make sentence relating to how to navigate between sub graphs clearer
in the docs
2025-03-18 09:25:32 -04:00
blafab-hg 2458f2d2e0 libs: pregel: find_subgraph_pregel: Do not search via introspection
When searching for subgraphs do not attempt to search function non
locals for RunnableCallables as this captures unwanted reference to
surrounding variables.
2025-03-18 11:19:09 +01:00
Nuno CamposandGitHub 477a43dae0 Update pyproject.toml 2025-03-17 21:58:49 -07:00
Nuno CamposandGitHub fc8e6ec64f When using global resume value, ensure subgraphs consume it (#3889)
- Previously the global resume value was passed to subgraphs without
being consumed
- This would result in two parallel subgraph calls being able to use the
same resume value
- Note this behavior can't be implemented over the wire, that will be
fixed in future PR

Closes #3398
2025-03-17 21:26:33 -07:00
Nuno Campos d6a457ef1d Improve prepare_single_task trigger checks to linear complexity
- Was O(n^2) due to individual channels created for every conditional edge, including the default cond edge created for Command
- Now using a single channel per node for all conditional edge / command triggers, reducing to linear complexity
- Improves run time on sequential(200) from 1.8s to 0.14s
2025-03-17 21:26:26 -07:00
Nuno Campos ce1077da40 Speed up task triggers check
- Using a sentinel value is faster than raising-catching an exception
2025-03-17 21:04:05 -07:00
Nuno Campos 969958695a Add time when running directly 2025-03-17 20:59:10 -07:00
Nuno Campos dd16ae4ba5 When using global resume value, ensure subgraphs consume it
- Previously the global resume value was passed to subgraphs without being consumed
- This would result in two parallel subgraph calls being able to use the same resume value
- Note this behavior can't be implemented over the wire, that will be fixed in future PR
2025-03-17 20:31:54 -07:00
Nuno CamposandGitHub e24e141253 Fix concurrency issue in PregelScratchpad.consume_null_resume (#3888)
- Need to use a single operation to check if present and remove item
from list
- This doesn't fix the separate issue that parallel tasks claiming a
single interrupt value have somewhat undefined behavior (in the sense
that they will race to be the first to take it). That will be fixed in a
future PR

Closes #3875
2025-03-17 20:22:20 -07:00
Nuno Campos eae1faa656 Fix 2025-03-17 20:12:33 -07:00
Nuno Campos 1976d6584c Lint 2025-03-17 20:00:33 -07:00
Nuno Campos 54e18445fc Fix concurrency issue in PregelScratchpad.consume_null_resume
- Need to use a single operation to check if present and remove item from list
- This doesn't fix the separate issue that parallel tasks claiming a single interrupt value have somewhat undefined behavior (in the sense that they will race to be the first to take it). That will be fixed in a future PR
2025-03-17 19:53:03 -07:00
Nuno Campos 69dc29aaf9 0.3.13 2025-03-17 18:52:09 -07:00
Nuno CamposandGitHub aa5ff74845 Fix missing interrupts in stream (#3886)
- When multiple parallel tasks and/or subgraphs emit interrupts some
were missing from stream output
2025-03-17 18:51:42 -07:00
Nuno CamposandGitHub 6049aaa842 Enable xray for remote graphs (#3879) 2025-03-17 18:49:51 -07:00
Nuno Campos 576aa1ca02 Order 2025-03-17 18:41:36 -07:00
Nuno Campos e28e97d5e0 Lint 2025-03-17 18:39:13 -07:00
Nuno Campos 59e7c63c93 Lint 2025-03-17 18:38:37 -07:00
Nuno Campos be7dee1c3b Fix 2025-03-17 18:35:53 -07:00
Nuno Campos 0aafa04bac WIP Fix missing interrupts in stream
- When multiple parallel tasks and/or subgraphs emit interrupts some were missing from stream output
2025-03-17 18:31:15 -07:00
Nuno CamposandGitHub 2e1adaa867 0.3.12 2025-03-17 16:56:34 -07:00
Nuno CamposandGitHub 3f8b165592 Update state.py 2025-03-17 16:56:09 -07:00
William FHandGitHub 9ed0fa196c langgraph-checkpoint 2.0.21 (#3883) 2025-03-17 15:25:26 -07:00
William Fu-Hinthorn 0b9adc28c3 langgraph-checkpoint 2.0.21 2025-03-17 15:15:29 -07:00
William FHandGitHub 3b0255d1ef Check that migrations are idempotent (#3881) 2025-03-17 15:13:59 -07:00
Eugene Yurtsev 80c3ccba7b add benchmark 2025-03-17 16:45:02 -04:00
William FHandGitHub d4255a0645 Merge branch 'main' into wfh/idempotency_test_ 2025-03-17 13:27:12 -07:00
William FHandGitHub 80d61a2600 Make expires_at idempotent (#3880) 2025-03-17 13:26:20 -07:00
William Fu-Hinthorn 424f24720a Make expires_at idempotent 2025-03-17 13:25:22 -07:00
William Fu-Hinthorn 2a71180c1d Add tests for idempotency in migraionts 2025-03-17 12:43:21 -07:00
William Fu-Hinthorn 697f878e36 Make expires_at idempotent 2025-03-17 12:38:43 -07:00
William Fu-Hinthorn 987b9da4ab Merge branch 'main' into nc/16mar/schema-coercer-no-throw 2025-03-17 11:58:20 -07:00
Tat Dat Duong 4bff1df4b0 Bump to 0.0.58 2025-03-17 18:14:51 +01:00
Tat Dat Duong 5104e31e35 feat(sdk-js): add bulkUpdateState method 2025-03-17 18:14:33 +01:00
Tat Dat Duong 7ae4739630 Make options optional 2025-03-17 18:07:14 +01:00
Nuno Campos 5db1949ae3 Fix 2025-03-17 09:55:21 -07:00
Nuno Campos ddb29df667 Fix 2025-03-17 09:39:23 -07:00
Nuno Campos fa467573d7 Enable xray for remote graphs 2025-03-17 09:36:33 -07:00
Tat Dat Duong 1a728a93c6 feat(sdk-js): add bulkUpdateState method 2025-03-17 17:22:03 +01:00
alxdr3kandGitHub def69c59d2 docs: add missing namespace definition in persistence.md (#3859)
- fix typo
- add missing namespace definition for memory store
2025-03-17 09:38:15 -04:00
Nuno Campos aaa0cd6b51 Fix 2025-03-16 11:53:29 -07:00
Nuno Campos a9c831c11b Schema coercer should never throw
- pydantic will do that for us if needed
2025-03-16 11:46:34 -07:00
Nuno Campos bad4d17c34 Remove 'check size' ci job 2025-03-14 21:54:01 -07:00
Nuno Campos 55219b23d8 0.3.11 2025-03-14 16:18:50 -07:00
Nuno CamposandGitHub 8edbd39ad3 Add optional encryption of checkpointer payloads (#3852)
- no dependency on any particular encryption lib (there is no py stdlib
encryption lib)
- works with any modern checkpointer, ie. those which use dumps_typed
and loads_typed methods to serialize data
- uses the default msg pack serializer, but also works with any custom
serializer
- backwards compatible with unencrypted data in same storage (will just
be read unencrypted)
- providing easy constructor to use AES encryption through pycriptodome
library, one single line of code to add it in
- other encryption libraries or algorithms (even assymetric ones) can be
used by implementing the two-method CipherProtocol interface
- cipher name (eg. aes) is stored with encrypted payload for forwards
compatibility

```py
import sqlite3

from langgraph.checkpoint.serde.encrypted import EncryptedSerializer
from langgraph.checkpoint.sqlite import SqliteSaver

# will read AES key from env var LANGGRAPH_AES_KEY
serde = EncryptedSerializer.from_pycryptodome_aes()
# works with any other checkpointer, including custom ones
checkpointer = SqliteSaver(sqlite3.connect('...'), serde=serde)
```
2025-03-14 16:14:29 -07:00
Nuno Campos 4b0fd834d8 Make it possible to implement a cipher that handles multiple protocols 2025-03-14 16:04:28 -07:00
Nuno Campos 0fd2748530 Accept custom serde implementations 2025-03-14 15:43:07 -07:00
Nuno Campos bc0a3419ed Lint 2025-03-14 15:38:22 -07:00
Nuno Campos 5cd47bac49 Add optional encryption of checkpointer payloads
- no dependency on any particular encryption lib (there is no py stdlib encryption lib)
- works with any modern checkpointer, ie. those which use dumps_typed and loads_typed methods to serialize data
- backwards compatible with unencrypted data in same storage (will just be read unencrypted)
- providing easy constructor to use AES encryption through pycriptodome library, one single line of code to add it in
- other encryption libraries or algorithms (even assymetric ones) can be used by implementing the two-method CipherProtocol interface
- cipher name (eg. aes) is stored with encrypted payload for forwards compatibility
2025-03-14 15:32:50 -07:00
William FHandGitHub 4c6d80a67f Add TTL Sweeper (#3849) 2025-03-14 14:29:40 -07:00
William Fu-Hinthorn 18ed044c27 Bump patch version 2025-03-14 14:03:30 -07:00
William Fu-Hinthorn 394a9fa85f Update schema 2025-03-14 13:48:23 -07:00
William Fu-Hinthorn 9741d9bdf0 Add tests for sweeper (sync) 2025-03-14 13:43:53 -07:00
William Fu-Hinthorn 06ca07432d Add sweeper 2025-03-13 18:55:16 -07:00
Nuno Campos e757a80001 0.3.10 2025-03-13 18:14:57 -07:00
William FHandGitHub a204444905 Update handling of updates/inputs passed in as pydantic models (#3839)
- remove usage of require_at_least_one_of, we shouldn't be enforcing
presence of keys in inputs/updates, an empty dict is a valid
input/update
- ensure that values that were explcitly set/assigned in pydantic model
are saved even if equal to default value
2025-03-13 18:14:17 -07:00
Nuno Campos 4cfdf8774a Update 2025-03-13 18:02:31 -07:00
Nuno Campos beb62fc053 Fix types 2025-03-13 17:39:43 -07:00
Nuno Campos 857f3e4a38 Update handling of updates/inputs passed in as pydantic models
- remove usage of require_at_least_one_of, we shouldn't be enforcing presence of keys in inputs/updates, an empty dict is a valid input/update
- ensure that values that were explcitly set/assigned in pydantic model are saved even if equal to default value
2025-03-13 17:31:38 -07:00
6342cd1665 prebuilt: fix typo and simplify functions of examples in chat_agent_executor.py. (#3827)
**Description:**
Fix typo and simplify functions of examples.

**Issue:**
N/A

**Dependencies:**
N/A

**Dependencies:**
N/A

Co-authored-by: Eugene Yurtsev <eyurtsev@gmail.com>
2025-03-13 15:32:25 -04:00
Eugene YurtsevandGitHub baedf91836 docs: fix regexp for base64 images for llms-full (#3834) 2025-03-13 15:32:09 -04:00
ArrayPDandGitHub 190b42850f docs: Enhance get_weather() in create-react-agent-memory.ipynb (#3825)
Since we are demonstrating thread-level memory not human-in-the-loop, a
string is more straightforward and reliable than AssertionError(), when
dealing with 'Unknown Location'.
2025-03-13 18:28:20 +00:00
Eugene YurtsevandGitHub 678b512aed ci: limit downloads from pypi stats to main branch (#3835)
At some point, we can run on a cron schedule
2025-03-13 14:24:55 -04:00
William FHandGitHub c85e246c32 0.3.9 (#3836) 2025-03-13 11:22:10 -07:00
William Fu-Hinthorn 98ebc45f31 0.3.9 2025-03-13 11:21:50 -07:00
David DuongandGitHub 5ca2f358f9 feat(sdk-js): automatically write ui messages (#3833) 2025-03-13 18:22:42 +01:00
William FHandGitHub 86169c1439 Coerce nested pydantic (#3806) 2025-03-13 10:17:53 -07:00
Tat Dat Duong 36d6eed468 feat(sdk-js): automatically write ui messages 2025-03-13 18:16:49 +01:00
William FHandGitHub ef50fed6fe StreamMode in Join [sdk] (#3584) 2025-03-13 10:05:45 -07:00
William Fu-Hinthorn c0abfc7df6 lint? 2025-03-13 09:55:41 -07:00
William Fu-Hinthorn 318889bc6c Merge branch 'main' into wfh/join_stream_mode 2025-03-13 09:46:23 -07:00
William Fu-Hinthorn b9e3fd5f3e Bump js 2025-03-13 09:45:47 -07:00
William Fu-Hinthorn 8729ebc40c Merge 2025-03-13 09:37:47 -07:00
William Fu-Hinthorn 919282fead Move files 2025-03-13 09:35:26 -07:00
David DuongandGitHub cff4784ff8 feat(docs): feedback on gen ui docs (#3831) 2025-03-13 17:31:56 +01:00
Tat Dat Duong 9921e5210a feat(docs): feedback on gen ui docs 2025-03-13 17:08:10 +01:00
Vadym BardaandGitHub 048eff9f11 prebuilt: release 0.1.3 (#3830) 2025-03-13 11:46:58 -04:00
ccurmeandGitHub 8a2765c8f2 prebuilt: update type annotation for tools (#3829) 2025-03-13 15:45:44 +00:00
William Fu-Hinthorn ffbcdd1ecc weakref 2025-03-13 08:04:57 -07:00
David DuongandGitHub 108a041fa7 feat(sdk-js): add docs for generative UI (#3774) 2025-03-13 15:17:54 +01:00
Tat Dat Duong 52e3c59f07 Replace with jpg 2025-03-13 15:09:24 +01:00
David DuongandGitHub 0e17988332 feat(sdk-js): add overridable ui namespacing (#3809) 2025-03-13 15:02:07 +01:00
Tat Dat Duong 5f0d05099d Bump to 0.0.54 2025-03-13 14:50:59 +01:00
Tat Dat Duong a1739d3184 Add a separate section for Frontend and Generative UI 2025-03-13 14:47:49 +01:00
Tat Dat Duong ab38cc2cc0 Further cleanup 2025-03-13 14:36:07 +01:00
Tat Dat Duong 647833dcaa Separate segments 2025-03-13 14:34:23 +01:00
Tat Dat Duong 1f03735b7d Add image 2025-03-13 14:29:35 +01:00
Vadym BardaandGitHub d980cca59b docs: fix link checking (#3826) 2025-03-13 13:28:35 +00:00
William FHandGitHub 944b93bf61 docs: more concise readme (#3815) 2025-03-13 09:03:18 -04:00
Vadym BardaandGitHub 8aa59d002a docs: add logo to readme (#3816) 2025-03-13 09:03:01 -04:00
Tat Dat Duong ed533b32a8 Add example for CSS 2025-03-13 13:47:20 +01:00
William Fu-Hinthorn d88f59eea4 Cache 2025-03-12 18:11:42 -07:00
Nuno CamposandGitHub fc5dde6c55 Rename env var (#3813) 2025-03-12 17:07:52 -07:00
Nuno Campos 4c902d21a3 Rename env var 2025-03-12 16:58:12 -07:00
Nuno CamposandGitHub 54804af06a Make default recursion_limit configurable by env var (#3812) 2025-03-12 16:54:59 -07:00
William Fu-Hinthorn 312f026e9c Add tests 2025-03-12 16:52:23 -07:00
Nuno Campos 6973b19cc7 Make default recursion_limit configurable by env var 2025-03-12 16:45:45 -07:00
Tat Dat Duong 45ed67856f feat(sdk-js): add overridable ui namespacing 2025-03-12 23:56:07 +01:00
Vadym BardaandGitHub 74b2dbe1ea docs: add reflection prebuilt (#3805) 2025-03-12 17:54:59 +00:00
Alexey BondarenkoandGitHub 7f803df586 Add state schemas to __all__ in chat_agent_executor.py (#3798) 2025-03-12 17:54:18 +00:00
Vadym BardaandGitHub a5b43c933a docs: update README (#3799) 2025-03-12 13:43:28 -04:00
Vadym BardaandGitHub aae2fb4b85 langgraph: release 0.3.8 (#3803) 2025-03-12 13:29:21 -04:00
Vadym BardaandGitHub c20a50875d langgraph: handle pydantic state updates better for fields w/ defaults (#3783) 2025-03-12 13:19:56 -04:00
MathieuandGitHub 779553f4aa docs: fix state type in Persistence documentation (#3801)
This PR fixes the type of `foo` in the `State` class in Persistence
documentation. The type was previously defined as `int`, but the code
uses it as a `str`.

Updated the type of `foo` in the documentation to `str` to match its
actual usage in the code.

No changes to the functionality or codebase, only a documentation fix.
2025-03-12 17:14:07 +00:00
ArrayPDandGitHub 537e69608e docs: Correct a typo in create-react-agent-memory.ipynb (#3800)
Fixed a typo in create-react-agent-memory.ipynb
2025-03-12 15:17:11 +00:00
William FHandGitHub 208cd4d70e Add default TTL in store & CLI (#3786) 2025-03-12 06:14:58 -07:00
Ben BurnsandGitHub 1352e58133 chore(langgraph): add functional api test for multiple task interrupts (#3790)
While working on langchain-ai/langgraphjs#984 I ported the test I was
debugging over to python so I could compare behavior. Figured I might as
well add it to this codebase, as I don't think we had this particular
case covered previously.
2025-03-12 18:50:24 +13:00
William Fu-Hinthorn f1162ac898 Bump 2025-03-11 20:22:58 -07:00
William Fu-Hinthorn 4de8443c5c Add default TTL in store & CLI 2025-03-11 20:15:38 -07:00
Nuno CamposandGitHub 96dc39aeab 0.3.7 2025-03-11 19:46:43 -07:00
Nuno CamposandGitHub 316f8410fa Avoid validating pydantic state models when we can (#3782)
- When a pydantic input schema isued but dict input is passed in
validate it once after running hidden START node. If the input is an
instance of the input model we skip validation altogether
- When entering each node we need to create a standalone instance of the
state class, but we can now skip validation, as it's now run once
elsewhere
2025-03-11 18:23:05 -07:00
Nuno Campos 1d3926af27 Fix kafka 2025-03-11 18:13:36 -07:00
Nuno Campos e566ed4b3f Fix py 3.9
- isclass and issubclass disagree on whether something like list[str] is a class
2025-03-11 17:51:13 -07:00
Nuno Campos 14c2241853 Lint 2025-03-11 17:44:24 -07:00
Nuno Campos 2c908f1557 Avoid validating pydantic state models when we can
- When a pydantic input schema isued but dict input is passed in validate it once after running hidden START node. If the input is an instance of the input model we skip validation altogether
- When entering each node we need to create a standalone instance of the state class, but we can now skip validation, as it's now run once elsewhere
2025-03-11 17:32:54 -07:00
William FHandGitHub 5005d1c004 Default store ttl config (#3781) 2025-03-11 17:18:16 -07:00
Vadym BardaandGitHub 02a46c45c8 langgraph: support subgraphs with a single node (#3780) 2025-03-12 00:09:35 +00:00
William Fu-Hinthorn 852a129881 Default store ttl config 2025-03-11 15:58:58 -07:00
Tat Dat Duong 78348d2d9f Improve docs 2025-03-11 21:06:02 +01:00
Tat Dat Duong 44af8d5257 Add a disclaimer 2025-03-11 19:24:11 +01:00
84c956bc8c Add llms.txt (#3765)
Co-authored-by: Lance Martin <lance@langchain.dev>
2025-03-11 18:01:50 +00:00
Eugene YurtsevandGitHub b86e6b82f2 ci: add poetry check --lock to test workflow (#3777) 2025-03-11 17:42:37 +00:00
b1de5be334 docs: Fix version badge by linking it to PyPi instead of shield (#3766)
Currently the version badge showing langgraph version as PyPi shield
image is linking to the shield image. It would be more intuitive to link
it to PyPi.

---------

Co-authored-by: vbarda <vadym@langchain.dev>
2025-03-11 16:21:24 +00:00
David DuongandGitHub 0751428422 feat(sdk-js): cleanup types for ui payloads (#3773) 2025-03-11 17:04:12 +01:00
Tat Dat Duong b16f05405b Bump to 0.0.53 2025-03-11 16:59:56 +01:00
Vadym BardaandGitHub ca8d92421a langgraph: release 0.3.6 (#3775) 2025-03-11 11:34:36 -04:00
7aa9d3fd00 langgraph: use input schema from conditional edge (#2516)
Currently we ignore the input schema in the branch and instead use the
input schema from the previous node (or overall graph schema)

This change makes the input schema to branches respected. This means
that if you try to pass extra keys and they're NOT in the input schema,
you will receive an error. If you don't provide an annotation in the
router, it will fall back to the previous node's input schema / full
graph state schema

Alternative solution is to just ignore the input schema in the router
altogether (including ignoring the schema from previous node / full
graph), but personally I find it more confusing.

---------

Co-authored-by: Nuno Campos <nuno@langchain.dev>
2025-03-11 11:33:28 -04:00
Tat Dat Duong ed69f60f24 Add missing links 2025-03-11 16:18:59 +01:00
Tat Dat Duong c55f1f12bf Update docs 2025-03-11 16:18:58 +01:00
Tat Dat Duong 5d76b1d624 Add docs 2025-03-11 16:18:58 +01:00
Tat Dat Duong 857fd3578f feat(sdk-js): cleanup types for ui payloads 2025-03-11 15:02:42 +01:00
William FHandGitHub 3a4af1e573 chore(deps): bump axios from 1.7.7 to 1.8.2 in /libs/sdk-js (#3740)
Bumps [axios](https://github.com/axios/axios) from 1.7.7 to 1.8.2.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/axios/axios/releases">axios's
releases</a>.</em></p>
<blockquote>
<h2>Release v1.8.2</h2>
<h2>Release notes:</h2>
<h3>Bug Fixes</h3>
<ul>
<li><strong>http-adapter:</strong> add allowAbsoluteUrls to path
building (<a
href="https://redirect.github.com/axios/axios/issues/6810">#6810</a>)
(<a
href="https://github.com/axios/axios/commit/fb8eec214ce7744b5ca787f2c3b8339b2f54b00f">fb8eec2</a>)</li>
</ul>
<h3>Contributors to this release</h3>
<ul>
<li><!-- raw HTML omitted --> <a href="https://github.com/lexcorp16"
title="+1/-1 ([#6810](https://github.com/axios/axios/issues/6810)
)">Fasoro-Joseph Alexander</a></li>
</ul>
<h2>Release v1.8.1</h2>
<h2>Release notes:</h2>
<h3>Bug Fixes</h3>
<ul>
<li><strong>utils:</strong> move <code>generateString</code> to platform
utils to avoid importing crypto module into client builds; (<a
href="https://redirect.github.com/axios/axios/issues/6789">#6789</a>)
(<a
href="https://github.com/axios/axios/commit/36a5a620bec0b181451927f13ac85b9888b86cec">36a5a62</a>)</li>
</ul>
<h3>Contributors to this release</h3>
<ul>
<li><!-- raw HTML omitted --> <a
href="https://github.com/DigitalBrainJS" title="+51/-47
([#6789](https://github.com/axios/axios/issues/6789) )">Dmitriy
Mozgovoy</a></li>
</ul>
<h2>Release v1.8.0</h2>
<h2>Release notes:</h2>
<h3>Bug Fixes</h3>
<ul>
<li><strong>examples:</strong> application crashed when navigating
examples in browser (<a
href="https://redirect.github.com/axios/axios/issues/5938">#5938</a>)
(<a
href="https://github.com/axios/axios/commit/1260ded634ec101dd5ed05d3b70f8e8f899dba6c">1260ded</a>)</li>
<li>missing word in SUPPORT_QUESTION.yml (<a
href="https://redirect.github.com/axios/axios/issues/6757">#6757</a>)
(<a
href="https://github.com/axios/axios/commit/1f890b13f2c25a016f3c84ae78efb769f244133e">1f890b1</a>)</li>
<li><strong>utils:</strong> replace getRandomValues with crypto module
(<a
href="https://redirect.github.com/axios/axios/issues/6788">#6788</a>)
(<a
href="https://github.com/axios/axios/commit/23a25af0688d1db2c396deb09229d2271cc24f6c">23a25af</a>)</li>
</ul>
<h3>Features</h3>
<ul>
<li>Add config for ignoring absolute URLs (<a
href="https://redirect.github.com/axios/axios/issues/5902">#5902</a>)
(<a
href="https://redirect.github.com/axios/axios/issues/6192">#6192</a>)
(<a
href="https://github.com/axios/axios/commit/32c7bcc0f233285ba27dec73a4b1e81fb7a219b3">32c7bcc</a>)</li>
</ul>
<h3>Reverts</h3>
<ul>
<li>Revert &quot;chore: expose fromDataToStream to be consumable (<a
href="https://redirect.github.com/axios/axios/issues/6731">#6731</a>)&quot;
(<a
href="https://redirect.github.com/axios/axios/issues/6732">#6732</a>)
(<a
href="https://github.com/axios/axios/commit/1317261125e9c419fe9f126867f64d28f9c1efda">1317261</a>),
closes <a
href="https://redirect.github.com/axios/axios/issues/6731">#6731</a> <a
href="https://redirect.github.com/axios/axios/issues/6732">#6732</a></li>
</ul>
<h3>BREAKING CHANGES</h3>
<ul>
<li>
<p>code relying on the above will now combine the URLs instead of prefer
request URL</p>
</li>
<li>
<p>feat: add config option for allowing absolute URLs</p>
</li>
<li>
<p>fix: add default value for allowAbsoluteUrls in buildFullPath</p>
</li>
<li>
<p>fix: typo in flow control when setting allowAbsoluteUrls</p>
</li>
</ul>
<h3>Contributors to this release</h3>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/axios/axios/blob/v1.x/CHANGELOG.md">axios's
changelog</a>.</em></p>
<blockquote>
<h2><a
href="https://github.com/axios/axios/compare/v1.8.1...v1.8.2">1.8.2</a>
(2025-03-07)</h2>
<h3>Bug Fixes</h3>
<ul>
<li><strong>http-adapter:</strong> add allowAbsoluteUrls to path
building (<a
href="https://redirect.github.com/axios/axios/issues/6810">#6810</a>)
(<a
href="https://github.com/axios/axios/commit/fb8eec214ce7744b5ca787f2c3b8339b2f54b00f">fb8eec2</a>)</li>
</ul>
<h3>Contributors to this release</h3>
<ul>
<li><!-- raw HTML omitted --> <a href="https://github.com/lexcorp16"
title="+1/-1 ([#6810](https://github.com/axios/axios/issues/6810)
)">Fasoro-Joseph Alexander</a></li>
</ul>
<h2><a
href="https://github.com/axios/axios/compare/v1.8.0...v1.8.1">1.8.1</a>
(2025-02-26)</h2>
<h3>Bug Fixes</h3>
<ul>
<li><strong>utils:</strong> move <code>generateString</code> to platform
utils to avoid importing crypto module into client builds; (<a
href="https://redirect.github.com/axios/axios/issues/6789">#6789</a>)
(<a
href="https://github.com/axios/axios/commit/36a5a620bec0b181451927f13ac85b9888b86cec">36a5a62</a>)</li>
</ul>
<h3>Contributors to this release</h3>
<ul>
<li><!-- raw HTML omitted --> <a
href="https://github.com/DigitalBrainJS" title="+51/-47
([#6789](https://github.com/axios/axios/issues/6789) )">Dmitriy
Mozgovoy</a></li>
</ul>
<h1><a
href="https://github.com/axios/axios/compare/v1.7.9...v1.8.0">1.8.0</a>
(2025-02-25)</h1>
<h3>Bug Fixes</h3>
<ul>
<li><strong>examples:</strong> application crashed when navigating
examples in browser (<a
href="https://redirect.github.com/axios/axios/issues/5938">#5938</a>)
(<a
href="https://github.com/axios/axios/commit/1260ded634ec101dd5ed05d3b70f8e8f899dba6c">1260ded</a>)</li>
<li>missing word in SUPPORT_QUESTION.yml (<a
href="https://redirect.github.com/axios/axios/issues/6757">#6757</a>)
(<a
href="https://github.com/axios/axios/commit/1f890b13f2c25a016f3c84ae78efb769f244133e">1f890b1</a>)</li>
<li><strong>utils:</strong> replace getRandomValues with crypto module
(<a
href="https://redirect.github.com/axios/axios/issues/6788">#6788</a>)
(<a
href="https://github.com/axios/axios/commit/23a25af0688d1db2c396deb09229d2271cc24f6c">23a25af</a>)</li>
</ul>
<h3>Features</h3>
<ul>
<li>Add config for ignoring absolute URLs (<a
href="https://redirect.github.com/axios/axios/issues/5902">#5902</a>)
(<a
href="https://redirect.github.com/axios/axios/issues/6192">#6192</a>)
(<a
href="https://github.com/axios/axios/commit/32c7bcc0f233285ba27dec73a4b1e81fb7a219b3">32c7bcc</a>)</li>
</ul>
<h3>Reverts</h3>
<ul>
<li>Revert &quot;chore: expose fromDataToStream to be consumable (<a
href="https://redirect.github.com/axios/axios/issues/6731">#6731</a>)&quot;
(<a
href="https://redirect.github.com/axios/axios/issues/6732">#6732</a>)
(<a
href="https://github.com/axios/axios/commit/1317261125e9c419fe9f126867f64d28f9c1efda">1317261</a>),
closes <a
href="https://redirect.github.com/axios/axios/issues/6731">#6731</a> <a
href="https://redirect.github.com/axios/axios/issues/6732">#6732</a></li>
</ul>
<h3>BREAKING CHANGES</h3>
<ul>
<li>
<p>code relying on the above will now combine the URLs instead of prefer
request URL</p>
</li>
<li>
<p>feat: add config option for allowing absolute URLs</p>
</li>
<li>
<p>fix: add default value for allowAbsoluteUrls in buildFullPath</p>
</li>
</ul>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/axios/axios/commit/a9f7689b0c4b6d68c7f587c3aa376860da509d94"><code>a9f7689</code></a>
chore(release): v1.8.2 (<a
href="https://redirect.github.com/axios/axios/issues/6812">#6812</a>)</li>
<li><a
href="https://github.com/axios/axios/commit/fb8eec214ce7744b5ca787f2c3b8339b2f54b00f"><code>fb8eec2</code></a>
fix(http-adapter): add allowAbsoluteUrls to path building (<a
href="https://redirect.github.com/axios/axios/issues/6810">#6810</a>)</li>
<li><a
href="https://github.com/axios/axios/commit/98120457559e573024862e2925d56295a965ad7e"><code>9812045</code></a>
chore(sponsor): update sponsor block (<a
href="https://redirect.github.com/axios/axios/issues/6804">#6804</a>)</li>
<li><a
href="https://github.com/axios/axios/commit/72acf759373ef4e211d5299818d19e50e08c02f8"><code>72acf75</code></a>
chore(sponsor): update sponsor block (<a
href="https://redirect.github.com/axios/axios/issues/6794">#6794</a>)</li>
<li><a
href="https://github.com/axios/axios/commit/2e64afdff5c41e38284a6fb8312f2745072513a1"><code>2e64afd</code></a>
chore(release): v1.8.1 (<a
href="https://redirect.github.com/axios/axios/issues/6800">#6800</a>)</li>
<li><a
href="https://github.com/axios/axios/commit/36a5a620bec0b181451927f13ac85b9888b86cec"><code>36a5a62</code></a>
fix(utils): move <code>generateString</code> to platform utils to avoid
importing crypto...</li>
<li><a
href="https://github.com/axios/axios/commit/cceb7b1e154fbf294135c93d3f91921643bbe49f"><code>cceb7b1</code></a>
chore(release): v1.8.0 (<a
href="https://redirect.github.com/axios/axios/issues/6795">#6795</a>)</li>
<li><a
href="https://github.com/axios/axios/commit/23a25af0688d1db2c396deb09229d2271cc24f6c"><code>23a25af</code></a>
fix(utils): replace getRandomValues with crypto module (<a
href="https://redirect.github.com/axios/axios/issues/6788">#6788</a>)</li>
<li><a
href="https://github.com/axios/axios/commit/32c7bcc0f233285ba27dec73a4b1e81fb7a219b3"><code>32c7bcc</code></a>
feat: Add config for ignoring absolute URLs (<a
href="https://redirect.github.com/axios/axios/issues/5902">#5902</a>)
(<a
href="https://redirect.github.com/axios/axios/issues/6192">#6192</a>)</li>
<li><a
href="https://github.com/axios/axios/commit/4a3e26cf65bb040b7eb4577d5fd62199b0f3d017"><code>4a3e26c</code></a>
chore(config): adjust rollup config to preserve license header to
minified Ja...</li>
<li>Additional commits viewable in <a
href="https://github.com/axios/axios/compare/v1.7.7...v1.8.2">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=axios&package-manager=npm_and_yarn&previous-version=1.7.7&new-version=1.8.2)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

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 merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after
your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge
and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating
it. You can achieve the same result by closing it manually
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)
You can disable automated security fix PRs for this repo from the
[Security Alerts
page](https://github.com/langchain-ai/langgraph/network/alerts).

</details>
2025-03-10 17:50:20 -07:00
37344124e1 Fix updated_at timestamp loading (#3767)
Co-authored-by: Mohammad Mohtashim <45242107+keenborder786@users.noreply.github.com>
2025-03-10 22:20:12 +00:00
David DuongandGitHub d0f4db6ddd feat(sdk-js): use fetchClient from client in gen ui (#3761) 2025-03-10 17:48:25 +01:00
Vadym BardaandGitHub a9800aab87 checkpoint-sqlite: release 2.0.6 (#3763) 2025-03-10 11:25:38 -04:00
Vadym BardaandGitHub 9bf3fc2d0f checkpoint-sqlite: commit transactions in AsyncSqliteSaver.aput_writes (#3762) 2025-03-10 15:14:20 +00:00
Tat Dat Duong a6e4bd93ff Bump to 0.0.52 2025-03-10 15:02:06 +01:00
Tat Dat Duong 0e9c41f480 feat(sdk-js): use fetchClient from client in gen ui 2025-03-10 13:59:00 +01:00
David DuongandGitHub d4368cfa97 feat(sdk-js): api improvements for gen ui (#3760)
- merge `typedUi.create` and `typedUi.write` into `typedUi.push`
- Add mutate function in `onCustomEvent`
2025-03-10 13:31:07 +01:00
Tat Dat Duong 3808302309 Bump to 0.0.51 2025-03-10 13:25:55 +01:00
Tat Dat Duong 25019450e2 feat(sdk-js): api improvements for gen ui
- merge `typedUi.create` and `typedUi.write` into `typedUi.push`
- Add mutate function in `onCustomEvent`
2025-03-09 10:26:50 +01:00
William FHandGitHub e4c7db180e Release checkpoint-postgres (#3745) 2025-03-07 13:51:36 -08:00
3183146141 prebuilt: allow pydantic model as state schema in create_react_agent (#3559)
Inherited attributes where not considered.
Pydantic model can inherit from other pydantic models. In those cases,
inherited attributes where not considered in the check and the code
fails.

---------

Co-authored-by: vbarda <vadym@langchain.dev>
2025-03-07 16:49:51 -05:00
Brace SproulandGitHub f070b1c805 feat(sdk-js): bump version (#3743) 2025-03-07 12:44:26 -08:00
Brace SproulandGitHub 141589a7e6 Merge branch 'main' into brace/fix-tool-call-args-type 2025-03-07 12:36:54 -08:00
bracesproul be37631181 bump version 2025-03-07 12:36:22 -08:00
David DuongandGitHub 51ddc792d6 fix(sdk-js): AIMessage tool call args type (#3741) 2025-03-07 21:35:04 +01:00
Vadym BardaandGitHub 52d4f73e39 docs: fix formatting for summarization doc (#3742) 2025-03-07 15:34:48 -05:00
bracesproul 4b25e28e3e fix(sdk-js): AIMessage tool call args type 2025-03-07 12:31:18 -08:00
dependabot[bot]andGitHub 263eab9f76 chore(deps): bump axios from 1.7.7 to 1.8.2 in /libs/sdk-js
Bumps [axios](https://github.com/axios/axios) from 1.7.7 to 1.8.2.
- [Release notes](https://github.com/axios/axios/releases)
- [Changelog](https://github.com/axios/axios/blob/v1.x/CHANGELOG.md)
- [Commits](https://github.com/axios/axios/compare/v1.7.7...v1.8.2)

---
updated-dependencies:
- dependency-name: axios
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-03-07 19:23:09 +00:00
William FHandGitHub c3df8bd500 Ensure key is string (#3739)
Mainly relevenat for the in memory store.
2025-03-07 11:21:32 -08:00
William FHandGitHub d86502421d Add TTL args for SDKs (#3728) 2025-03-06 23:30:48 +00:00
William FHandGitHub cbf26a5d98 Fix indentation in docstring (#3727) 2025-03-06 13:35:20 -08:00
William FHandGitHub 09bd5990d4 Add TTL option for store items (#3704) 2025-03-06 13:20:32 -08:00
Nuno CamposandGitHub 79595d43a5 feat: bump sdk versions js and py (#3725) 2025-03-06 11:16:12 -08:00
Arjun Natarajan 49a6704bdc bump sdk versions js and py 2025-03-06 14:06:03 -05:00
David DuongandGitHub a430b7fcfb feat(cli): allow sending UI args (#3722) 2025-03-06 19:59:05 +01:00
Nuno CamposandGitHub 48c287d107 feat: update assistant version class (#3702) 2025-03-06 10:21:51 -08:00
Tat Dat Duong 0fdc787597 Bump to 0.1.75 2025-03-06 18:04:21 +01:00
Tat Dat Duong 3bd86fc6f5 Update schema 2025-03-06 17:57:51 +01:00
Tat Dat Duong f1024f7341 feat(cli): allow sending UI args 2025-03-06 17:55:42 +01:00
David DuongandGitHub f9ac88012f feat(sdk-js): loading external components (#3689)
- **chore: use prepack hook instead of prepublish**
- **feat(sdk-js): add react-ui implementation**
- **Add apiUrl, assistantId to props**
- **Bump to 0.0.46-experimental.0**
2025-03-06 17:11:50 +01:00
Tat Dat Duong 9d0186b5bf Bump to 0.0.47 2025-03-06 17:05:02 +01:00
Tat Dat Duong 40062c40df Add fallback for components defined at client level 2025-03-06 17:05:02 +01:00
Tat Dat Duong 36bbe059df Bump to 0.0.47-experimental.0 2025-03-06 17:05:01 +01:00
Tat Dat Duong 52627010cb Cache promises 2025-03-06 17:05:01 +01:00
Tat Dat Duong f6781d19ab Undo version experimental bump 2025-03-06 17:05:01 +01:00
Tat Dat Duong fcf134a452 Remove @langchain/langgraph-sdk/react-ui/types entrypoint 2025-03-06 17:05:01 +01:00
Tat Dat Duong 80331b88e0 Remove a nesting level 2025-03-06 17:05:01 +01:00
Tat Dat Duong b37f894f38 Stabilise boostrapping UI context 2025-03-06 17:05:01 +01:00
Tat Dat Duong 79de3dbad3 Fix require symbol 2025-03-06 17:05:00 +01:00
Tat Dat Duong 677fd3ce28 Update entrypoint 2025-03-06 17:05:00 +01:00
Tat Dat Duong 4ee863f30d Reexport as @langchain/langgraph-sdk/react-ui 2025-03-06 17:05:00 +01:00
Tat Dat Duong 7e060f88a2 Introduce useStreamContext 2025-03-06 17:05:00 +01:00
Tat Dat Duong f49856af0b Fix types for collect 2025-03-06 17:05:00 +01:00
Tat Dat Duong 5a7d384e2f Bump to 0.0.46-experimental.0 2025-03-06 17:05:00 +01:00
Tat Dat Duong b73b34ddd5 Add apiUrl, assistantId to props 2025-03-06 17:04:59 +01:00
Tat Dat Duong c9ffd753f5 feat(sdk-js): add react-ui implementation 2025-03-06 17:04:59 +01:00
Tat Dat Duong e85e157e8f chore: use prepack hook instead of prepublish 2025-03-06 17:04:59 +01:00
Vadym BardaandGitHub 88e7868885 prebuilt: release 0.1.2 (#3708) 2025-03-05 21:40:58 -05:00
Vadym BardaandGitHub e8dd682320 prebuilt: allow passing RunnableSequence as a model (#3706) 2025-03-06 02:37:55 +00:00
Nuno CamposandGitHub 75143b966c Make pydntic input test stricter (#3703)
- Now tests a model with inherited fields
2025-03-05 15:30:25 -08:00
Nuno Campos 490e1aab3b Don't enforce stream order 2025-03-05 15:21:16 -08:00
Arjun Natarajan 003226cef4 expose assistantbase 2025-03-05 16:47:18 -05:00
Arjun Natarajan 098a199cb9 update assistant version class 2025-03-05 15:39:34 -05:00
Nuno Campos 97f6f45993 Make pydntic input test stricter
- Now tests a model with inherited fields
2025-03-05 11:15:08 -08:00
Xiangyu YinandGitHub e8631c052a Update packages.yml to propose a new entry (#3629)
Hi, I have built a package `nodeology` that empowers researchers to
rapidly develop, test, adapt, and execute foundation AI-integrated
scientific workflows by leveraging langgraph's state machine framework.
Please take a look and let me know if it can be added into this list.
Thank you :)
2025-03-05 16:00:16 +00:00
David DuongandGitHub 16a86c8b8e feat(sdk-js): bump to 0.0.46 (#3693) 2025-03-05 11:12:50 +01:00
Tat Dat Duong 5fa6bb5f55 feat(sdk-js): bump to 0.0.46 2025-03-05 11:08:59 +01:00
David DuongandGitHub d29e9e22c7 feat(sdk-js): useStream expose callerOptions and defaultHeaders (#3688) 2025-03-05 10:42:57 +01:00
Tat Dat Duong 6990e1fcf5 retrigger checks 2025-03-05 10:36:45 +01:00
David DuongandGitHub 22e60c47cc fix(sdk-js): stream intermediate values with messages-tuple (#3664)
We still need intermediate messages to ensure the client state and
server state is in-sync as quickly as possible.
2025-03-05 10:33:05 +01:00
Nuno CamposandGitHub d9396c38ea chore(langgraph): fix typing of task decorator (#3670)
An async function of the form `def foo(P) -> T` has type `Callable[[P],
Awaitable[T]]`. The old type annotations then converted the function
into a `Callable[[P], SyncAsyncFuture[Awaitable[T]]]` which is
incorrect.

The change introduced in this commit updates the type annotations to
ensure the `Awaitable[T]` is correctly unwrapped.

I've tested it locally and confirmed it work on:

```python
@task 
def sync_fn(a: int) -> int: ...

@task 
def async_fn(a: int) -> int: ...
```

Let me know if you want me to add tests, just let me know how you test
type annotations.
2025-03-04 17:05:35 -08:00
Vadym BardaandGitHub ff60ee8c9a langgraph: release 0.3.5 (#3690) 2025-03-04 19:29:05 -05:00
Vadym BardaandGitHub 8761721fb9 langgraph: do not pass subgraph state on Command.parent updates (#3686) 2025-03-04 19:21:03 -05:00
William FHandGitHub de85e7c246 Add json schema to CLI (#3684)
So you have cute IDE autocomplete / language server checking.
2025-03-04 23:48:27 +00:00
David DuongandGitHub d333f4438f fix(sdk-js): handle threadId: undefined as controlled (#3687) 2025-03-05 00:46:26 +01:00
Tat Dat Duong af14a2abbc feat(sdk-js): useStream expose callerOptions and defaultHeaders 2025-03-05 00:29:25 +01:00
Tat Dat Duong e466c2c90c fix(sdk-js): handle threadId: undefined as controlled 2025-03-05 00:20:59 +01:00
Nuno Campos 815a67ef55 0.3.4 2025-03-04 14:33:27 -08:00
Nuno CamposandGitHub 38f1b415a0 When rehydrating a pydantic module, fallback to returning the kwargs dict (#3685)
- when the class can't be found, or can't be constructed, fallback to
returning the kwargs dict, instead of returning nothing
2025-03-04 14:31:57 -08:00
Nuno Campos ed78174adf Lint 2025-03-04 14:21:18 -08:00
Nuno Campos 5da6971a95 When rehydrating a pydantic module, fallback to returning the kwargs dict
- when the class can't be found, or can't be constructed, fallback to returning the kwargs dict, instead of returning nothing
2025-03-04 14:10:49 -08:00
256e92bfb3 Pregel.config_schema should use config_type directly when present (#3641)
- the previous behavior of re-creating model through config_specs would
lose custom annotations on config_type

---------

Co-authored-by: Eugene Yurtsev <eyurtsev@gmail.com>
2025-03-04 16:14:54 -05:00
Vadym BardaandGitHub 3d4e5c0471 sdk-py: fix decode_json in sdk (#3681) 2025-03-04 20:05:16 +00:00
ccurmeandGitHub 013a12334e docs: document langgraph-bigtool (#3682) 2025-03-04 20:03:13 +00:00
ccurmeandGitHub c7211e03e9 docs: fix typo (#3677)
https://platform.openai.com/docs/guides/embeddings#embedding-models
2025-03-04 19:05:56 +00:00
Nuno Campos ffc916e38c 0.3.3 2025-03-04 10:22:01 -08:00
Nuno CamposandGitHub 03bf149ebd Retry condition for resuming flag should apply only to top graphs (#3676) 2025-03-04 10:20:35 -08:00
Nuno Campos 137dcce5b5 Retry condition for resuming flag should apply only to top graphs 2025-03-04 09:51:13 -08:00
JP-EllisandGitHub 48164a95da chore: whitespace cleanup (#3671)
Uncovered while working on #3670. Feel free to close if too minor to
merge.

Signed-off-by: JP-Ellis <josh@jpellis.me>
2025-03-04 23:45:47 +13:00
JP-Ellis 3926e83884 chore(langgraph): fix typing of task decorator
An async function of the form `def foo(P) -> T` has type `Callable[[P],
Awaitable[T]]`. The old type annotations then converted the function
into a `Callable[[P], SyncAsyncFuture[Awaitable[T]]]` which is
incorrect.

The change introduced in this commit updates the type annotations to
ensure the `Awaitable[T]` is correctly unwrapped.

Signed-off-by: JP-Ellis <josh@jpellis.me>
2025-03-04 16:54:53 +11:00
Nuno CamposandGitHub 43709a16bf When retrying a previously attempted run, resume from previous checkpoint (#3668)
- Ignore input if being passed in when a checkpoint already exists for
that run_id
2025-03-03 17:43:11 -08:00
Nuno Campos d98c7248dc Oops 2025-03-03 17:33:27 -08:00
Nuno Campos ac2736f18e When retrying a previously attempted run, resume from previous checkpoint
- Ignore input if being passed in when a checkpoint already exists for that run_id
2025-03-03 17:31:45 -08:00
Tat Dat Duong fc130a52ef fix(sdk-js): stream intermediate values with messages-tuple
We still need intermediate messages to ensure the client state and server state is in-sync as quickly as possible.
2025-03-03 17:19:45 +01:00
Vadym BardaandGitHub 7d025e42ef langgraph: release 0.3.2 (#3649) 2025-02-28 18:13:23 -05:00
Vadym BardaandGitHub 4e9ed36f76 langgraph: unset resuming flag to avoid propagating to subgraphs (#3647) 2025-02-28 23:11:54 +00:00
Vadym BardaandGitHub 5d73df6133 sdk-py: fix docstring for runs.list (#3646)
Fixes #3645
2025-02-28 15:43:49 -05:00
David DuongandGitHub fcc1210945 docs: fix deprecation warning style (#3639)
messed up an indentation that was causing the warning to not render
correctly
2025-02-28 16:34:35 +01:00
Arjun Natarajan da5ee30bef fix deprecation warning style 2025-02-28 10:30:03 -05:00
jessicaouandGitHub 57ff761cff Update Adopters title in menu bar (#3634) 2025-02-28 09:17:14 -05:00
jessicaouandGitHub f0a46bc3e3 Update adopters.md title (#3635) 2025-02-28 09:16:58 -05:00
Vadym BardaandGitHub b1587d24ed docs: update langgraph api constraints (#3633) 2025-02-27 13:59:36 -05:00
Vadym BardaandGitHub a1c676707c cli: update api version (#3632) 2025-02-27 13:57:07 -05:00
Vadym BardaandGitHub 38b19fa99c docs: update README (#3626) 2025-02-27 10:47:20 -05:00
Vadym BardaandGitHub 3c3428da78 docs: update installs in how-tos/tutorials (#3624) 2025-02-27 10:25:31 -05:00
Vadym BardaandGitHub bb0125b4bb ci: re-enable notebook runner on latest version (#3611) 2025-02-27 10:09:57 -05:00
Vadym BardaandGitHub 7580ad6005 langgraph: release 0.3.1 (#3623) 2025-02-27 10:08:02 -05:00
Vadym BardaandGitHub eb8aa6b761 langgraph: add prebuilt dependency (#3622) 2025-02-27 10:07:04 -05:00
Vadym BardaandGitHub fe0de3e07e ci: update release workflow for prebuilt (#3621) 2025-02-27 09:49:15 -05:00
David DuongandGitHub f51831f48e docs: update getting started docs for studio (#3542) 2025-02-27 15:41:52 +01:00
Vadym BardaandGitHub 745eb90a6d prebuilt: remove langgraph dependency (#3620) 2025-02-27 09:41:43 -05:00
Arjun Natarajan f136e40065 fix link 2025-02-26 21:47:32 -05:00
Arjun Natarajan de888b4032 make reference to langsmith a bit cleareR 2025-02-26 21:33:45 -05:00
Arjun Natarajan 7cb0bd52e8 add link to cli 2025-02-26 21:31:33 -05:00
Vadym BardaandGitHub 3778f6113c prebuilt: release 0.1.0 (#3610) 2025-02-26 18:48:03 -05:00
Vadym BardaandGitHub 24c13c211e langgraph: separate prebuilt into a standalone package (#3589) 2025-02-26 18:33:07 -05:00
Vadym BardaandGitHub 2e36189c16 langgraph: release 0.2.76 (#3609) 2025-02-26 16:41:28 -05:00
Arjun Natarajan 302aa8b9cb clean up docs 2025-02-26 15:57:05 -05:00
Vadym BardaandGitHub dac11f875c langgraph: fix get_state(subgraphs=True) for checkpointer=True (#3607) 2025-02-26 20:43:46 +00:00
andrestorres123andGitHub 264be423f9 docs: Add Delve Taxonomy Generator package to the Prebuilt Agents (#3606) 2025-02-26 19:03:51 +00:00
HackHuangandGitHub 9a05600ff9 docs(concepts) : Add a tutorial link for map-reduce (#3577)
Update `low_level.md`: Add a tutorial link for map-reduce, now it's
perfect !!!
2025-02-26 12:23:02 -05:00
Eugene YurtsevandGitHub 56dd728975 docs: remove one more beta (#3601) 2025-02-26 12:22:22 -05:00
Eugene YurtsevandGitHub c157c956f4 docs: prebuilt add github stars (#3603) 2025-02-26 12:22:08 -05:00
Vadym BardaandGitHub dd293dad30 langgraph: release 0.2.75 (#3602) 2025-02-26 11:47:16 -05:00
Vadym BardaandGitHub 30811d7841 langgraph: add py.typed files to modules (#3600) 2025-02-26 16:41:51 +00:00
Vadym BardaandGitHub 28a705b71a docs: update requirements (#3598) 2025-02-26 10:35:16 -05:00
Vadym BardaandGitHub 3b8130b96f docs: add swarm (#3597) 2025-02-26 09:59:29 -05:00
Harrison ChaseandGitHub 94fc0adb05 faq about no langsmith (#3596) 2025-02-26 09:43:28 -05:00
Nuno CamposandGitHub 162e96262f langgraph: stream_mode=messages should not emit input or state messages (#3591)
- any messages seen in inputs in on_chain_start should not be emitted
2025-02-25 19:09:57 -08:00
Nuno Campos 1bb0037450 langgraph: stream_mode=messages should not emit input or state messages
- any messages seen in inputs in on_chain_start should not be emitted
2025-02-25 19:00:33 -08:00
Nuno CamposandGitHub 50c53d3120 checkpoint-sqlite: update aiosqlite bounds (#3540)
aiosqlite 0.21.0 was released on Feb 2

It seems to be a maintenance release:
https://github.com/omnilib/aiosqlite/blob/main/CHANGELOG.md#v0210
2025-02-25 16:56:10 -08:00
Nuno CamposandGitHub 0b7b849633 Update adopters.md to include Cisco Outshift (#3573) 2025-02-25 16:47:52 -08:00
Nuno CamposandGitHub 678eb5cdbe pregel: update validation error messages (#3517)
OK not including as well, but this was useful for troubleshooting as a
new user (especially before there were any examples)
2025-02-25 16:45:57 -08:00
Arjun Natarajan a0969b61a3 add back desktop docs in dedicated section w deprecation warning 2025-02-25 16:08:21 -05:00
Arjun Natarajan e679ab73c4 fix broken docs part 2025-02-25 15:53:23 -05:00
William Fu-Hinthorn b5a981d82d Review 2025-02-25 11:58:01 -08:00
Andrew NguonlyandGitHub bdf1215ced docs: Add docs for DD_API_KEY env var (#3585) 2025-02-25 11:24:59 -08:00
William Fu-Hinthorn f679348327 StreamMode in Join [sdk] 2025-02-25 11:14:38 -08:00
William FHandGitHub cba1852720 Fix typo (#3583) 2025-02-25 18:19:48 +00:00
David DuongandGitHub edf707be51 feat(react): support interrupt_before/after (#3582) 2025-02-25 18:06:25 +01:00
Tat Dat Duong d3b9a96504 feat(react): support interrupt_before/after 2025-02-25 17:57:12 +01:00
David DuongandGitHub 3257e5ae76 fix(docs): remove @langchain/langgraph/web import in branching example (#3580) 2025-02-25 16:18:09 +01:00
Tat Dat Duong bedd0eb286 fix(docs): remove @langchain/langgraph/web import in branching example 2025-02-25 16:11:09 +01:00
David DuongandGitHub 42f0c351fd fix(react): avoid implicitly streaming values if not needed (#3579) 2025-02-25 16:07:41 +01:00
Tat Dat Duong a290984362 fix(react): avoid implicitly streaming values if not needed 2025-02-25 15:58:21 +01:00
David DuongandGitHub f1d6fd184f fix(docs): typo for npm install command (#3578) 2025-02-25 15:53:49 +01:00
Tat Dat Duong 503f716104 fix(docs): typo for npm install command 2025-02-25 15:49:50 +01:00
jessicaouandGitHub b8fafa2795 Update adopters.md to include Cisco Outshift 2025-02-24 18:34:38 -08:00
Nuno Campos 515c34d1ce Fix docs build 2025-02-24 17:14:42 -08:00
Nuno CamposandGitHub 5ea0d49d4d Add docs page on lgp scalability / resilience (#3510) 2025-02-24 16:52:37 -08:00
Andrew NguonlyandGitHub d9f71ef8b3 docs: Add section for Add or Remove GitHub Repositories (#3571) 2025-02-24 16:12:03 -08:00
Eugene YurtsevandGitHub 8658a5dc0b docs: add pregel conceptual doc (#3516)
* Update API Reference for Pregel
* Add conceptual page for Pregel
* The content for the two is very similar at the moment (i.e.,
duplicated content). This is usually a bad sign, but in this case I'm OK
duplicating information along both paths since the underlying algorithm
sets us apart from other implementations.
2025-02-24 17:48:03 -05:00
William FHandGitHub 2afee13d9e Docs on custom routes (#3568) 2025-02-24 11:21:41 -08:00
HackHuangandGitHub f7d9daa4eb docs(multi_agent.md) : Fix some code snippets (#3565)
Hey buddy! You forgot to import the `Command` in some code snippets.
2025-02-24 13:28:56 -05:00
HackHuangandGitHub fb28aa6d4b docs(concepts) : update human_in_the_loop.md (#3558)
Fix the false output result.
2025-02-24 04:52:48 +00:00
jessicaouandGitHub 3488945cdf Update adopters.md to include Klarna (#3560) 2025-02-24 04:39:25 +00:00
Theodore NiandGitHub e6681bc175 Merge branch 'main' into update-aiosqlite-bounds 2025-02-22 06:16:58 -06:00
Sudar Selva Ganesh MandGitHub 57e8081921 chore(docs): make webhooks platform doc more readable (#3551)
1. Provided additional context on webhook usage and setup.
2. Structured supported endpoints into a table for better readability.
2025-02-23 00:17:21 +13:00
Nino RisteskiandGitHub 078b335448 chore(checkpoint): fix typos in README (#3553) 2025-02-22 11:10:09 +00:00
Arjun Natarajan 6615c6bb0d remove other references to desktop
:
2025-02-20 18:16:49 -08:00
Arjun Natarajan 32df0016ee update getting started docs 2025-02-20 18:00:26 -08:00
Vadym BardaandGitHub 39b2bb9c8f update opendeepresearch name (#3541) 2025-02-20 18:16:40 -05:00
5eb793d7d8 Update packages w/ Open Deep Research (#3539)
Here: 
https://github.com/langchain-ai/open_deep_research

---------

Co-authored-by: Vadym Barda <vadym@langchain.dev>
2025-02-20 15:04:11 -08:00
Theodore Ni a9cdb9c948 checkpoint-sqlite: update aiosqlite bounds 2025-02-20 14:51:51 -08:00
David DuongandGitHub 3dac1894cc fix(react): handle non-concatenable messages (#3536) 2025-02-20 21:28:02 +01:00
Tat Dat Duong 1500764b46 fix(react): handle non-concatenable messages 2025-02-20 21:24:00 +01:00
Vadym BardaandGitHub fbb89325f9 langgraph: allow passing config_schema to create_react_agent (#3534) 2025-02-20 19:36:17 +00:00
David DuongandGitHub 187c71a812 feat(react): add interrupt docs (#3533) 2025-02-20 20:10:35 +01:00
Tat Dat Duong b09b33070e feat(docs): add interrupt docs 2025-02-20 20:03:52 +01:00
Vadym BardaandGitHub 31a7bcf750 langgraph: handle non-overlapping subgraph updates in Command.PARENT (#3521) 2025-02-20 13:15:27 -05:00
langchain-infraandGitHub 1a12b0309c docs: add langgraph platform ips (#3528) 2025-02-19 22:52:02 -05:00
infra 660c15d072 docs: add langgraph platform ips 2025-02-19 22:39:54 -05:00
langchain-infraandGitHub 4a59da7cfd docs: add langgraph platform ips (#3527) 2025-02-19 22:27:38 -05:00
infra aacc079eed fmt 2025-02-19 22:23:42 -05:00
langchain-infraandGitHub 3d70a4ed65 Delete libs/cli/langgraph_cli/docker-compose.yaml 2025-02-19 22:16:10 -05:00
infra caad15f7ae docs: add langgraph platform ips 2025-02-19 22:14:29 -05:00
infra 1f4d4e7bfd docs: add langgraph platform ips 2025-02-19 22:14:09 -05:00
David DuongandGitHub 5b0bf861ac feat(react): add interrupts, clean up generic types (#3526) 2025-02-20 03:17:48 +01:00
Tat Dat Duong a69ea47ac2 Bump to 0.0.44 2025-02-20 03:06:11 +01:00
Tat Dat Duong f83d18188f feat(react): add interrupts, clean up generic types 2025-02-20 03:06:10 +01:00
David DuongandGitHub 688efdea3d fix(react): avoid streaming messages if they are not needed (#3525) 2025-02-20 03:05:46 +01:00
David DuongandGitHub 6641dcd3c9 fix(react): output non-abort errors in console, handle bogus message type (#3524) 2025-02-20 02:45:18 +01:00
William FHandGitHub ad14d92f5e [cli] Bump api floor (#3523) 2025-02-20 00:26:15 +00:00
Tat Dat Duong c63fbbfaa6 fix(react): avoid streaming messages if they are not needed 2025-02-20 01:22:08 +01:00
Tat Dat Duong 577b4413a9 fix(react): output non-abort errors in console, handle bogus message type 2025-02-20 01:20:19 +01:00
William FHandGitHub 277c341817 Configure loopback transports (#3522) 2025-02-19 15:58:57 -08:00
mathislindnerandGitHub 88d0f41c55 docs: Update map-reduce-fixed-typo.ipynb (#3509)
fixed a typo:
We will use this an edge in the graph
to 
We will use this as an edge in the graph
2025-02-19 17:28:21 -05:00
Eugene YurtsevandGitHub 0a4953c4bc Update index.md (#3519) 2025-02-19 21:52:17 +00:00
Eugene YurtsevandGitHub 059e16789c docs: fix anchor links (#3518) 2025-02-19 16:48:41 -05:00
Eugene Yurtsev 4dc8f813e7 x 2025-02-19 16:16:14 -05:00
Nuno Campos f613fdfcbc Add sections on postgres and redis 2025-02-19 11:25:56 -08:00
David DuongandGitHub 41b36dcf3f docs: playground studio integration (#3514) 2025-02-19 19:49:37 +01:00
Arjun Natarajan b39dcd7fad pr feedback 2025-02-19 10:43:02 -08:00
Arjun Natarajan c0ad92b6db update title 2025-02-19 10:20:13 -08:00
Eugene YurtsevandGitHub b8d25bc0ed docs build: test api link generation (#3513) 2025-02-19 13:15:53 -05:00
Arjun Natarajan 7884401ec8 docs for playground studio integration 2025-02-19 09:43:21 -08:00
David DuongandGitHub a3bc029344 feat(sdk-js/react): make configurable typed via generics (#3511) 2025-02-19 18:19:51 +01:00
Tat Dat Duong 15e67fdd57 feat(sdk-js/react): make configurable typed 2025-02-19 17:27:26 +01:00
Nuno Campos 265466184c Add docs page on lgp scalability / resilience 2025-02-19 08:24:36 -08:00
275 changed files with 29904 additions and 10201 deletions
+1 -2
View File
@@ -4,7 +4,7 @@ on:
workflow_call:
env:
POETRY_VERSION: "1.7.1"
POETRY_VERSION: "2.1.2"
jobs:
build:
@@ -71,4 +71,3 @@ jobs:
working-directory: libs/cli/js-examples
run: |
langgraph build -t langgraph-test-e
+1 -7
View File
@@ -9,7 +9,7 @@ on:
description: "From which folder this pipeline executes"
env:
POETRY_VERSION: "1.7.1"
POETRY_VERSION: "2.1.2"
# This env var allows us to get inline annotations when ruff has complaints.
RUFF_OUTPUT_FORMAT: github
@@ -50,12 +50,6 @@ jobs:
working-directory: ${{ inputs.working-directory }}
run: poetry check
- name: Check lock file
if: steps.changed-files.outputs.all
shell: bash
working-directory: ${{ inputs.working-directory }}
run: poetry lock --check
- name: Install dependencies
if: steps.changed-files.outputs.all
# Also installs dev/lint/test/typing dependencies, to ensure we have
+1 -1
View File
@@ -9,7 +9,7 @@ on:
description: "From which folder this pipeline executes"
env:
POETRY_VERSION: "1.7.1"
POETRY_VERSION: "2.1.2"
jobs:
build:
+1 -1
View File
@@ -4,7 +4,7 @@ on:
workflow_call:
env:
POETRY_VERSION: "1.7.1"
POETRY_VERSION: "2.1.2"
jobs:
build:
+1 -1
View File
@@ -9,7 +9,7 @@ on:
description: "From which folder this pipeline executes"
env:
POETRY_VERSION: "1.7.1"
POETRY_VERSION: "2.1.2"
PYTHON_VERSION: "3.10"
jobs:
+1 -1
View File
@@ -4,7 +4,7 @@ on:
workflow_call:
env:
POETRY_VERSION: "1.7.1"
POETRY_VERSION: "2.1.2"
jobs:
build:
+1 -1
View File
@@ -8,7 +8,7 @@ on:
- "libs/**"
env:
POETRY_VERSION: "1.7.1"
POETRY_VERSION: "2.1.2"
jobs:
benchmark:
+2 -2
View File
@@ -6,7 +6,7 @@ on:
- "libs/**"
env:
POETRY_VERSION: "1.7.1"
POETRY_VERSION: "2.1.2"
jobs:
benchmark:
@@ -43,7 +43,7 @@ jobs:
run: |
{
echo 'OUTPUT<<EOF'
make -s benchmark
make -s benchmark-fast
echo EOF
} >> "$GITHUB_OUTPUT"
- name: Compare benchmarks
+42 -1
View File
@@ -17,7 +17,7 @@ concurrency:
cancel-in-progress: true
env:
POETRY_VERSION: "1.7.1"
POETRY_VERSION: "2.1.2"
jobs:
changes:
@@ -39,6 +39,7 @@ jobs:
- 'libs/checkpoint-sqlite/**'
- 'libs/checkpoint-postgres/**'
- 'libs/scheduler-kafka/**'
- 'libs/prebuilt/**'
sdk-js:
- 'libs/sdk-js/**'
@@ -56,6 +57,7 @@ jobs:
"libs/checkpoint-sqlite",
"libs/checkpoint-postgres",
"libs/scheduler-kafka",
"libs/prebuilt",
]
if: needs.changes.outputs.python == 'true'
uses: ./.github/workflows/_lint.yml
@@ -74,6 +76,7 @@ jobs:
"libs/checkpoint",
"libs/checkpoint-sqlite",
"libs/checkpoint-postgres",
"libs/prebuilt",
]
if: needs.changes.outputs.python == 'true'
uses: ./.github/workflows/_test.yml
@@ -111,6 +114,42 @@ jobs:
- name: Run check_sdk_methods script
run: python .github/scripts/check_sdk_methods.py
check-schema:
needs: changes
if: needs.changes.outputs.python == 'true'
name: "Check CLI schema hasn't changed #${{ matrix.python-version }}"
runs-on: ubuntu-latest
strategy:
matrix:
python-version:
- "3.11"
steps:
- uses: actions/checkout@v4
- name: Set up Python ${{ matrix.python-version }} + Poetry ${{ env.POETRY_VERSION }}
uses: "./.github/actions/poetry_setup"
with:
python-version: "3.11"
poetry-version: ${{ env.POETRY_VERSION }}
cache-key: schema-check-cli
- name: Install CLI dependencies
run: |
cd libs/cli
poetry install
- name: Generate schema and check for changes
run: |
cd libs/cli
# Create a temporary copy of the current schema
cp schemas/schema.json schemas/schema.current.json
# Generate new schema
poetry run python generate_schema.py
# Compare the new schema with the original
if ! diff -q schemas/schema.json schemas/schema.current.json > /dev/null; then
echo "Error: Langgraph.json configuration schema has changed. Please run 'poetry run python generate_schema.py' in the libs/cli directory and commit the changes."
diff schemas/schema.json schemas/schema.current.json
exit 1
fi
echo "Schema check passed - no changes detected"
integration-test:
needs: changes
if: needs.changes.outputs.python == 'true'
@@ -177,6 +216,8 @@ jobs:
test,
test-langgraph,
test-scheduler-kafka,
check-sdk-methods,
check-schema,
integration-test,
test-js,
]
+14 -22
View File
@@ -10,7 +10,7 @@ on:
workflow_dispatch:
env:
POETRY_VERSION: "1.7.1"
POETRY_VERSION: "2.1.2"
permissions:
contents: read
@@ -63,35 +63,16 @@ jobs:
poetry-version: ${{ env.POETRY_VERSION }}
cache-key: docs
- name: Use Node.js
uses: actions/setup-node@v3
with:
node-version: "22"
cache: "yarn"
cache-dependency-path: docs/yarn.lock
- name: Install dependencies
run: |
yarn
poetry install --with test --with docs --no-root
poetry run pip install -U \
pytest \
pytest-check-links \
GitPython \
"git+https://github.com/benjamincburns/markdown-exec.git@cc0d39d737e5ffd4b83d23cd8729d7ea16e363c8"
# we run this installation only for internal PRs
# as GITHUB_TOKEN is not available for PRs from outside contributors
if [ -n "${GITHUB_TOKEN}" ]; then
poetry run pip install "git+https://${GITHUB_TOKEN}@github.com/langchain-ai/mkdocs-material-insiders.git"
fi
poetry run jupyter kernelspec list
poetry run python3 -m ipykernel install --user --name=python3
npm install -g tslab
poetry run tslab install --python=python3
poetry run jupyter kernelspec list
- name: Run unit tests
# Run unit tests on the docs build pipeline
run: make tests
@@ -102,7 +83,14 @@ jobs:
- name: Build llms-text
run: make llms-text
- name: Build site
run: make build-docs
run: |
# If this is main branch, then we want to download stats. we do this
# with the env variable DOWNLOAD_STATS=true
if [ "${{ github.ref }}" == "refs/heads/main" ]; then
DOWNLOAD_STATS=true make build-docs
else
make build-docs
fi
env:
MKDOCS_GIT_COMMITTERS_APIKEY: ${{ secrets.MKDOCS_GIT_COMMITTERS_APIKEY }}
OPENAI_API_KEY: sf-proj-1234567890 # fake placeholder, shouldn't actually be used
@@ -111,12 +99,13 @@ jobs:
env:
LANGCHAIN_API_KEY: test
run: |
if [ "${{ github.event_name }}" == "schedule" ] || [ "${{ github.event_name }}" == "workflow_dispatch" ] || ([ "${{ github.event_name }}" == "push" ] && [ "${{ github.ref }}" == "refs/heads/main" ]); then
if [ "${{ github.event_name }}" == "schedule" ]; then
echo "Running link check on all HTML files matching notebooks in docs directory..."
poetry run pytest -v \
--check-links-ignore "https://(api|web|docs)\.smith\.langchain\.com/.*" \
--check-links-ignore "https://academy\.langchain\.com/.*" \
--check-links-ignore "https://x.com/.*" \
--check-links-ignore "https://twitter.com/.*" \
--check-links-ignore "https://github\.com/.*" \
--check-links-ignore "http://localhost:8123/.*" \
--check-links-ignore "http://localhost:2024.*" \
@@ -126,6 +115,7 @@ jobs:
--check-links-ignore "https://openai\.com/.*" \
--check-links-ignore "https://www\.uber\.com/.*" \
--check-links-ignore "https://pepy\.tech/.*" \
--check-links-ignore "docs/docs/static/wordmark_*" \
--check-links $(find site -name "index.html" | grep -v 'storm/index.html')
else
@@ -143,8 +133,10 @@ jobs:
--check-links-ignore "http://localhost:2024.*" \
--check-links-ignore "http://127.0.0.1:.*" \
--check-links-ignore "https://x.com/.*" \
--check-links-ignore "https://twitter.com/.*" \
--check-links-ignore "https://github\.com/.*" \
--check-links-ignore "/.*\.(ipynb|html)$" \
--check-links-ignore "docs/docs/static/wordmark_*" \
--check-links ${CHANGED_FILES} \
|| ([ $? = 5 ] && exit 0 || exit $?)
else
+6 -6
View File
@@ -12,7 +12,7 @@ on:
workflow_dispatch:
env:
POETRY_VERSION: "1.7.1"
POETRY_VERSION: "2.1.2"
jobs:
markdown-link-check:
@@ -42,8 +42,8 @@ jobs:
- name: Check README.md is in sync
run: |
if ! diff -q README.md libs/langgraph/README.md >/dev/null; then
echo "README.md is out of sync with libs/langgraph/README.md"
diff -C 3 README.md libs/langgraph/README.md
exit 1
fi
if ! diff -q README.md libs/langgraph/README.md >/dev/null; then
echo "README.md is out of sync with libs/langgraph/README.md"
diff -C 3 README.md libs/langgraph/README.md
exit 1
fi
+6 -2
View File
@@ -10,7 +10,7 @@ on:
env:
PYTHON_VERSION: "3.11"
POETRY_VERSION: "1.7.1"
POETRY_VERSION: "2.1.2"
jobs:
build:
@@ -195,7 +195,11 @@ jobs:
"$PKG_NAME==$VERSION" \
)
if [[ "$PKG_NAME" == *checkpoint* ]]; then
if [[ "$PKG_NAME" == *prebuilt* ]]; then
poetry run pip install langgraph
fi
if [[ "$PKG_NAME" == *checkpoint* || "$PKG_NAME" == *prebuilt* ]]; then
# since checkpoint packages are namespace packages, import them with . convention
# i.e. import langgraph.checkpoint or langgraph.checkpoint.sqlite
IMPORT_NAME="$(echo "$PKG_NAME" | sed s/-/./g)"
+10 -10
View File
@@ -9,7 +9,7 @@ on:
type: string
description: "JSON string of changed files"
schedule:
- cron: '0 13 * * *'
- cron: "0 13 * * *"
defaults:
run:
@@ -30,12 +30,12 @@ jobs:
uses: "./.github/actions/poetry_setup"
with:
python-version: 3.11
poetry-version: 1.7.1
poetry-version: 2.1.2
cache-key: test-langgraph-notebooks
- name: Install dependencies
run: |
poetry install --with test
poetry install --with test --no-root
poetry run pip install jupyter
- name: Start services
@@ -57,13 +57,13 @@ jobs:
env:
# these won't actually be used because of the VCR cassettes
# but need to set them to avoid triggering getpass()
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
TAVILY_API_KEY: ${{ secrets.TAVILY_API_KEY }}
LANGSMITH_API_KEY: ${{ secrets.LANGSMITH_API_KEY }}
NOMIC_API_KEY: ${{ secrets.NOMIC_API_KEY }}
COHERE_API_KEY: ${{ secrets.COHERE_API_KEY }}
FIREWORKS_API_KEY: ${{ secrets.FIREWORKS_API_KEY }}
OPENAI_API_KEY: "very-secret-key"
ANTHROPIC_API_KEY: "very-secret-key"
TAVILY_API_KEY: "very-secret-key"
LANGSMITH_API_KEY: "very-secret-key"
NOMIC_API_KEY: "very-secret-key"
COHERE_API_KEY: "very-secret-key"
FIREWORKS_API_KEY: "very-secret-key"
run: |
if [ "${{ github.event_name }}" = "workflow_dispatch" ] || [ "${{ github.event_name }}" = "schedule" ]; then
echo "Running all notebooks"
-29
View File
@@ -1,29 +0,0 @@
name: Check File Size
on:
push:
branches:
- main
pull_request:
branches:
- main
workflow_dispatch:
jobs:
file-size-check:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Get changed files
id: changed-files
uses: tj-actions/changed-files@v44
- name: Filter by size
# TODO: roll back the web voyager hack
run: |
large_added_files=$(find ${{ steps.changed-files.outputs.added_files }} -maxdepth 0 -size +1M | grep -v "web_voyager" || true)
if [ -n "$large_added_files" ]; then
echo "Large files added: $large_added_files"
echo "# Large files added:" >> $GITHUB_STEP_SUMMARY
echo "$large_added_files" >> $GITHUB_STEP_SUMMARY
exit 1
fi
+47 -299
View File
@@ -1,339 +1,87 @@
# 🦜🕸️LangGraph
<picture class="github-only">
<source media="(prefers-color-scheme: light)" srcset="https://langchain-ai.github.io/langgraph/static/wordmark_dark.svg">
<source media="(prefers-color-scheme: dark)" srcset="https://langchain-ai.github.io/langgraph/static/wordmark_light.svg">
<img alt="LangGraph Logo" src="https://langchain-ai.github.io/langgraph/static/wordmark_dark.svg" width="80%">
</picture>
![Version](https://img.shields.io/pypi/v/langgraph)
<div>
<br>
</div>
[![Version](https://img.shields.io/pypi/v/langgraph.svg)](https://pypi.org/project/langgraph/)
[![Downloads](https://static.pepy.tech/badge/langgraph/month)](https://pepy.tech/project/langgraph)
[![Open Issues](https://img.shields.io/github/issues-raw/langchain-ai/langgraph)](https://github.com/langchain-ai/langgraph/issues)
[![Docs](https://img.shields.io/badge/docs-latest-blue)](https://langchain-ai.github.io/langgraph/)
⚡ Building language agents as graphs ⚡
> [!NOTE]
> Looking for the JS version? See the [JS repo](https://github.com/langchain-ai/langgraphjs) and the [JS docs](https://langchain-ai.github.io/langgraphjs/).
## Overview
LangGraph — used by Replit, Uber, LinkedIn, GitLab and more — is a low-level orchestration framework for building controllable agents. While langchain provides integrations and composable components to streamline LLM application development, the LangGraph library enables agent orchestration — offering customizable architectures, long-term memory, and human-in-the-loop to reliably handle complex tasks.
[LangGraph](https://langchain-ai.github.io/langgraph/) is a library for building
stateful, multi-actor applications with LLMs, used to create agent and multi-agent
workflows. Check out an introductory tutorial [here](https://langchain-ai.github.io/langgraph/tutorials/introduction/).
LangGraph is inspired by [Pregel](https://research.google/pubs/pub37252/) and [Apache Beam](https://beam.apache.org/). The public interface draws inspiration from [NetworkX](https://networkx.org/documentation/latest/). LangGraph is built by LangChain Inc, the creators of LangChain, but can be used without LangChain.
### Why use LangGraph?
LangGraph powers [production-grade agents](https://www.langchain.com/built-with-langgraph), trusted by Linkedin, Uber, Klarna, GitLab, and many more. LangGraph provides fine-grained control over both the flow and state of your agent applications. It implements a central [persistence layer](https://langchain-ai.github.io/langgraph/concepts/persistence/), enabling features that are common to most agent architectures:
- **Memory**: LangGraph persists arbitrary aspects of your application's state,
supporting memory of conversations and other updates within and across user
interactions;
- **Human-in-the-loop**: Because state is checkpointed, execution can be interrupted
and resumed, allowing for decisions, validation, and corrections at key stages via
human input.
Standardizing these components allows individuals and teams to focus on the behavior
of their agent, instead of its supporting infrastructure.
Through [LangGraph Platform](#langgraph-platform), LangGraph also provides tooling for
the development, deployment, debugging, and monitoring of your applications.
LangGraph integrates seamlessly with
[LangChain](https://python.langchain.com/docs/introduction/) and
[LangSmith](https://docs.smith.langchain.com/) (but does not require them).
To learn more about LangGraph, check out our first LangChain Academy
course, *Introduction to LangGraph*, available for free
[here](https://academy.langchain.com/courses/intro-to-langgraph).
### LangGraph Platform
[LangGraph Platform](https://langchain-ai.github.io/langgraph/concepts/langgraph_platform) is infrastructure for deploying LangGraph agents. It is a commercial solution for deploying agentic applications to production, built on the open-source LangGraph framework. The LangGraph Platform consists of several components that work together to support the development, deployment, debugging, and monitoring of LangGraph applications: [LangGraph Server](https://langchain-ai.github.io/langgraph/concepts/langgraph_server) (APIs), [LangGraph SDKs](https://langchain-ai.github.io/langgraph/concepts/sdk) (clients for the APIs), [LangGraph CLI](https://langchain-ai.github.io/langgraph/concepts/langgraph_cli) (command line tool for building the server), and [LangGraph Studio](https://langchain-ai.github.io/langgraph/concepts/langgraph_studio) (UI/debugger).
See deployment options [here](https://langchain-ai.github.io/langgraph/concepts/deployment_options/)
(includes a free tier).
Here are some common issues that arise in complex deployments, which LangGraph Platform addresses:
- **Streaming support**: LangGraph Server provides [multiple streaming modes](https://langchain-ai.github.io/langgraph/concepts/streaming) optimized for various application needs
- **Background runs**: Runs agents asynchronously in the background
- **Support for long running agents**: Infrastructure that can handle long running processes
- **[Double texting](https://langchain-ai.github.io/langgraph/concepts/double_texting)**: Handle the case where you get two messages from the user before the agent can respond
- **Handle burstiness**: Task queue for ensuring requests are handled consistently without loss, even under heavy loads
## Installation
```shell
```bash
pip install -U langgraph
```
## Example
Let's build a tool-calling [ReAct-style](https://langchain-ai.github.io/langgraph/concepts/agentic_concepts/#react-implementation) agent that uses a search tool!
```shell
pip install langchain-anthropic
```
```shell
export ANTHROPIC_API_KEY=sk-...
```
Optionally, we can set up [LangSmith](https://docs.smith.langchain.com/) for best-in-class observability.
```shell
export LANGSMITH_TRACING=true
export LANGSMITH_API_KEY=lsv2_sk_...
```
The simplest way to create a tool-calling agent in LangGraph is to use `create_react_agent`:
<details open>
<summary>High-level implementation</summary>
To learn more about how to use LangGraph, check out [the docs](https://langchain-ai.github.io/langgraph/). We show a simple example below of how to create a ReAct agent.
```python
# This code depends on pip install langchain[anthropic]
from langgraph.prebuilt import create_react_agent
from langgraph.checkpoint.memory import MemorySaver
from langchain_anthropic import ChatAnthropic
from langchain_core.tools import tool
# Define the tools for the agent to use
@tool
def search(query: str):
"""Call to surf the web."""
# This is a placeholder, but don't tell the LLM that...
if "sf" in query.lower() or "san francisco" in query.lower():
return "It's 60 degrees and foggy."
return "It's 90 degrees and sunny."
tools = [search]
model = ChatAnthropic(model="claude-3-5-sonnet-latest", temperature=0)
# Initialize memory to persist state between graph runs
checkpointer = MemorySaver()
app = create_react_agent(model, tools, checkpointer=checkpointer)
# Use the agent
final_state = app.invoke(
{"messages": [{"role": "user", "content": "what is the weather in sf"}]},
config={"configurable": {"thread_id": 42}}
agent = create_react_agent("anthropic:claude-3-7-sonnet-latest", tools=[search])
agent.invoke(
{"messages": [{"role": "user", "content": "what is the weather in sf"}]}
)
final_state["messages"][-1].content
```
```
"Based on the search results, I can tell you that the current weather in San Francisco is:\n\nTemperature: 60 degrees Fahrenheit\nConditions: Foggy\n\nSan Francisco is known for its microclimates and frequent fog, especially during the summer months. The temperature of 60°F (about 15.5°C) is quite typical for the city, which tends to have mild temperatures year-round. The fog, often referred to as "Karl the Fog" by locals, is a characteristic feature of San Francisco\'s weather, particularly in the mornings and evenings.\n\nIs there anything else you\'d like to know about the weather in San Francisco or any other location?"
```
Now when we pass the same <code>"thread_id"</code>, the conversation context is retained via the saved state (i.e. stored list of messages)
## Why use LangGraph?
```python
final_state = app.invoke(
{"messages": [{"role": "user", "content": "what about ny"}]},
config={"configurable": {"thread_id": 42}}
)
final_state["messages"][-1].content
```
LangGraph is built for developers who want to build powerful, adaptable AI agents. Developers choose LangGraph for:
```
"Based on the search results, I can tell you that the current weather in New York City is:\n\nTemperature: 90 degrees Fahrenheit (approximately 32.2 degrees Celsius)\nConditions: Sunny\n\nThis weather is quite different from what we just saw in San Francisco. New York is experiencing much warmer temperatures right now. Here are a few points to note:\n\n1. The temperature of 90°F is quite hot, typical of summer weather in New York City.\n2. The sunny conditions suggest clear skies, which is great for outdoor activities but also means it might feel even hotter due to direct sunlight.\n3. This kind of weather in New York often comes with high humidity, which can make it feel even warmer than the actual temperature suggests.\n\nIt's interesting to see the stark contrast between San Francisco's mild, foggy weather and New York's hot, sunny conditions. This difference illustrates how varied weather can be across different parts of the United States, even on the same day.\n\nIs there anything else you'd like to know about the weather in New York or any other location?"
```
</details>
- **Reliability and controllability.** Steer agent actions with moderation checks and human-in-the-loop approvals. LangGraph persists context for long-running workflows, keeping your agents on course.
- **Low-level and extensible.** Build custom agents with fully descriptive, low-level primitives free from rigid abstractions that limit customization. Design scalable multi-agent systems, with each agent serving a specific role tailored to your use case.
- **First-class streaming support.** With token-by-token streaming and streaming of intermediate steps, LangGraph gives users clear visibility into agent reasoning and actions as they unfold in real time.
> [!TIP]
> LangGraph is a **low-level** framework that allows you to implement any custom agent
architectures. Click on the low-level implementation below to see how to implement a
tool-calling agent from scratch.
LangGraph is trusted in production and powering agents for companies like:
<details>
<summary>Low-level implementation</summary>
- [Klarna](https://blog.langchain.dev/customers-klarna/): Customer support bot for 85 million active users
- [Elastic](https://www.elastic.co/blog/elastic-security-generative-ai-features): Security AI assistant for threat detection
- [Uber](https://dpe.org/sessions/ty-smith-adam-huda/this-year-in-ubers-ai-driven-developer-productivity-revolution/): Automated unit test generation
- [Replit](https://www.langchain.com/breakoutagents/replit): Code generation
- And many more ([see list here](https://www.langchain.com/built-with-langgraph))
```python
from typing import Literal
## LangGraphs ecosystem
from langchain_anthropic import ChatAnthropic
from langchain_core.tools import tool
from langgraph.checkpoint.memory import MemorySaver
from langgraph.graph import END, START, StateGraph, MessagesState
from langgraph.prebuilt import ToolNode
While LangGraph can be used standalone, it also integrates seamlessly with any LangChain product, giving developers a full suite of tools for building agents. To improve your LLM application development, pair LangGraph with:
- [LangSmith](http://www.langchain.com/langsmith) — Helpful for agent evals and observability. Debug poor-performing LLM app runs, evaluate agent trajectories, gain visibility in production, and improve performance over time.
- [LangGraph Platform](https://langchain-ai.github.io/langgraph/concepts/#langgraph-platform) — Deploy and scale agents effortlessly with a purpose-built deployment platform for long running, stateful workflows. Discover, reuse, configure, and share agents across teams — and iterate quickly with visual prototyping in [LangGraph Studio](https://langchain-ai.github.io/langgraph/concepts/langgraph_studio/).
# Define the tools for the agent to use
@tool
def search(query: str):
"""Call to surf the web."""
# This is a placeholder, but don't tell the LLM that...
if "sf" in query.lower() or "san francisco" in query.lower():
return "It's 60 degrees and foggy."
return "It's 90 degrees and sunny."
## Pairing with LangGraph Platform
While LangGraph is our open-source agent orchestration framework, enterprises that need scalable agent deployment can benefit from [LangGraph Platform](https://langchain-ai.github.io/langgraph/concepts/langgraph_platform/).
tools = [search]
LangGraph Platform can help engineering teams:
tool_node = ToolNode(tools)
- **Accelerate agent development**: Quickly create agent UXs with configurable templates and [LangGraph Studio](https://langchain-ai.github.io/langgraph/concepts/langgraph_studio/) for visualizing and debugging agent interactions.
- **Deploy seamlessly**: We handle the complexity of deploying your agent. LangGraph Platform includes robust APIs for memory, threads, and cron jobs plus auto-scaling task queues & servers.
- **Centralize agent management & reusability**: Discover, reuse, and manage agents across the organization. Business users can also modify agents without coding.
model = ChatAnthropic(model="claude-3-5-sonnet-latest", temperature=0).bind_tools(tools)
## Additional resources
# Define the function that determines whether to continue or not
def should_continue(state: MessagesState) -> Literal["tools", END]:
messages = state['messages']
last_message = messages[-1]
# If the LLM makes a tool call, then we route to the "tools" node
if last_message.tool_calls:
return "tools"
# Otherwise, we stop (reply to the user)
return END
- [LangChain Academy](https://academy.langchain.com/courses/intro-to-langgraph): Learn the basics of LangGraph in our free, structured course.
- [Tutorials](https://langchain-ai.github.io/langgraph/tutorials/): Simple walkthroughs with guided examples on getting started with LangGraph.
- [Templates](https://langchain-ai.github.io/langgraph/concepts/template_applications/): Pre-built reference apps for common agentic workflows (e.g. ReAct agent, memory, retrieval etc.) that can be cloned and adapted.
- [How-to Guides](https://langchain-ai.github.io/langgraph/how-tos/): Quick, actionable code snippets for topics such as streaming, adding memory & persistence, and design patterns (e.g. branching, subgraphs, etc.).
- [API Reference](https://langchain-ai.github.io/langgraph/reference/graphs/): Detailed reference on core classes, methods, how to use the graph and checkpointing APIs, and higher-level prebuilt components.
- [Built with LangGraph](https://www.langchain.com/built-with-langgraph): Hear how industry leaders use LangGraph to ship powerful, production-ready AI applications.
## Acknowledgements
# Define the function that calls the model
def call_model(state: MessagesState):
messages = state['messages']
response = model.invoke(messages)
# We return a list, because this will get added to the existing list
return {"messages": [response]}
# Define a new graph
workflow = StateGraph(MessagesState)
# Define the two nodes we will cycle between
workflow.add_node("agent", call_model)
workflow.add_node("tools", tool_node)
# Set the entrypoint as `agent`
# This means that this node is the first one called
workflow.add_edge(START, "agent")
# We now add a conditional edge
workflow.add_conditional_edges(
# First, we define the start node. We use `agent`.
# This means these are the edges taken after the `agent` node is called.
"agent",
# Next, we pass in the function that will determine which node is called next.
should_continue,
)
# We now add a normal edge from `tools` to `agent`.
# This means that after `tools` is called, `agent` node is called next.
workflow.add_edge("tools", 'agent')
# Initialize memory to persist state between graph runs
checkpointer = MemorySaver()
# Finally, we compile it!
# This compiles it into a LangChain Runnable,
# meaning you can use it as you would any other runnable.
# Note that we're (optionally) passing the memory when compiling the graph
app = workflow.compile(checkpointer=checkpointer)
# Use the agent
final_state = app.invoke(
{"messages": [{"role": "user", "content": "what is the weather in sf"}]},
config={"configurable": {"thread_id": 42}}
)
final_state["messages"][-1].content
```
<b>Step-by-step Breakdown</b>:
<details>
<summary>Initialize the model and tools.</summary>
<ul>
<li>
We use <code>ChatAnthropic</code> as our LLM. <strong>NOTE:</strong> we need to make sure the model knows that it has these tools available to call. We can do this by converting the LangChain tools into the format for OpenAI tool calling using the <code>.bind_tools()</code> method.
</li>
<li>
We define the tools we want to use - a search tool in our case. It is really easy to create your own tools - see documentation here on how to do that <a href="https://python.langchain.com/docs/how_to/custom_tools/">here</a>.
</li>
</ul>
</details>
<details>
<summary>Initialize graph with state.</summary>
<ul>
<li>We initialize graph (<code>StateGraph</code>) by passing state schema (in our case <code>MessagesState</code>)</li>
<li><code>MessagesState</code> is a prebuilt state schema that has one attribute -- a list of LangChain <code>Message</code> objects, as well as logic for merging the updates from each node into the state.</li>
</ul>
</details>
<details>
<summary>Define graph nodes.</summary>
There are two main nodes we need:
<ul>
<li>The <code>agent</code> node: responsible for deciding what (if any) actions to take.</li>
<li>The <code>tools</code> node that invokes tools: if the agent decides to take an action, this node will then execute that action.</li>
</ul>
</details>
<details>
<summary>Define entry point and graph edges.</summary>
First, we need to set the entry point for graph execution - <code>agent</code> node.
Then we define one normal and one conditional edge. Conditional edge means that the destination depends on the contents of the graph's state (<code>MessagesState</code>). In our case, the destination is not known until the agent (LLM) decides.
<ul>
<li>Conditional edge: after the agent is called, we should either:
<ul>
<li>a. Run tools if the agent said to take an action, OR</li>
<li>b. Finish (respond to the user) if the agent did not ask to run tools</li>
</ul>
</li>
<li>Normal edge: after the tools are invoked, the graph should always return to the agent to decide what to do next</li>
</ul>
</details>
<details>
<summary>Compile the graph.</summary>
<ul>
<li>
When we compile the graph, we turn it into a LangChain
<a href="https://python.langchain.com/docs/concepts/runnables/">Runnable</a>,
which automatically enables calling <code>.invoke()</code>, <code>.stream()</code> and <code>.batch()</code>
with your inputs
</li>
<li>
We can also optionally pass checkpointer object for persisting state between graph runs, and enabling memory,
human-in-the-loop workflows, time travel and more. In our case we use <code>MemorySaver</code> -
a simple in-memory checkpointer
</li>
</ul>
</details>
<details>
<summary>Execute the graph.</summary>
<ol>
<li>LangGraph adds the input message to the internal state, then passes the state to the entrypoint node, <code>"agent"</code>.</li>
<li>The <code>"agent"</code> node executes, invoking the chat model.</li>
<li>The chat model returns an <code>AIMessage</code>. LangGraph adds this to the state.</li>
<li>Graph cycles the following steps until there are no more <code>tool_calls</code> on <code>AIMessage</code>:
<ul>
<li>If <code>AIMessage</code> has <code>tool_calls</code>, <code>"tools"</code> node executes</li>
<li>The <code>"agent"</code> node executes again and returns <code>AIMessage</code></li>
</ul>
</li>
<li>Execution progresses to the special <code>END</code> value and outputs the final state. And as a result, we get a list of all our chat messages as output.</li>
</ol>
</details>
</details>
## Documentation
* [Tutorials](https://langchain-ai.github.io/langgraph/tutorials/): Learn to build with LangGraph through guided examples.
* [How-to Guides](https://langchain-ai.github.io/langgraph/how-tos/): Accomplish specific things within LangGraph, from streaming, to adding memory & persistence, to common design patterns (branching, subgraphs, etc.), these are the place to go if you want to copy and run a specific code snippet.
* [Conceptual Guides](https://langchain-ai.github.io/langgraph/concepts/high_level/): In-depth explanations of the key concepts and principles behind LangGraph, such as nodes, edges, state and more.
* [API Reference](https://langchain-ai.github.io/langgraph/reference/graphs/): Review important classes and methods, simple examples of how to use the graph and checkpointing APIs, higher-level prebuilt components and more.
* [LangGraph Platform](https://langchain-ai.github.io/langgraph/concepts/#langgraph-platform): LangGraph Platform is a commercial solution for deploying agentic applications in production, built on the open-source LangGraph framework.
## Resources
* [Built with LangGraph](https://www.langchain.com/built-with-langgraph): Hear how industry leaders use LangGraph to ship powerful, production-ready AI applications.
## Contributing
For more information on how to contribute, see [here](https://github.com/langchain-ai/langgraph/blob/main/CONTRIBUTING.md).
LangGraph is inspired by [Pregel](https://research.google/pubs/pub37252/) and [Apache Beam](https://beam.apache.org/). The public interface draws inspiration from [NetworkX](https://networkx.org/documentation/latest/). LangGraph is built by LangChain Inc, the creators of LangChain, but can be used without LangChain.
+9 -1
View File
@@ -10,7 +10,15 @@ build-prebuilt:
# Use to create an update to date prebuilt page.
# Looks up download stats for each of the prebuilt packages and
# generates the final prebuilt page.
poetry run python -m _scripts.third_party_page.get_download_stats stats.yml
@if [ "$(DOWNLOAD_STATS)" = "true" ]; then \
set -x; \
poetry run python -m _scripts.third_party_page.get_download_stats stats.yml; \
set +x; \
else \
set -x; \
poetry run python -m _scripts.third_party_page.get_download_stats --fake stats.yml; \
set +x; \
fi
poetry run python -m _scripts.third_party_page.create_third_party_page stats.yml docs/prebuilt.md --language python
build-docs: build-typedoc build-prebuilt
+2
View File
@@ -14,6 +14,8 @@ To run the documentation server locally you can run:
make serve-docs
```
This will start the documentation server on [http://127.0.0.1:8000/langgraph/](http://127.0.0.1:8000/langgraph/).
## Execute notebooks
If you would like to automatically execute all of the notebooks, to mimic the "Run notebooks" GHA, you can run:
+115 -139
View File
@@ -1,9 +1,9 @@
import ast
import importlib
import inspect
import logging
import re
from functools import lru_cache
from typing import List, Literal, Optional
from typing import List, Optional
from typing_extensions import TypedDict
@@ -39,7 +39,6 @@ MANUAL_API_REFERENCES_LANGGRAPH = [
(["langgraph.graph"], "langgraph.graph.message", "add_messages", "graphs"),
(["langgraph.graph"], "langgraph.graph.state", "StateGraph", "graphs"),
(["langgraph.graph"], "langgraph.graph.state", "CompiledStateGraph", "graphs"),
([], "langgraph.types", "StreamMode", "types"),
(["langgraph.graph"], "langgraph.constants", "START", "constants"),
(["langgraph.graph"], "langgraph.constants", "END", "constants"),
(["langgraph.constants"], "langgraph.types", "Send", "types"),
@@ -48,7 +47,9 @@ MANUAL_API_REFERENCES_LANGGRAPH = [
(["langgraph.constants"], "langgraph.types", "Command", "types"),
(["langgraph.func"], "langgraph.func", "entrypoint", "func"),
(["langgraph.func"], "langgraph.func", "task", "func"),
([], "langgraph.types", "RetryPolicy", "types"),
(["langgraph.types"], "langgraph.types", "RetryPolicy", "types"),
(["langgraph.types"], "langgraph.types", "StreamMode", "types"),
(["langgraph.types"], "langgraph.types", "StreamWriter", "types"),
([], "langgraph.checkpoint.base", "Checkpoint", "checkpoints"),
([], "langgraph.checkpoint.base", "CheckpointMetadata", "checkpoints"),
([], "langgraph.checkpoint.base", "BaseCheckpointSaver", "checkpoints"),
@@ -68,34 +69,19 @@ WELL_KNOWN_LANGGRAPH_OBJECTS = {
}
def _make_regular_expression(pkg_prefix: str) -> re.Pattern:
if not pkg_prefix.isidentifier():
raise ValueError(f"Invalid package prefix: {pkg_prefix}")
return re.compile(
r"from\s+(" + pkg_prefix + "(?:_\w+)?(?:\.\w+)*?)\s+import\s+"
r"((?:\w+(?:,\s*)?)*" # Match zero or more words separated by a comma+optional ws
r"(?:\s*\(.*?\))?)", # Match optional parentheses block
re.DOTALL, # Match newlines as well
)
# Regular expression to match langchain import lines
_IMPORT_LANGCHAIN_RE = _make_regular_expression("langchain")
_IMPORT_LANGGRAPH_RE = _make_regular_expression("langgraph")
@lru_cache(maxsize=10_000)
def _get_full_module_name(module_path: str, class_name: str) -> Optional[str]:
"""Get full module name using inspect, with LRU cache to memoize results."""
try:
module = importlib.import_module(module_path)
class_ = getattr(module, class_name)
module = inspect.getmodule(class_)
if module is None:
# For constants, inspect.getmodule() might return None
# In this case, we'll return the original module_path
symbol = getattr(module, class_name)
# First check the __module__ attribute on the symbol.
mod_name = getattr(symbol, "__module__", None)
# If __module__ is not set or comes from typing,
# assume the definition is in module_path.
if mod_name is None or mod_name.startswith("typing"):
return module_path
return module.__name__
return mod_name
except AttributeError as e:
logger.warning(f"API Reference: Could not find module for {class_name}, {e}")
return None
@@ -104,139 +90,128 @@ def _get_full_module_name(module_path: str, class_name: str) -> Optional[str]:
return None
def _get_doc_title(data: str, file_name: str) -> str:
try:
return re.findall(r"^#\s*(.*)", data, re.MULTILINE)[0]
except IndexError:
pass
# Parse the rst-style titles
try:
return re.findall(r"^(.*)\n=+\n", data, re.MULTILINE)[0]
except IndexError:
return file_name
class ImportInformation(TypedDict):
imported: str # The name of the class that was imported.
source: str # The full module path from which the class was imported.
docs: str # The URL pointing to the class's documentation.
title: str # The title of the document where the import is used.
path: str # The path of the file where the markdown content originated.
def _get_imports(
code: str, doc_title: str, package_ecosystem: Literal["langchain", "langgraph"]
) -> List[ImportInformation]:
"""Get imports from the given code block.
Args:
code: Python code block from which to extract imports
doc_title: Title of the document
package_ecosystem: "langchain" or "langgraph". The two live in different
repositories and have separate documentation sites.
Returns:
List of import information for the given code block
"""
imports = []
if package_ecosystem == "langchain":
pattern = _IMPORT_LANGCHAIN_RE
elif package_ecosystem == "langgraph":
pattern = _IMPORT_LANGGRAPH_RE
else:
raise ValueError(f"Invalid package ecosystem: {package_ecosystem}")
for import_match in pattern.finditer(code):
module = import_match.group(1)
if "pydantic_v1" in module:
continue
imports_str = (
import_match.group(2).replace("(\n", "").replace("\n)", "")
) # Handle newlines within parentheses
# remove any newline and spaces, then split by comma
imported_classes = [
imp.strip()
for imp in re.split(r",\s*", imports_str.replace("\n", ""))
if imp.strip()
]
for class_name in imported_classes:
module_path = _get_full_module_name(module, class_name)
if not module_path:
continue
if len(module_path.split(".")) < 2:
continue
if package_ecosystem == "langchain":
pkg = module_path.split(".")[0].replace("langchain_", "")
top_level_mod = module_path.split(".")[1]
url = (
_LANGCHAIN_API_REFERENCE
+ pkg
+ "/"
+ top_level_mod
+ "/"
+ module_path
+ "."
+ class_name
+ ".html"
)
elif package_ecosystem == "langgraph":
if (module, class_name) not in WELL_KNOWN_LANGGRAPH_OBJECTS:
# Likely not documented yet
continue
source_module, namespace = WELL_KNOWN_LANGGRAPH_OBJECTS[
(module, class_name)
]
url = (
_LANGGRAPH_API_REFERENCE
+ namespace
+ "/#"
+ source_module
+ "."
+ class_name
)
else:
raise ValueError(f"Invalid package ecosystem: {package_ecosystem}")
# Add the import information to our list
imports.append(
{
"imported": class_name,
"source": module,
"docs": url,
"title": doc_title,
}
)
return imports
def get_imports(code: str, doc_title: str) -> List[ImportInformation]:
def get_imports(code: str, path: str) -> List[ImportInformation]:
"""Retrieve all import references from the given code for specified ecosystems.
Args:
code: The source code from which to extract import references.
doc_title: The documentation title associated with the code.
path: The path of the file where the markdown content originated.
Returns:
A list of import information for each import found.
"""
ecosystems = ["langchain", "langgraph"]
all_imports = []
for package_ecosystem in ecosystems:
all_imports.extend(_get_imports(code, doc_title, package_ecosystem))
return all_imports
# Parse the code into an AST.
try:
tree = ast.parse(code)
except SyntaxError:
return []
found_imports = []
# Walk through the AST and process ImportFrom nodes.
for node in ast.walk(tree):
if isinstance(node, ast.ImportFrom):
# node.module is the source module.
if node.module is None:
continue
for alias in node.names:
if not (
node.module.startswith("langchain")
or node.module.startswith("langgraph")
):
continue
found_imports.append(
{
"source": node.module,
# alias.name is the original name even if an alias exists.
"imported": alias.name,
}
)
imports: list[ImportInformation] = []
for found_import in found_imports:
module = found_import["source"]
if module.startswith("langchain"):
# Handles things like `langchain` or `langchain_anthropic`
package_ecosystem = "langchain"
elif module.startswith("langgraph"):
package_ecosystem = "langgraph"
else:
continue
class_name = found_import["imported"]
module_path = _get_full_module_name(module, class_name)
if not module_path:
continue
if len(module_path.split(".")) < 2:
continue
if package_ecosystem == "langchain":
pkg = module_path.split(".")[0].replace("langchain_", "")
top_level_mod = module_path.split(".")[1]
url = (
_LANGCHAIN_API_REFERENCE
+ pkg
+ "/"
+ top_level_mod
+ "/"
+ module_path
+ "."
+ class_name
+ ".html"
)
elif package_ecosystem == "langgraph":
if (module, class_name) not in WELL_KNOWN_LANGGRAPH_OBJECTS:
# Likely not documented yet
continue
source_module, namespace = WELL_KNOWN_LANGGRAPH_OBJECTS[
(module, class_name)
]
url = (
_LANGGRAPH_API_REFERENCE
+ namespace
+ "/#"
+ source_module
+ "."
+ class_name
)
else:
raise ValueError(f"Invalid package ecosystem: {package_ecosystem}")
# Add the import information to our list
imports.append(
{
"imported": class_name,
"source": module,
"docs": url,
"path": path,
}
)
return imports
def update_markdown_with_imports(markdown: str) -> str:
def update_markdown_with_imports(markdown: str, path: str) -> str:
"""Update markdown to include API reference links for imports in Python code blocks.
This function scans the markdown content for Python code blocks, extracts any imports, and appends links to their API documentation.
This function scans the markdown content for Python code blocks, extracts any
imports, and appends links to their API documentation.
Args:
markdown: The markdown content to process.
path: The path of the file where the markdown content originated.
Returns:
Updated markdown with API reference links appended to Python code blocks.
@@ -247,7 +222,8 @@ def update_markdown_with_imports(markdown: str) -> str:
```python
from langchain.nlp import TextGenerator
```
This function will append an API reference link to the `TextGenerator` class from the `langchain.nlp` module if it's recognized.
This function will append an API reference link to the `TextGenerator` class
from the `langchain.nlp` module if it's recognized.
"""
code_block_pattern = re.compile(
r"(?P<indent>[ \t]*)```(?P<language>python|py)\n(?P<code>.*?)\n(?P=indent)```",
+2 -2
View File
@@ -175,7 +175,7 @@ def _on_page_markdown_with_config(
# Append API reference links to code blocks
if add_api_references:
markdown = update_markdown_with_imports(markdown)
markdown = update_markdown_with_imports(markdown, page.file.abs_src_path)
# Apply highlight comments to code blocks
markdown = _highlight_code_blocks(markdown)
@@ -186,7 +186,7 @@ def _on_page_markdown_with_config(
if remove_base64_images:
# Remove base64 encoded images from markdown
markdown = re.sub(r"!\[.*?\]\(data:image/+;base64,[^\)]+\)", "", markdown)
markdown = re.sub(r"!\[.*?\]\(data:image/[^;]+;base64,[^)]+\)", "", markdown)
return markdown
@@ -83,14 +83,18 @@ def generate_markdown(resolved_packages: List[ResolvedPackage], language: str) -
resolved_packages, key=lambda p: p["weekly_downloads"] or 0, reverse=True
)
rows = [
"| Name | GitHub URL | Description | Weekly Downloads |",
"| --- | --- | --- | --- |",
"| Name | GitHub URL | Description | Weekly Downloads | Stars |",
"| --- | --- | --- | --- | --- |",
]
for package in sorted_packages:
name = f"**{package['name']}**"
repo_url = f"[{package['repo']}](https://github.com/{package['repo']})"
stars_badge = (
f"https://img.shields.io/github/stars/{package['repo']}?style=social"
)
stars = f"![GitHub stars]({stars_badge})"
downloads = package["weekly_downloads"] or "-"
row = f"| {name} | {repo_url} | {package['description']} | {downloads} |"
row = f"| {name} | {repo_url} | {package['description']} | {downloads} | {stars}"
rows.append(row)
markdown_content = MARKDOWN.format(
library_list="\n".join(rows), langgraph_url=langgraph_url
@@ -30,10 +30,23 @@ PACKAGES_FILE = HERE / "packages.yml"
PACKAGES = yaml.safe_load(PACKAGES_FILE.read_text())['packages']
def _get_weekly_downloads(packages: list[Package]) -> list[ResolvedPackage]:
def _get_weekly_downloads(packages: list[Package], fake: bool) -> list[ResolvedPackage]:
"""Retrieve the monthly download count for a list of packages from PyPIStats."""
resolved_packages: list[ResolvedPackage] = []
if fake:
# To avoid making network requests during testing, return fake download counts
for package in packages:
resolved_packages.append(
{
"name": package["name"],
"repo": package["repo"],
"weekly_downloads": -12345,
"description": package["description"],
}
)
return resolved_packages
for package in packages:
# First check if package exists on PyPI
pypi_url = f"https://pypi.org/pypi/{package['name']}/json"
@@ -88,13 +101,13 @@ def _get_weekly_downloads(packages: list[Package]) -> list[ResolvedPackage]:
def main(output_file: str) -> None:
def main(output_file: str, fake: bool) -> None:
"""Main function to generate package download information.
Args:
output_file: Path to the output YAML file.
"""
resolved_packages: list[ResolvedPackage] = _get_weekly_downloads(PACKAGES)
resolved_packages: list[ResolvedPackage] = _get_weekly_downloads(PACKAGES, fake)
if not output_file.endswith(".yml"):
raise ValueError("Output file must have a .yml extension")
@@ -115,6 +128,15 @@ if __name__ == "__main__":
"downloads.yml"
),
)
parser.add_argument(
"--fake",
default=False,
action="store_true",
help=(
"Generate fake download counts for testing purposes. "
"This option will not make any network requests."
),
)
args = parser.parse_args()
main(args.output_file)
main(args.output_file, args.fake)
+29 -5
View File
@@ -2,16 +2,40 @@
packages:
- name: "trustcall"
repo: "hinthornw/trustcall"
description: "Tenacious tool calling built on LangGraph"
description: "Tenacious tool calling built on LangGraph."
- name: "breeze-agent"
repo: "andrestorres123/breeze-agent"
description: "A streamlined research system built inspired on STORM and built on LangGraph"
description: "A streamlined research system built inspired on STORM and built on LangGraph."
- name: "langgraph-supervisor"
repo: "langchain-ai/langgraph-supervisor"
description: "Build supervisor multi-agent systems with LangGraph"
repo: "langchain-ai/langgraph-supervisor-py"
description: "Build supervisor multi-agent systems with LangGraph."
- name: "langmem"
repo: "langchain-ai/langmem"
description: "Build agents that learn and adapt from interactions over time."
- name: "langchain-mcp-adapters"
repo: "langchain-ai/langchain-mcp-adapters"
description: "Make Anthropic Model Context Protocol (MCP) tools compatible with LangGraph agents."
description: "Make Anthropic Model Context Protocol (MCP) tools compatible with LangGraph agents."
- name: "open-deep-research"
repo: "langchain-ai/open_deep_research"
description: "Open source assistant for iterative web research and report writing."
- name: "langgraph-swarm"
repo: "langchain-ai/langgraph-swarm-py"
description: "Build swarm-style multi-agent systems using LangGraph."
- name: "delve-taxonomy-generator"
repo: "andrestorres123/delve"
description: "A taxonomy generator for unstructured data"
- name: "nodeology"
repo: "xyin-anl/Nodeology"
description: "Enable researcher to build scientific workflows easily with simplified interface."
- name: "langgraph-bigtool"
repo: "langchain-ai/langgraph-bigtool"
description: "Build LangGraph agents with large numbers of tools."
- name: "ai-data-science-team"
repo: "business-science/ai-data-science-team"
description: "An AI-powered data science team of agents to help you perform common data science tasks 10X faster."
- name: "langgraph-reflection"
repo: "langchain-ai/langgraph-reflection"
description: "LangGraph agent that runs a reflection step."
- name: "langgraph-codeact"
repo: "langchain-ai/langgraph-codeact"
description: "LangGraph implementation of CodeAct agent that generates and executes code instead of tool calling."
@@ -0,0 +1 @@
eNptV3tcVHUWB3zAbr7yo1mmdZt8JM4dZphhGEAyXibKADI8xCD3zr2/YS5zX9wHMBiZtNaapo2htqW1IY9E8rGwaiVpa1k+UjNw1Tay1NxtSU1LS9d1z29meGX3j/nM3HPO97y+5/x+U9NUjmSFFYXQFlZQkUzRKvxQfDVNMirTkKL+sZFHqltk6rOzHLkbNZk9FelWVUmJj4qiJNYgSkigWAMt8lHlpijaTalR8F3ikB+m3iky3tND0xbpeKQoVAlSdPFPLNLRIrgSVF28rgAMpioEqxIeQawQCJcoz9TpdbLIIZBqCpJ11fr+BpmogigUZQ+RwqpeglX67AiKKKdkFsFr0UWwYMLSBEcJDE/JHkVP0BqnajLFEaygqKyq+QPUE6BAlLNOmRJUQkBsidspym5RZBQD4RB5hLFUNyJ4UQG5qFJODhEuRAEUgrgFmtMYFF8kFAkmAxEZ6VBB4jfKYJ1IVr2RkfFEEqF4eafI4dcuGSFG5P1uGcSLNFTcqyc4kaZUxBCi0GNIpCs4eEOREI2Bc1moIOEo0ygZYcy5vWmzqkI4ZQhcJTj8CTklyyLFVFBeHDnAysE0nZqicqxQQlAqpCO5kYwA3ozhU6C6uDbZUKtAyBwllyBC0pwclFGC1xC9C8l+c0KgAqWUkSqDB6hDoEgsA1UKVoyGBgG8BcOn8RIrIwJXBxHJGssxgOP3I/R0SvF4FSiGhOQ+RxIliDLFg7ScRRXKr5BjMHJPqhhsFsWLmtJblApR5hiS5ihF6SkEIckiowUoDghWjFBAcRxEBn1RMUguOHCxAiXQLCTo1pw9XvMEFnfInwM2jsXGdqCoxivYMN3PBRw21rZDZURJ5FiVEoiAFgZKklV9v592kUGygN8Sj9hFe9K0QKMwQBIPNaAHGGcGqz6bVVRRxiWw4RhSWTzCiEjRWIUVUKB9POJUfwlFf0MC5AcGycjFIRonAj3DVWKC1i7gPKHQSMCciPNzomdgAg7YHjJDWG5ChU4pquwdAI5jh2UB7WRVFuGZg7mVWafmD0UV/Q57ho2S1YBF72D2eDcZsftZlOKGPvWRnQJ1ooQTnaDqCggJGnaQSnF6wg3ziZ2gcmCyApPgQUTvrghCEQUIeQx4VqHJkDKMElEKMwGwLlB1w/QEJggnVQGbieApD6Q1cOdQhCawsBoDI+wV/PyUOIpGhr7NBZyDJkGav1pfFXjoCNxWFrMs0GonVJJwwnbk7th9xXodDxzh4EWJpJIWERQUPHO8Lt5FcQrS61TEw9D4F5Iu3mgwwhtR5AKLVvVKGMulCX7Og3Hv1/hFOggdS0uQurACxgNCAwUGwRiyUkBHlwdlUt2wZqF5oEcE9YA8MGU8hbVw1rAfAAtvGowLQwYRYQbgX/7VFvQYjAcygF7pqqshWzhlYDUwEG6fJmQd1BSdpcBW0Kwurm6CGYZxUbpCRtXjdvu2DDyAtlI0jaBISKBFPIe+1pIqVtLDmnVxMLN6okpRmWbohYD8JfA1exCSSIoDejcGbH3bKEmChecPI6pUEYWWYO9IHNCd4mbcJhJaJ6i+tiwIJSk9KtsL56VAmAxWk8G0rZIEHrACB+cfCQu9xNco+eXv9RdIFO0BEDJ4FvsaA8Zb+uuIiq/BTtFZjgGQlEy7fQ2UzFstrf3fy5qgwpHha0rJvtNdUNjnzmwwmQxx2wcAK16B9jX4SbZzgDFsNi9Ji4Dhe9PYSIuih0W+06HhCxfSroVOPhF5vIUZGcnuea4CQXE71NlpqRWSwxltijGUVEbH5NtjMwvtVZ6qMoNImmItZmtcdLTJQpoMRgPkTKZVpMzKzWBSCyjbLDlZMxjVGHfWbFMZnSVl5EkyW2bNnpM52wrEWZiLshz21LLHo/lcj1ZitzgdhpxsG+91zFYEj6kqlVroTqtikc0cOze7yhqX5S5bkF8xl9ZMOV5kTeMtCQSErJWzTOKCOUnZjmw7w+ZHxzoK57vS5glqXqrCV6LZBelahn1hrGzJUKPz7LGWfjGbjWbSGAzbarTYjPjZ0sMYDgklqttXb7IaY96C9SjBoYOebVTwFUGpqQeSosOfNAUvRnVZc/v4fU99KhDW157r1vSE0UwkSTIRbYyOIUyW+JjYeGMs8bg9tyUl6Cf3N5m5PRe2rAIHKZnWMw9NtFsTPIhpTvnNGWjHMwAN9i9tkSNRpSQqiAxG5WuZT+YEroRkemprYOxIUS6hBLbK79a3CfMbroCs0BYUwybAkOCc5BVfvcUaY94SFPVwrxkSM5ImI2k0vVtJwh5DHMuzUD3/Z/ASCtSPwbXddaeGKnoQ3Fc3mfwK8LzfX0dGPISD/fchWeLg2f3bWr1ofiVr3MCYoImoX0wbTbyy6055EKPOqLRU9iiTLOM7NQlz1khZY6xWmwXog8wus8tkNTEMhWKNCFmQzci8g5cjDSi4fZIoq6SCaLh2q17fKT1PVeJlk2g2xZitkGtCzw3UoTlTRZyEkgB3HMTBpWgr7SJpinYjMsA4X1NqYWaSPT1lx3yyP3XILClw5W8SREVgXa5GB5KhO75mmhM1BnanjBpTZpE5SYW+trhoKs5K2azIxthiUCxDphXkbOtB6yVaPV68TRQHsZfTvla3OVEXb7GYdQlwoCbarBaj0f/HYElj4CD4aNCxB5dHhPifQSvyvlh5f+yw6usFo66+9PxSvrvq0s219elW8nSj/cqojiVJHtvDCM2bLncPqxly4/5b7U+nP3Sq64drYT9+RA9rSLly+fLhnXc/dv6774ZG0vM+jbxxYPlOsevI5SPXftgodn986WZF09yr/1u3v/2DL6I6bV+dOT8u+t09MTG7X3i9o+zkc3Zd7sG3pq4raRr3j9ZTXH7Y9C0HLnj4jgP3Zbk+bm098EPnuZ+dFZ/91Typc/h/rWEhP+c/rSx7s3Fr5/AJq66L+ZNqyLzYVc+HNH/46J5N2R8ucx4rnTF4eHhDdvPT3yd/n3xX6e++7VydemGsfvvkkYa9WW1LstZfPNPw+QPDhs4fPbugqtwzftDvbUOE2rCOMdM6wiYQOaNH/CtpXi0xpfSRecZJjl3nh7897cWkK4NuGV6bvzLslYhXU69PHPJTYssjjGHTkWW1D3PTt0478OmMw/sOjFm58sllGdIV3cYJE7/cO3JJbOj4zDO5e+lSdtj+441fuUbvzR709/2dgz0ZK9vChcecuhYUP7J1xQ3P1LCjZxK6F2yunZSyZ//Yiit/qg658Mt/7u2IDy2x2RynQ5eHza0Liai7N3Fs5sx2fcTuxsERz9WUb3rjyD42c9HN7nvmTJ/8tWJ8NOvY3vyR9K5FxzdMaSl2Rdw62zKlrr2puOxzr+3Qtpnl06jbFy4t/iT0xlF7Svq13IhfZuSN+POKZ0/U0uqba0zc+gWPuU+q6OD1iTdalj/VnD7J+tK5FRfizl5t2HapdsSV9rMnvRmrOukm68iT3czqshFDj1cWKQefGXff5UFbv9lwV9ilS+/pXw69/u8PDx18J2bNzM0zvKNPPzv8byMGF7t+rBm6s5s9tOjlVQkNYZvXLv0D7W06N+Po2Ko38ooco+Y80caeOBf+2tV05suDhcOac+rGd0y5uODQhrWaOfOmKSLlaPGpt/ePpXa8s4QKNz9cqC0p8qxbr1dIR+XS/a61bfXLHxiefnfRt8TVz4ZUfHU315l92jCmdkUmdX7BZu+G2PUdNY2PfhGSnHJ/dteJ48q654q7HNGJbatT7VNf2aBXux4cbBycf7gqcso17zhvZRt5lM/YXbun+O3x49afTNONGXGqLjUuf/INY9jPRd3bF31TmZex+4V3s9/fuPqiuqP141LjuYfiE/acTFsz9tYo255/hr8eYijNUZ8cMWFHtFvfua/zg5XbN098cPCscP526/rF+7p2XEy+ufjM88+Yxqz5Li0jN+Fq2/mv59dxXbe1bt+3OdLk2hNHjiVPbJjxwqvju/977Ymc9Kg5m9POJs+dNmXnrb9Yysq06qWu8mqvXPziA7MWh4aE3L49KOSpnxa3F4aHhPwftFJrYA==
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+8 -2
View File
@@ -1,4 +1,4 @@
# 🦜🕸️ LangGraph Adopters
# 🦜🕸️ Companies using LangGraph
This list of companies using LangGraph and their success stories is compiled from public sources. If your company uses LangGraph, we'd love for you to share your story and add it to the list. Youre also welcome to contribute updates based on publicly available information from other companies, such as blog posts or press releases.
@@ -9,17 +9,23 @@ This list of companies using LangGraph and their success stories is compiled fro
| [AppFolio](https://www.appfolio.com/) | Real Estate | Copilot for domain-specific task | [Case study, 2024](https://blog.langchain.dev/customers-appfolio/) |
| [Athena Intelligence](https://www.athenaintel.com/) | Software & Technology (GenAI Native) | Research & summarization | [Case study, 2024](https://blog.langchain.dev/customers-athena-intelligence/) |
| [Captide](https://www.captide.co/) | Software & Technology (GenAI Native) | Data extraction | [Case study, 2025](https://blog.langchain.dev/how-captide-is-redefining-equity-research-with-agentic-workflows-built-on-langgraph-and-langsmith/) |
| [Cisco Outshift](https://outshift.cisco.com/) | Software & Technology | DevOps | [Blog post, 2025](https://outshift.cisco.com/blog/build-react-agent-application-for-devops-tasks-using-rest-apis) |
| [C.H. Robinson](https://www.chrobinson.com/en-us/) | Logistics | Automation | [Case study, 2025](https://blog.langchain.dev/customers-chrobinson/) |
| [Elastic](https://www.elastic.co/) | Software & Technology | Copilot for domain-specific task | [Blog post, 2025](https://www.elastic.co/blog/elastic-security-generative-ai-features) |
| [GitLab](https://about.gitlab.com/) | Software & Technology | Code generation | [Duo workflow docs](https://handbook.gitlab.com/handbook/engineering/architecture/design-documents/duo_workflow/) |
| [Inconvo](https://inconvo.ai/?ref=blog.langchain.dev) | Software & Technology | Code generation | [Case study, 2025](https://blog.langchain.dev/customers-inconvo/) |
| [Infor](https://infor.com/) | Software & Technology | GenAI embedded product experiences; customer support; copilot | [Case study, 2025](https://blog.langchain.dev/customers-infor/) |
| [Klarna](https://www.klarna.com/) | Fintech | Copilot for domain-specific task | [Case study, 2025](https://blog.langchain.dev/customers-klarna/) |
| [Komodo Health](https://www.komodohealth.com/) | Healthcare | Copilot for domain-specific task | [Blog post](https://www.komodohealth.com/perspectives/new-gen-ai-assistant-empowers-the-enterprise/) |
| [LinkedIn](https://www.linkedin.com/) | Social Media | Code generation; Search & discovery | [Blog post, 2025](https://www.linkedin.com/blog/engineering/ai/practical-text-to-sql-for-data-analytics); [Blog post, 2024](https://www.linkedin.com/blog/engineering/generative-ai/behind-the-platform-the-journey-to-create-the-linkedin-genai-application-tech-stack) |
| [Minimal](https://gominimal.ai/) | E-commerce | Customer support | [Case study, 2025](https://blog.langchain.dev/how-minimal-built-a-multi-agent-customer-support-system-with-langgraph-langsmith/) |
| [OpenRecovery](https://www.openrecovery.com/) | Healthcare | Copilot for domain-specific task | [Case study, 2024](https://blog.langchain.dev/customers-openrecovery/) |
| [Qodo](https://www.qodo.ai/) | Software & Technology (GenAI Native) | Code generation | [Blog post, 2025](https://www.qodo.ai/blog/why-we-chose-langgraph-to-build-our-coding-agent/) |
| [Rakuten](https://www.rakuten.com/) | E-commerce / Fintech | Copilot for domain-specific task | [Blog post, 2025](https://rakuten.today/blog/from-ai-hype-to-real-world-tools-rakuten-teams-up-with-langchain.html) |
| [Replit](https://replit.com/) | Software & Technology | Code generation | [Blog post, 2024](https://blog.langchain.dev/customers-replit/); [Breakout agent story, 2024](https://www.langchain.com/breakoutagents/replit); [Fireside chat video, 2024](https://www.youtube.com/watch?v=ViykMqljjxU) |
| [Rexera](https://www.rexera.com/) | Real Estate (GenAI Native) | Copilot for domain-specific task | [Case study, 2024](https://blog.langchain.dev/customers-rexera/) |
| [Tradestack](https://www.tradestack.uk/) | Software & Technology (GenAI Native) | Copilot for domain-specific task | [Case study, 2024](https://blog.langchain.dev/customers-tradestack/) |
| [Uber](https://www.uber.com/) | Transportation | Developer productivity; Code generation | [Presentation, 2024](https://dpe.org/sessions/ty-smith-adam-huda/this-year-in-ubers-ai-driven-developer-productivity-revolution/); [Video, 2024](https://www.youtube.com/watch?v=8rkA5vWUE4Y) |
| [Unify](https://www.unifygtm.com/) | Software & Technology (GenAI Native) | Copilot for domain-specific task | [Blog post, 2024](https://blog.langchain.dev/unify-launches-agents-for-account-qualification-using-langgraph-and-langsmith/) |
| [Vizient](https://www.vizientinc.com/) | Healthcare | Copilot for domain-specific task | [Case study, 2025](https://blog.langchain.dev/p/3d2cd58c-13a5-4df9-bd84-7d54ed0ed82c/) |
| [Vizient](https://www.vizientinc.com/) | Healthcare | Copilot for domain-specific task | [Case study, 2025](https://blog.langchain.dev/p/3d2cd58c-13a5-4df9-bd84-7d54ed0ed82c/) |
| [Vodafone](https://www.vodafone.com/) | Telecommunications | Code generation; internal search | [Case study, 2025](https://blog.langchain.dev/customers-vodafone/) |
+27 -2
View File
@@ -1,6 +1,6 @@
# How to Deploy to LangGraph Cloud
# How to Deploy to Cloud SaaS
LangGraph Cloud is available within <a href="https://www.langchain.com/langsmith" target="_blank">LangSmith</a>. To deploy a LangGraph Cloud API, navigate to the <a href="https://smith.langchain.com/" target="_blank">LangSmith UI</a>.
Before deploying, review the [conceptual guide for the Cloud SaaS](../../concepts/langgraph_cloud.md) deployment option.
## Prerequisites
@@ -92,3 +92,28 @@ Starting from the `LangGraph Platform` view...
1. Check/uncheck checkbox to `Automatically update deployment on push to branch`.
1. Branch creation/deletion and tag creation/deletion events will not trigger an update. Only pushes to an existing branch will trigger an update.
1. Pushes in quick succession to a branch will not trigger subsequent updates. In the future, this functionality may be changed/improved.
## Add or Remove GitHub Repositories
After installing and authorizing LangChain's `hosted-langserve` GitHub app, repository access for the app can be modified to add new repositories or remove existing repositories. If a new repository is created, it may need to be added explicitly.
1. From the GitHub profile, navigate to `Settings` > `Applications` > `hosted-langserve` > click `Configure`.
1. Under `Repository access`, select `All repositories` or `Only select repositories`. If `Only select repositories` is selected, new repositories must be explicitly added.
1. Click `Save`.
1. When creating a new deployment, the list of GitHub repositories in the dropdown menu will be updated to reflect the repository access changes.
## Whitelisting IP Addresses
All traffic from `LangGraph Platform` deployments created after January 6th 2025 will come through a NAT gateway.
This NAT gateway will have several static ip addresses depending on the region you are deploying in. Refer to the table below for the list of IP addresses to whitelist:
| US | EU |
|----------------|----------------|
| 35.197.29.146 | 34.13.192.67 |
| 34.145.102.123 | 34.147.105.64 |
| 34.169.45.153 | 34.90.22.166 |
| 34.82.222.17 | 34.147.36.213 |
| 35.227.171.135 | 34.32.137.113 |
| 34.169.88.30 | 34.91.238.184 |
| 34.19.93.202 | 35.204.101.241 |
| 34.19.34.50 | 35.204.48.32 |
@@ -0,0 +1,56 @@
# How to Deploy Self-Hosted Control Plane
Before deploying, review the [conceptual guide for the Self-Hosted Control Plane](../../concepts/langgraph_self_hosted_control_plane.md) deployment option.
## Prerequisites
1. You are using Kubernetes.
1. You have self-hosted LangSmith deployed.
1. Use the [LangGraph CLI](../../concepts/langgraph_cli.md) to [test your application locally](./test_locally.md).
1. Use the [LangGraph CLI](../../concepts/langgraph_cli.md) to build a Docker image (i.e. `langgraph build`) and push it to a registry your Kubernetes cluster has access to.
1. `KEDA` is installed on your cluster.
helm repo add kedacore https://kedacore.github.io/charts
helm install keda kedacore/keda --namespace keda --create-namespace
1. Ingress Configuration (recommended)
1. Install `Ingress Nginx` to serve as a reverse proxy for your deployment.
helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx
helm repo update
helm install ingress-nginx ingress-nginx/ingress-nginx
1. Provision a root domain that will suffix all domains for your workloads (e.g. `us.langgraph.app`).
1. Provision wildcard certificates to terminate TLS for your deployments.
1. Note: If this step is skipped, you will need to provision domains/certs for each of your deployments.
1. You have slack space in your cluster for multiple deployments. `Cluster-Autoscaler` is recommended to automatically provision new nodes.
## Setup
1. As part of configuring your Self-Hosted LangSmith instance, you enable the `langgraphPlatform` option. This will provision a few key resources.
1. `listener`: This is a service that listens to the [control plane](../../concepts/langgraph_control_plane.md) for changes to your deployments and creates/updates downstream CRDs.
1. `LangGraphPlatform CRD`: A CRD for LangGraph Platform deployments. This contains the spec for managing an instance of a LangGraph platform deployment.
1. `operator`: This operator handles changes to your LangGraph Platform CRDs.
1. `host-backend`: This is the [control plane](../../concepts/langgraph_control_plane.md).
1. Two additional images will be used by the chart.
hostBackendImage:
repository: "docker.io/langchain/hosted-langserve-backend"
pullPolicy: IfNotPresent
tag: "0.9.80"
operatorImage:
repository: "docker.io/langchain/langgraph-operator"
pullPolicy: IfNotPresent
tag: "aa9dff4"
1. In your `values.yaml` file, enable the `langgraphPlatform` option.
config:
langgraphPlatform:
enabled: true
langgraphPlatformLicenseKey: "YOUR_LANGGRAPH_PLATFORM_LICENSE_KEY"
rootDomain: "YOUR_ROOT_DOMAIN"
1. You can also configure base templates for your agents by overriding the base templates [here](https://github.com/langchain-ai/helm/blob/main/charts/langsmith/values.yaml#L898).
1. You create a deployment from the [Control Plane UI](../../concepts/langgraph_control_plane.md#control-plane-ui).
@@ -0,0 +1,53 @@
# How to Deploy Self-Hosted Data Plane
Before deploying, review the [conceptual guide for the Self-Hosted Data Plane](../../concepts/langgraph_self_hosted_data_plane.md) deployment option.
## Prerequisites
1. Use the [LangGraph CLI](../../concepts/langgraph_cli.md) to [test your application locally](./test_locally.md).
1. Use the [LangGraph CLI](../../concepts/langgraph_cli.md) to build a Docker image (i.e. `langgraph build`) and push it to a registry your Kubernetes cluster or Amazon ECS cluster has access to.
## Kubernetes
### Prerequisites
1. `KEDA` is installed on your cluster.
helm repo add kedacore https://kedacore.github.io/charts
helm install keda kedacore/keda --namespace keda --create-namespace
1. A valid `Ingress` controller is install on your cluster.
1. You have slack space in your cluster for multiple deployments. `Cluster-Autoscaler` is recommended to automatically provision new nodes.
### Setup
1. You give us your LangSmith organization ID. We will enable the Self-Hosted Data Plane for your organization.
1. We provide you a [Helm chart](https://github.com/langchain-ai/helm/tree/main/charts/langgraph-dataplane) which you run to setup your Kubernetes cluster. This chart contains a few important components.
1. `langgraph-listener`: This is a service that listens to LangChain's [control plane](../../concepts/langgraph_control_plane.md) for changes to your deployments and creates/updates downstream CRDs.
1. `LangGraphPlatform CRD`: A CRD for LangGraph Platform deployments. This contains the spec for managing an instance of a LangGraph Platform deployment.
1. `langgraph-platform-operator`: This operator handles changes to your LangGraph Platform CRDs.
1. Configure your `langgraph-dataplane-values.yaml` file.
config:
langgraphPlatformLicenseKey: "" # Your LangGraph Platform license key
langsmithApiKey: "" # API Key of your Workspace
langsmithWorkspaceId: "" # Workspace ID
hostBackendUrl: "https://api.host.langchain.com" # Only override this if on EU
smithBackendUrl: "https://api.smith.langchain.com" # Only override this if on EU
1. Deploy `langgraph-dataplane` Helm chart.
helm repo add langchain https://langchain-ai.github.io/helm/
helm repo update
helm upgrade -i langgraph-dataplane langchain/langgraph-dataplane --values langgraph-dataplane-values.yaml
1. If successful, you will see two services start up in your namespace.
NAME READY STATUS RESTARTS AGE
langgraph-dataplane-listener-7fccd788-wn2dx 0/1 Running 0 9s
langgraph-dataplane-redis-0 0/1 ContainerCreating 0 9s
1. You create a deployment from the [Control Plane UI](../../concepts/langgraph_control_plane.md#control-plane-ui).
## Amazon ECS
Coming soon!
@@ -17,7 +17,7 @@ This guide explains how to add semantic search to your LangGraph deployment's cr
...
"store": {
"index": {
"embed": "openai:text-embeddings-3-small",
"embed": "openai:text-embedding-3-small",
"dims": 1536,
"fields": ["$"]
}
@@ -27,7 +27,7 @@ This guide explains how to add semantic search to your LangGraph deployment's cr
This configuration:
- Uses OpenAI's text-embeddings-3-small model for generating embeddings
- Uses OpenAI's text-embedding-3-small model for generating embeddings
- Sets the embedding dimension to 1536 (matching the model's output)
- Indexes all fields in your stored data (`["$"]` means index everything, or specify specific fields like `["text", "metadata.title"]`)
+5 -6
View File
@@ -36,21 +36,20 @@ Dependencies can optionally be specified in one of the following files: `pyproje
The dependencies below will be included in the image, you can also use them in your code, as long as with a compatible version range:
```
langgraph>=0.2.56,<0.3.0
langgraph-checkpoint>=2.0.5,<3.0
langgraph>=0.2.56,<0.4.0
langgraph-sdk>=0.1.53
langgraph-checkpoint>=2.0.15,<3.0
langchain-core>=0.2.38,<0.4.0
langsmith>=0.1.63
orjson>=3.9.7
httpx>=0.25.0
tenacity>=8.0.0
uvicorn>=0.26.0
sse-starlette>=2.1.0
sse-starlette>=2.1.0,<2.2.0
uvloop>=0.18.0
httptools>=0.5.0
jsonschema-rs>=0.16.3
croniter>=1.0.1
jsonschema-rs>=0.20.0
structlog>=23.1.0
redis>=5.0.0,<6.0.0
```
Example `requirements.txt` file:
@@ -36,21 +36,20 @@ Dependencies can optionally be specified in one of the following files: `pyproje
The dependencies below will be included in the image, you can also use them in your code, as long as with a compatible version range:
```
langgraph>=0.2.56,<0.3.0
langgraph-checkpoint>=2.0.5,<3.0
langgraph>=0.2.56,<0.4.0
langgraph-sdk>=0.1.53
langgraph-checkpoint>=2.0.15,<3.0
langchain-core>=0.2.38,<0.4.0
langsmith>=0.1.63
orjson>=3.9.7
httpx>=0.25.0
tenacity>=8.0.0
uvicorn>=0.26.0
sse-starlette>=2.1.0
sse-starlette>=2.1.0,<2.2.0
uvloop>=0.18.0
httptools>=0.5.0
jsonschema-rs>=0.16.3
croniter>=1.0.1
jsonschema-rs>=0.20.0
structlog>=23.1.0
redis>=5.0.0,<6.0.0
```
Example `pyproject.toml` file:
@@ -65,7 +64,7 @@ license = "MIT"
readme = "README.md"
[tool.poetry.dependencies]
python = ">=3.9.0,<3.13"
python = ">=3.9"
langgraph = "^0.2.0"
langchain-fireworks = "^0.1.3"
@@ -0,0 +1,110 @@
# How to Deploy a Standalone Container
Before deploying, review the [conceptual guide for the Standalone Container](../../concepts/langgraph_standalone_container.md) deployment option.
## Prerequisites
1. Use the [LangGraph CLI](../../concepts/langgraph_cli.md) to [test your application locally](./test_locally.md).
1. Use the [LangGraph CLI](../../concepts/langgraph_cli.md) to build a Docker image (i.e. `langgraph build`).
1. The following environment variables are needed for a standalone container deployment.
1. `REDIS_URI`: Connection details to a Redis instance. Redis will be used as a pub-sub broker to enable streaming real time output from background runs. The value of `REDIS_URI` must be a valid [Redis connection URI](https://redis-py.readthedocs.io/en/stable/connections.html#redis.Redis.from_url).
!!! Note "Shared Redis Instance"
Multiple self-hosted deployments can share the same Redis instance. For example, for `Deployment A`, `REDIS_URI` can be set to `redis://<hostname_1>:<port>/1` and for `Deployment B`, `REDIS_URI` can be set to `redis://<hostname_1>:<port>/2`.
`1` and `2` are different database numbers within the same instance, but `<hostname_1>` is shared. **The same database number cannot be used for separate deployments**.
1. `DATABASE_URI`: Postgres connection details. Postgres will be used to store assistants, threads, runs, persist thread state and long term memory, and to manage the state of the background task queue with 'exactly once' semantics. The value of `DATABASE_URI` must be a valid [Postgres connection URI](https://www.postgresql.org/docs/current/libpq-connect.html#LIBPQ-CONNSTRING-URIS).
!!! Note "Shared Postgres Instance"
Multiple self-hosted deployments can share the same Postgres instance. For example, for `Deployment A`, `DATABASE_URI` can be set to `postgres://<user>:<password>@/<database_name_1>?host=<hostname_1>` and for `Deployment B`, `DATABASE_URI` can be set to `postgres://<user>:<password>@/<database_name_2>?host=<hostname_1>`.
`<database_name_1>` and `database_name_2` are different databases within the same instance, but `<hostname_1>` is shared. **The same database cannot be used for separate deployments**.
1. `LANGSMITH_API_KEY`: (if using [Lite](../../concepts/langgraph_data_plane.md#lite-vs-enterprise)) LangSmith API key. This will be used to authenticate ONCE at server start up.
1. `LANGGRAPH_CLOUD_LICENSE_KEY`: (if using [Enterprise](../../concepts/langgraph_data_plane.md#lite-vs-enterprise)) LangGraph Platform license key. This will be used to authenticate ONCE at server start up.
1. `LANGSMITH_ENDPOINT`: To send traces to a [self-hosted LangSmith](https://docs.smith.langchain.com/self_hosting) instance, set `LANGSMITH_ENDPOINT` to the hostname of the self-hosted LangSmith instance.
## Kubernetes (Helm)
Use this [Helm chart](https://github.com/langchain-ai/helm/blob/main/charts/langgraph-cloud/README.md) to deploy a LangGraph Server to a Kubernetes cluster.
## Docker
Run the following `docker` command:
```shell
docker run \
--env-file .env \
-p 8123:8000 \
-e REDIS_URI="foo" \
-e DATABASE_URI="bar" \
-e LANGSMITH_API_KEY="baz" \
my-image
```
!!! note
* You need to replace `my-image` with the name of the image you built in the prerequisite steps (from `langgraph build`)
and you should provide appropriate values for `REDIS_URI`, `DATABASE_URI`, and `LANGSMITH_API_KEY`.
* If your application requires additional environment variables, you can pass them in a similar way.
## Docker Compose
Docker Compose YAML file:
```yml
volumes:
langgraph-data:
driver: local
services:
langgraph-redis:
image: redis:6
healthcheck:
test: redis-cli ping
interval: 5s
timeout: 1s
retries: 5
langgraph-postgres:
image: postgres:16
ports:
- "5433:5432"
environment:
POSTGRES_DB: postgres
POSTGRES_USER: postgres
POSTGRES_PASSWORD: postgres
volumes:
- langgraph-data:/var/lib/postgresql/data
healthcheck:
test: pg_isready -U postgres
start_period: 10s
timeout: 1s
retries: 5
interval: 5s
langgraph-api:
image: ${IMAGE_NAME}
ports:
- "8123:8000"
depends_on:
langgraph-redis:
condition: service_healthy
langgraph-postgres:
condition: service_healthy
env_file:
- .env
environment:
REDIS_URI: redis://langgraph-redis:6379
LANGSMITH_API_KEY: ${LANGSMITH_API_KEY}
POSTGRES_URI: postgres://postgres:postgres@langgraph-postgres:5432/postgres?sslmode=disable
```
You can run the command `docker compose up` with this Docker Compose file in the same folder.
This will launch a LangGraph Server on port `8123` (if you want to change this, you can change this by changing the ports in the `langgraph-api` volume). You can test if the application is healthy by running:
```shell
curl --request GET --url 0.0.0.0:8123/ok
```
Assuming everything is running correctly, you should see a response like:
```shell
{"ok":true}
```
@@ -0,0 +1,31 @@
# Testing local agents with remote traces
## Overview
A common workflow when debugging production-deployed agents is to test the same thread against a local version of the same agent, which may have modifications.
To support this, LangGraph Studio, in combination with LangSmith, allows you to clone remote threads traced in LangSmith into your locally running agent. This cloned thread can then be used to re-run specific nodes within Studio.
## Requirements
!!! info "Prerequisites"
- langgraph>=0.3.18
- langgraph-api>=0.0.32
- A thread traced in LangSmith.
- A locally running agent. See [here](../../how-tos/local-studio.md) for setup instructions.
- Note that your local agent must be using the above specified `langgraph` and `langgraph-api` versions.
- The nodes present in the remote trace must exist in at least one of the graphs in your local agent.
## Cloning Thread
First navigate to the LangSmith trace. Here you should see a button to "Run in Studio".
![Run in Studio](../img/run_in_studio.png){width=1200}
This will prompt you to enter the url that your locally running agent is accessible at. Once provided, select "Clone thread locally". If you have multiple graphs in your agent, you will also be prompted to select a graph to clone this thread under.
Once selected, a will a new thread in your local agent will be created and the thread history will be reconstruced to reflect the original trace.
Alternatively, if your trace originates from an agent deployed on LangGraph Platform, you can "View original thread" to open Studio with the actual deployed thread.
@@ -0,0 +1,366 @@
# How to implement Generative User Interfaces with LangGraph
!!! info "Prerequisites"
- [LangGraph Platform](../../concepts/langgraph_platform.md)
- [LangGraph Server](../../concepts/langgraph_server.md)
- [`useStream()` React Hook](./use_stream_react.md)
Generative user interfaces (Generative UI) allows agents to go beyond text and generate rich user interfaces. This enables creating more interactive and context-aware applications where the UI adapts based on the conversation flow and AI responses.
![Generative UI Sample](./img/generative_ui_sample.jpg)
LangGraph Platform supports colocating your React components with your graph code. This allows you to focus on building specific UI components for your graph while easily plugging into existing chat interfaces such as [Agent Chat](https://agentchat.vercel.app) and loading the code only when actually needed.
## Tutorial
### 1. Define and configure UI components
First, create your first UI component. For each component you need to provide an unique identifier that will be used to reference the component in your graph code.
```tsx title="src/agent/ui.tsx"
const WeatherComponent = (props: { city: string }) => {
return <div>Weather for {props.city}</div>;
};
export default {
weather: WeatherComponent,
};
```
Next, define your UI components in your `langgraph.json` configuration:
```json
{
"node_version": "20",
"graphs": {
"agent": "./src/agent/index.ts:graph"
},
"ui": {
"agent": "./src/agent/ui.tsx"
}
}
```
The `ui` section points to the UI components that will be used by graphs. By default, we recommend using the same key as the graph name, but you can split out the components however you like, see [Customise the namespace of UI components](#customise-the-namespace-of-ui-components) for more details.
LangGraph Platform will automatically bundle your UI components code and styles and serve them as external assets that can be loaded by the `LoadExternalComponent` component. Some dependencies such as `react` and `react-dom` will be automatically excluded from the bundle.
CSS and Tailwind 4.x is also supported out of the box, so you can freely use Tailwind classes as well as `shadcn/ui` in your UI components.
=== "`src/agent/ui.tsx`"
```tsx
import "./styles.css";
const WeatherComponent = (props: { city: string }) => {
return <div className="bg-red-500">Weather for {props.city}</div>;
};
export default {
weather: WeatherComponent,
};
```
=== "`src/agent/styles.css`"
```css
@import "tailwindcss";
```
### 2. Send the UI components in your graph
=== "Python"
```python title="src/agent.py"
import uuid
from typing import Annotated, Sequence, TypedDict
from langchain_core.messages import AIMessage, BaseMessage
from langchain_openai import ChatOpenAI
from langgraph.graph import StateGraph
from langgraph.graph.message import add_messages
from langgraph.graph.ui import AnyUIMessage, ui_message_reducer, push_ui_message
class AgentState(TypedDict): # noqa: D101
messages: Annotated[Sequence[BaseMessage], add_messages]
ui: Annotated[Sequence[AnyUIMessage], ui_message_reducer]
async def weather(state: AgentState):
class WeatherOutput(TypedDict):
city: str
weather: WeatherOutput = (
await ChatOpenAI(model="gpt-4o-mini")
.with_structured_output(WeatherOutput)
.with_config({"tags": ["nostream"]})
.ainvoke(state["messages"])
)
message = AIMessage(
id=str(uuid.uuid4()),
content=f"Here's the weather for {weather['city']}",
)
# Emit UI elements associated with the message
push_ui_message("weather", weather, message=message)
return {"messages": [message]}
workflow = StateGraph(AgentState)
workflow.add_node(weather)
workflow.add_edge("__start__", "weather")
graph = workflow.compile()
```
=== "JS"
Use the `typedUi` utility to emit UI elements from your agent nodes:
```typescript title="src/agent/index.ts"
import {
typedUi,
uiMessageReducer,
} from "@langchain/langgraph-sdk/react-ui/server";
import { ChatOpenAI } from "@langchain/openai";
import { v4 as uuidv4 } from "uuid";
import { z } from "zod";
import type ComponentMap from "./ui.js";
import {
Annotation,
MessagesAnnotation,
StateGraph,
type LangGraphRunnableConfig,
} from "@langchain/langgraph";
const AgentState = Annotation.Root({
...MessagesAnnotation.spec,
ui: Annotation({ reducer: uiMessageReducer, default: () => [] }),
});
export const graph = new StateGraph(AgentState)
.addNode("weather", async (state, config) => {
// Provide the type of the component map to ensure
// type safety of `ui.push()` calls as well as
// pushing the messages to the `ui` and sending a custom event as well.
const ui = typedUi<typeof ComponentMap>(config);
const weather = await new ChatOpenAI({ model: "gpt-4o-mini" })
.withStructuredOutput(z.object({ city: z.string() }))
.withConfig({ tags: ["nostream"] })
.invoke(state.messages);
const response = {
id: uuidv4(),
type: "ai",
content: `Here's the weather for ${weather.city}`,
};
// Emit UI elements associated with the AI message
ui.push({ name: "weather", props: weather }, { message: response });
return { messages: [response] };
})
.addEdge("__start__", "weather")
.compile();
```
### 3. Handle UI elements in your React application
On the client side, you can use `useStream()` and `LoadExternalComponent` to display the UI elements.
```tsx title="src/app/page.tsx"
"use client";
import { useStream } from "@langchain/langgraph-sdk/react";
import { LoadExternalComponent } from "@langchain/langgraph-sdk/react-ui";
export default function Page() {
const { thread, values } = useStream({
apiUrl: "http://localhost:2024",
assistantId: "agent",
});
return (
<div>
{thread.messages.map((message) => (
<div key={message.id}>
{message.content}
{values.ui
?.filter((ui) => ui.metadata?.message_id === message.id)
.map((ui) => (
<LoadExternalComponent key={ui.id} stream={thread} message={ui} />
))}
</div>
))}
</div>
);
}
```
Behind the scenes, `LoadExternalComponent` will fetch the JS and CSS for the UI components from LangGraph Platform and render them in a shadow DOM, thus ensuring style isolation from the rest of your application.
## How-to guides
### Show loading UI when components are loading
You can provide a fallback UI to be rendered when the components are loading.
```tsx
<LoadExternalComponent
stream={thread}
message={ui}
fallback={<div>Loading...</div>}
/>
```
### Provide custom components on the client side
If you already have the components loaded in your client application, you can provide a map of such components to be rendered directly without fetching the UI code from LangGraph Platform.
```tsx
const clientComponents = {
weather: WeatherComponent,
};
<LoadExternalComponent
stream={thread}
message={ui}
components={clientComponents}
/>;
```
### Customise the namespace of UI components.
By default `LoadExternalComponent` will use the `assistantId` from `useStream()` hook to fetch the code for UI components. You can customise this by providing a `namespace` prop to the `LoadExternalComponent` component.
=== "`src/app/page.tsx`"
```tsx
<LoadExternalComponent
stream={thread}
message={ui}
namespace="custom-namespace"
/>
```
=== "`langgraph.json`"
```json
{
"ui": {
"custom-namespace": "./src/agent/ui.tsx"
}
}
```
### Access and interact with the thread state from the UI component
You can access the thread state inside the UI component by using the `useStreamContext` hook.
```tsx
import { useStreamContext } from "@langchain/langgraph-sdk/react-ui";
const WeatherComponent = (props: { city: string }) => {
const { thread, submit } = useStreamContext();
return (
<>
<div>Weather for {props.city}</div>
<button
onClick={() => {
const newMessage = {
type: "human",
content: `What's the weather in ${props.city}?`,
};
submit({ messages: [newMessage] });
}}
>
Retry
</button>
</>
);
};
```
### Pass additional context to the client components
You can pass additional context to the client components by providing a `meta` prop to the `LoadExternalComponent` component.
```tsx
<LoadExternalComponent stream={thread} message={ui} meta={{ userId: "123" }} />
```
Then, you can access the `meta` prop in the UI component by using the `useStreamContext` hook.
```tsx
import { useStreamContext } from "@langchain/langgraph-sdk/react-ui";
const WeatherComponent = (props: { city: string }) => {
const { meta } = useStreamContext<
{ city: string },
{ MetaType: { userId?: string } }
>();
return (
<div>
Weather for {props.city} (user: {meta?.userId})
</div>
);
};
```
### Streaming UI updates before the node execution is finished
You can stream UI updates before the node execution is finished by using the `onCustomEvent` callback of the `useStream()` hook.
```tsx
import { uiMessageReducer } from "@langchain/langgraph-sdk/react-ui";
const { thread, submit } = useStream({
apiUrl: "http://localhost:2024",
assistantId: "agent",
onCustomEvent: (event, options) => {
options.mutate((prev) => {
const ui = uiMessageReducer(prev.ui ?? [], event);
return { ...prev, ui };
});
},
});
```
### Remove UI messages from state
Similar to how messages can be removed from the state by appending a RemoveMessage you can remove an UI message from the state by calling `remove_ui_message` / `ui.delete` with the ID of the UI message.
=== "Python"
```python
from langgraph.graph.ui import push_ui_message, delete_ui_message
# push message
message = push_ui_message("weather", {"city": "London"})
# remove said message
delete_ui_message(message["id"])
```
=== "JS"
```tsx
// push message
const message = ui.push({ name: "weather", props: { city: "London" } });
// remove said message
ui.delete(message.id);
```
## Learn more
- [JS/TS SDK Reference](../reference/sdk/js_ts_sdk_ref.md)
@@ -63,7 +63,7 @@ Now, let's invoke our graph by interrupting before `ask_human` node:
"messages": [
{
"role": "user",
"content": "Use the search tool to ask the user where they are, then look up the weather there",
"content": "Ask the user where they are, then look up the weather there",
}
]
}
@@ -85,8 +85,7 @@ Now, let's invoke our graph by interrupting before `ask_human` node:
messages: [
{
role: "human",
content: "Use the search tool to ask the user where they are, then look up the weather there"
}
content: "Ask the user where they are, then look up the weather there" }
]
};
@@ -115,7 +114,7 @@ Now, let's invoke our graph by interrupting before `ask_human` node:
--header 'Content-Type: application/json' \
--data "{
\"assistant_id\": \"agent\",
\"input\": {\"messages\": [{\"role\": \"human\", \"content\": \"Use the search tool to ask the user where they are, then look up the weather there\"}]},
\"input\": {\"messages\": [{\"role\": \"human\", \"content\": \"Ask the user where they are, then look up the weather there\"}]},
\"interrupt_before\": [\"ask_human\"],
\"stream_mode\": [
\"updates\"
Binary file not shown.

After

Width:  |  Height:  |  Size: 115 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 59 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 39 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 93 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 578 KiB

@@ -0,0 +1,140 @@
# Prompt Engineering in LangGraph Studio
## Overview
A central aspect of agent development is prompt engineering. LangGraph Studio makes it easy to iterate on the prompts used within your graph directly within the UI.
## Setup
The first step is to define your [configuration](https://langchain-ai.github.io/langgraph/how-tos/configuration/) such that LangGraph Studio is aware of the prompts you want to iterate on and which nodes they are associated with.
### Reference
When defining your configuration, you can use special metadata keys to instruct LangGraph Studio how to handle different fields. Here's a reference for the available configuration options:
#### `langgraph_nodes`
- **Description**: Specifies which graph nodes a configuration field is associated with.
- **Value Type**: Array of strings, where each string is the name of a node in your graph.
- **Usage Context**: Include in the `json_schema_extra` dictionary for Pydantic models or the `metadata["json_schema_extra"]` dictionary for dataclasses.
- **Required**: No, but necessary if you want a field to be editable for specific nodes in the UI.
- **Example**:
```python
system_prompt: str = Field(
default="You are a helpful AI assistant.",
json_schema_extra={"langgraph_nodes": ["call_model", "other_node"]},
)
```
#### `langgraph_type`
- **Description**: Specifies the type of configuration field, which determines how it's handled in the UI.
- **Value Type**: String
- **Supported Values**:
- `"prompt"`: Indicates the field contains prompt text that should be treated specially in the UI.
- **Usage Context**: Include in the `json_schema_extra` dictionary for Pydantic models or the `metadata["json_schema_extra"]` dictionary for dataclasses.
- **Required**: No, but helpful for prompt fields to enable special handling.
- **Example**:
```python
system_prompt: str = Field(
default="You are a helpful AI assistant.",
json_schema_extra={
"langgraph_nodes": ["call_model"],
"langgraph_type": "prompt",
},
)
```
### Example
For example, if you have a node called `call_model` whose system prompt you want to iterate on, you can define a configuration like the following.
```python
## Using Pydantic
from pydantic import BaseModel, Field
from typing import Annotated, Literal
class Configuration(BaseModel):
"""The configuration for the agent."""
system_prompt: str = Field(
default="You are a helpful AI assistant.",
description="The system prompt to use for the agent's interactions. "
"This prompt sets the context and behavior for the agent.",
json_schema_extra={
"langgraph_nodes": ["call_model"],
"langgraph_type": "prompt",
},
)
model: Annotated[
Literal[
"anthropic/claude-3-7-sonnet-latest",
"anthropic/claude-3-5-haiku-latest",
"openai/o1",
"openai/gpt-4o-mini",
"openai/o1-mini",
"openai/o3-mini",
],
{"__template_metadata__": {"kind": "llm"}},
] = Field(
default="openai/gpt-4o-mini",
description="The name of the language model to use for the agent's main interactions. "
"Should be in the form: provider/model-name.",
json_schema_extra={"langgraph_nodes": ["call_model"]},
)
## Using Dataclasses
from dataclasses import dataclass, field
@dataclass(kw_only=True)
class Configuration:
"""The configuration for the agent."""
system_prompt: str = field(
default="You are a helpful AI assistant.",
metadata={
"description": "The system prompt to use for the agent's interactions. "
"This prompt sets the context and behavior for the agent.",
"json_schema_extra": {"langgraph_nodes": ["call_model"]},
},
)
model: Annotated[str, {"__template_metadata__": {"kind": "llm"}}] = field(
default="anthropic/claude-3-5-sonnet-20240620",
metadata={
"description": "The name of the language model to use for the agent's main interactions. "
"Should be in the form: provider/model-name.",
"json_schema_extra": {"langgraph_nodes": ["call_model"]},
},
)
```
## Iterating on prompts
### Node Configuration
With this set up, running your graph and viewing in LangGraph Studio will result in the graph rendering like such.
**Note the configuration icon in the top right corner of the `call_model` node**:
![Graph in Studio](../img/studio_graph_with_configuration.png){width=1200}
Clicking this icon will open a modal where you can edit the configuration for all of the fields associated with the `call_model` node. From here, you can save your changes and apply them to the graph. Note that these values reflect the currently active assistant, and saving will update the assistant with the new values.
![Configuration modal](../img/studio_node_configuration.png){width=1200}
### Playground
LangGraph Studio also supports prompt engineering through an integration with the LangSmith Playground. To do so:
1. Open an existing thread or create a new one.
2. Within the thread log, any nodes that have made an LLM call will have a "View LLM Runs" button. Clicking this will open a popover with the LLM runs for that node.
3. Select the LLM run you want to edit. This will open the LangSmith Playground with the selected LLM run.
![Playground in Studio](../img/studio_playground.png){width=1200}
From here you can edit the prompt, test different model configurations and re-run just this LLM call without having to re-run the entire graph. When you are happy with your changes, you can copy the updated prompt back into your graph.
For more information on how to use the LangSmith Playground, see the [LangSmith Playground documentation](https://docs.smith.langchain.com/prompt_engineering/how_to_guides#playground).
File diff suppressed because it is too large Load Diff
+3 -3
View File
@@ -1,10 +1,10 @@
# Test Cloud Deployment
# Test LangGraph Platform Deployment
The LangGraph Studio UI connects directly to LangGraph Cloud deployments.
The LangGraph Studio UI connects directly to LangGraph Platform deployments.
Starting from the <a href="https://smith.langchain.com/" target="_blank">LangSmith UI</a>...
1. In the left-hand navigation panel, select `LangGraph Cloud`. The `LangGraph Cloud` view contains a list of existing LangGraph Cloud deployments.
1. In the left-hand navigation panel, select `LangGraph Platform`. The `LangGraph Platform` view contains a list of existing LangGraph Platform deployments.
1. Select an existing deployment to test with LangGraph Studio.
1. In the top-right corner, select `Open LangGraph Studio`.
1. [Invoke an assistant](./invoke_studio.md) or [view an existing thread](./threads_studio.md).
+115 -48
View File
@@ -1,7 +1,8 @@
# How to integrate LangGraph into your React application
!!! info "Prerequisites"
- [LangGraph Platform](../../concepts/langgraph_platform.md)
!!! info "Prerequisites"
- [LangGraph Platform](../../concepts/langgraph_platform.md)
- [LangGraph Server](../../concepts/langgraph_server.md)
The `useStream()` React hook provides a seamless way to integrate LangGraph into your React applications. It handles all the complexities of streaming, state management, and branching logic, letting you focus on building great chat experiences.
@@ -9,19 +10,18 @@ The `useStream()` React hook provides a seamless way to integrate LangGraph into
Key features:
- Messages streaming: Handle a stream of message chunks to form a complete message
- Automatic state management for messages, loading states, and errors
- Automatic state management for messages, interrupts, loading states, and errors
- Conversation branching: Create alternate conversation paths from any point in the chat history
- UI-agnostic design - bring your own components and styling
- UI-agnostic design: bring your own components and styling
Let's explore how to use `useStream()` in your React application.
The `useStream()` provides a solid foundation for creating bespoke chat experiences. For pre-built chat components and interfaces, we recommend checking out [CopilotKit](https://docs.copilotkit.ai/coagents/quickstart/langgraph) and [assistant-ui](https://www.assistant-ui.com/docs/runtimes/langgraph).
The `useStream()` provides a solid foundation for creating bespoke chat experiences. For pre-built chat components and interfaces, we also recommend checking out [CopilotKit](https://docs.copilotkit.ai/coagents/quickstart/langgraph) and [assistant-ui](https://www.assistant-ui.com/docs/runtimes/langgraph).
## Installation
```bash
npm install @langchain/langgraph-sdk @langchain/langchain-core react
npm install @langchain/langgraph-sdk @langchain/core
```
## Example
@@ -65,9 +65,7 @@ export default function App() {
Stop
</button>
) : (
<button key="submit" type="submit">
Send
</button>
<button keytype="submit">Send</button>
)}
</form>
</div>
@@ -81,6 +79,7 @@ The `useStream()` hook takes care of all the complex state management behind the
- Thread state management
- Loading and error states
- Interrupts
- Message handling and updates
- Branching support
@@ -134,9 +133,9 @@ We recommend storing the `threadId` in your URL's query parameters to let users
### Messages Handling
To enable messages handling, you need to pass the `messagesKey` option to the `useStream()` hook.
The `useStream()` hook will keep track of the message chunks received from the server and concatenate them together to form a complete message. The completed message chunks can be retrieved via the `messages` property.
When enabled, the `useStream()` hook will keep track of the message chunks received from the server and concatenate them together to form a complete message. The completed message chunks can be retrieved via the `messages` property.
By default, the `messagesKey` is set to `messages`, where it will append the new messages chunks to `values["messages"]`. If you store messages in a different key, you can change the value of `messagesKey`.
```tsx
import type { Message } from "@langchain/langgraph-sdk";
@@ -159,9 +158,45 @@ export default function HomePage() {
}
```
### Branching Support
Under the hood, the `useStream()` hook will use the `streamMode: "messages-key"` to receive a stream of messages (i.e. individual LLM tokens) from any LangChain chat model invocations inside your graph nodes. Learn more about messages streaming in the [How to stream messages from your graph](./stream_messages.md) guide.
To enable branching, you need to enable messages handling. Pass the `messagesKey` option to the `useStream()` hook. For each message, you can use `getMessagesMetadata()` to get the first checkpoint from which the message has been first seen. You can then create a new run from the checkpoint preceding the first seen checkpoint to create a new branch in a thread.
### Interrupts
The `useStream()` hook exposes the `interrupt` property, which will be filled with the last interrupt from the thread. You can use interrupts to:
- Render a confirmation UI before executing a node
- Wait for human input, allowing agent to ask the user with clarifying questions
Learn more about interrupts in the [How to handle interrupts](../../how-tos/human_in_the_loop/wait-user-input.ipynb) guide.
```tsx
const thread = useStream<{ messages: Message[] }, { InterruptType: string }>({
apiUrl: "http://localhost:2024",
assistantId: "agent",
messagesKey: "messages",
});
if (thread.interrupt) {
return (
<div>
Interrupted! {thread.interrupt.value}
<button
type="button"
onClick={() => {
// `resume` can be any value that the agent accepts
thread.submit(undefined, { command: { resume: true } });
}}
>
Resume
</button>
</div>
);
}
```
### Branching
For each message, you can use `getMessagesMetadata()` to get the first checkpoint from which the message has been first seen. You can then create a new run from the checkpoint preceding the first seen checkpoint to create a new branch in a thread.
A branch can be created in following ways:
@@ -169,23 +204,12 @@ A branch can be created in following ways:
2. Request a regeneration of a previous assistant message.
```tsx
/* eslint-disable @typescript-eslint/no-floating-promises */
"use client";
import type { Message } from "@langchain/langgraph-sdk";
import { useStream } from "@langchain/langgraph-sdk/react";
import {
Annotation,
MessagesAnnotation,
type StateType,
type UpdateType,
} from "@langchain/langgraph/web";
import { useState } from "react";
const AgentState = Annotation.Root({
...MessagesAnnotation.spec,
});
function BranchSwitcher({
branch,
branchOptions,
@@ -263,10 +287,7 @@ function EditMessage({
}
export default function App() {
const thread = useStream<
StateType<typeof AgentState.spec>,
UpdateType<typeof AgentState.spec>
>({
const thread = useStream({
apiUrl: "http://localhost:2024",
assistantId: "agent",
messagesKey: "messages",
@@ -344,13 +365,38 @@ export default function App() {
}
```
For advanced use cases you can use the `experimental_branchTree` property to get the tree representation of the thread, which can be used to render branching controls for non-message based graphs.
### Optimistic Updates
You can optimistically update the client state before performing a network request to the agent, allowing you to provide immediate feedback to the user, such as showing the user message immediately before the agent has seen the request.
```tsx
const stream = useStream({
apiUrl: "http://localhost:2024",
assistantId: "agent",
messagesKey: "messages",
});
const handleSubmit = (text: string) => {
const newMessage = { type: "human" as const, content: text };
stream.submit(
{ messages: [newMessage] },
{
optimisticValues(prev) {
const prevMessages = prev.messages ?? [];
const newMessages = [...prevMessages, newMessage];
return { ...prev, messages: newMessages };
},
}
);
};
```
### TypeScript
The `useStream()` hook is fully typed to help catch errors early and provide better IDE support. You can specify types for:
- State shape
- Update format
- Custom events
The `useStream()` hook is friendly for apps written in TypeScript and you can specify types for the state to get better type safety and IDE support.
```tsx
// Define your types
@@ -359,25 +405,46 @@ type State = {
context?: Record<string, unknown>;
};
type Update = {
messages: Message[] | Message;
context?: Record<string, unknown>;
};
type CustomEvent = {
type: "progress" | "debug";
payload: unknown;
};
// Use them with the hook
const thread = useStream<State, Update, CustomEvent>({
const thread = useStream<State>({
apiUrl: "http://localhost:2024",
assistantId: "agent",
messagesKey: "messages",
});
```
If you're using LangGraph.js, you can reuse your graph's annotation types:
You can also optionally specify types for different scenarios, such as:
- `ConfigurableType`: Type for the `config.configurable` property (default: `Record<string, unknown>`)
- `InterruptType`: Type for the interrupt value - i.e. contents of `interrupt(...)` function (default: `unknown`)
- `CustomEventType`: Type for the custom events (default: `unknown`)
- `UpdateType`: Type for the submit function (default: `Partial<State>`)
```tsx
const thread = useStream<
State,
{
UpdateType: {
messages: Message[] | Message;
context?: Record<string, unknown>;
};
InterruptType: string;
CustomEventType: {
type: "progress" | "debug";
payload: unknown;
};
ConfigurableType: {
model: string;
};
}
>({
apiUrl: "http://localhost:2024",
assistantId: "agent",
messagesKey: "messages",
});
```
If you're using LangGraph.js, you can also reuse your graph's annotation types. However, make sure to only import the types of the annotation schema in order to avoid importing the entire LangGraph.js runtime (i.e. via `import type { ... }` directive).
```tsx
import {
@@ -394,7 +461,7 @@ const AgentState = Annotation.Root({
const thread = useStream<
StateType<typeof AgentState.spec>,
UpdateType<typeof AgentState.spec>
{ UpdateType: UpdateType<typeof AgentState.spec> }
>({
apiUrl: "http://localhost:2024",
assistantId: "agent",
@@ -410,7 +477,7 @@ The `useStream()` hook provides several callback options to help you respond to
- `onFinish`: Called when the stream is finished.
- `onUpdateEvent`: Called when an update event is received.
- `onCustomEvent`: Called when a custom event is received. See [Custom events](../../concepts/streaming.md#custom) to learn how to stream custom events.
- `onMetadataEvent`: Called when a metadata event is received.
- `onMetadataEvent`: Called when a metadata event is received, which contains the Run ID and Thread ID.
## Learn More
+119 -114
View File
@@ -1,142 +1,147 @@
# Use Webhooks
# Using Webhooks
You may wish to use webhooks in your client, especially when using async streams in case you want to update something in your service once the API call to LangGraph Cloud has finished running. To do so, you will need to expose an endpoint that can accept POST requests, and then pass it to your API request in the "webhook" parameter.
When working with LangGraph Cloud, you may want to use webhooks to receive updates after an API call completes. Webhooks are useful for triggering actions in your service once a run has finished processing. To implement this, you need to expose an endpoint that can accept `POST` requests and pass this endpoint as a `webhook` parameter in your API request.
Currently, the SDK has not exposed this endpoint but you can access it through curl commands as follows.
Currently, the SDK does not provide built-in support for defining webhook endpoints, but you can specify them manually using API requests.
The following endpoints accept `webhook` as a parameter:
## Supported Endpoints
- Create Run -> POST /thread/{thread_id}/runs
- Create Thread Cron -> POST /thread/{thread_id}/runs/crons
- Stream Run -> POST /thread/{thread_id}/runs/stream
- Wait Run -> POST /thread/{thread_id}/runs/wait
- Create Cron -> POST /runs/crons
- Stream Run Stateless -> POST /runs/stream
- Wait Run Stateless -> POST /runs/wait
The following API endpoints accept a `webhook` parameter:
In this example, we will show calling a webhook after streaming a run.
| Operation | HTTP Method | Endpoint |
|-----------|------------|----------|
| Create Run | `POST` | `/thread/{thread_id}/runs` |
| Create Thread Cron | `POST` | `/thread/{thread_id}/runs/crons` |
| Stream Run | `POST` | `/thread/{thread_id}/runs/stream` |
| Wait Run | `POST` | `/thread/{thread_id}/runs/wait` |
| Create Cron | `POST` | `/runs/crons` |
| Stream Run Stateless | `POST` | `/runs/stream` |
| Wait Run Stateless | `POST` | `/runs/wait` |
## Setup
In this guide, well show how to trigger a webhook after streaming a run.
First, let's setup our assistant and thread:
## Setting Up Your Assistant and Thread
Before making API calls, set up your assistant and thread.
=== "Python"
```python
from langgraph_sdk import get_client
```python
from langgraph_sdk import get_client
client = get_client(url=<DEPLOYMENT_URL>)
assistant_id = "agent"
thread = await client.threads.create()
print(thread)
```
client = get_client(url=<DEPLOYMENT_URL>)
# Using the graph deployed with the name "agent"
assistant_id = "agent"
# create thread
thread = await client.threads.create()
print(thread)
```
=== "JavaScript"
```js
import { Client } from "@langchain/langgraph-sdk";
=== "Javascript"
```js
import { Client } from "@langchain/langgraph-sdk";
const client = new Client({ apiUrl: <DEPLOYMENT_URL> });
// Using the graph deployed with the name "agent"
const assistantID = "agent";
// create thread
const thread = await client.threads.create();
console.log(thread);
```
const client = new Client({ apiUrl: <DEPLOYMENT_URL> });
const assistantID = "agent";
const thread = await client.threads.create();
console.log(thread);
```
=== "CURL"
```bash
curl --request POST \
--url <DEPLOYMENT_URL>/assistants/search \
--header 'Content-Type: application/json' \
--data '{ "limit": 10, "offset": 0 }' | jq -c 'map(select(.config == null or .config == {})) | .[0]' && \
curl --request POST \
--url <DEPLOYMENT_URL>/threads \
--header 'Content-Type: application/json' \
--data '{}'
```
```bash
curl --request POST \
--url <DEPLOYMENT_URL>/assistants/search \
--header 'Content-Type: application/json' \
--data '{
"limit": 10,
"offset": 0
}' | jq -c 'map(select(.config == null or .config == {})) | .[0]' && \
curl --request POST \
--url <DEPLOYMENT_URL>/threads \
--header 'Content-Type: application/json' \
--data '{}'
```
### Example Response
```json
{
"thread_id": "9dde5490-2b67-47c8-aa14-4bfec88af217",
"created_at": "2024-08-30T23:07:38.242730+00:00",
"updated_at": "2024-08-30T23:07:38.242730+00:00",
"metadata": {},
"status": "idle",
"config": {},
"values": null
}
```
Output:
## Using a Webhook with a Graph Run
{
'thread_id': '9dde5490-2b67-47c8-aa14-4bfec88af217',
'created_at': '2024-08-30T23:07:38.242730+00:00',
'updated_at': '2024-08-30T23:07:38.242730+00:00',
'metadata': {},
'status': 'idle',
'config': {},
'values': None
}
To use a webhook, specify the `webhook` parameter in your API request. When the run completes, LangGraph Cloud sends a `POST` request to the specified webhook URL.
## Use graph with a webhook
To invoke a run with a webhook, we specify the `webhook` parameter with the desired endpoint when creating a run. Webhook requests are triggered by the end of a run.
For example, if we can receive requests at `https://my-server.app/my-webhook-endpoint`, we can pass this to `stream`:
For example, if your server listens for webhook events at `https://my-server.app/my-webhook-endpoint`, include this in your request:
=== "Python"
```python
input = { "messages": [{ "role": "user", "content": "Hello!" }] }
```python
# create input
input = { "messages": [{ "role": "user", "content": "Hello!" }] }
async for chunk in client.runs.stream(
thread_id=thread["thread_id"],
assistant_id=assistant_id,
input=input,
stream_mode="events",
webhook="https://my-server.app/my-webhook-endpoint"
):
pass
```
async for chunk in client.runs.stream(
thread_id=thread["thread_id"],
assistant_id=assistant_id,
input=input,
stream_mode="events",
webhook="https://my-server.app/my-webhook-endpoint"
):
# Do something with the stream output
pass
```
=== "JavaScript"
```js
const input = { messages: [{ role: "human", content: "Hello!" }] };
=== "Javascript"
const streamResponse = client.runs.stream(
thread["thread_id"],
assistantID,
{
input: input,
webhook: "https://my-server.app/my-webhook-endpoint"
}
);
```js
// create input
const input = { messages: [{ role: "human", content: "Hello!" }] };
// stream events
const streamResponse = client.runs.stream(
thread["thread_id"],
assistantID,
{
input: input,
webhook: "https://my-server.app/my-webhook-endpoint"
}
);
for await (const chunk of streamResponse) {
// Do something with the stream output
}
```
for await (const chunk of streamResponse) {
// Handle stream output
}
```
=== "CURL"
```bash
curl --request POST \
--url <DEPLOYMENT_URL>/threads/<THREAD_ID>/runs/stream \
--header 'Content-Type: application/json' \
--data '{
"assistant_id": <ASSISTANT_ID>,
"input" : {"messages":[{"role": "user", "content": "Hello!"}]},
"webhook": "https://my-server.app/my-webhook-endpoint"
}'
```
The schema for the payload sent to `my-webhook-endpoint` is that of a [run](../../concepts/langgraph_server.md/#runs). See [API Reference](https://langchain-ai.github.io/langgraph/cloud/reference/api/api_ref.html#model/run) for more detail. Note that the run input, configuration, etc. are included in the `kwargs` field.
### Signing webhook requests
To sign the webhook requests, we can specify a token parameter in the webhook URL, e.g.,
```
https://my-server.app/my-webhook-endpoint?token=...
```bash
curl --request POST \
--url <DEPLOYMENT_URL>/threads/<THREAD_ID>/runs/stream \
--header 'Content-Type: application/json' \
--data '{
"assistant_id": <ASSISTANT_ID>,
"input": {"messages": [{"role": "user", "content": "Hello!"}]},
"webhook": "https://my-server.app/my-webhook-endpoint"
}'
```
The server should then extract the token from the request's parameters and validate it before processing the payload.
## Webhook Payload
LangGraph Cloud sends webhook notifications in the format of a [Run](../../concepts/langgraph_server.md/#runs). See the [API Reference](https://langchain-ai.github.io/langgraph/cloud/reference/api/api_ref.html#model/run) for details. The request payload includes run input, configuration, and other metadata in the `kwargs` field.
## Securing Webhooks
To ensure only authorized requests hit your webhook endpoint, consider adding a security token as a query parameter:
```
https://my-server.app/my-webhook-endpoint?token=YOUR_SECRET_TOKEN
```
Your server should extract and validate this token before processing requests.
## Testing Webhooks
You can test your webhook using online services like:
- **[Beeceptor](https://beeceptor.com/)** Quickly create a test endpoint and inspect incoming webhook payloads.
- **[Webhook.site](https://webhook.site/)** View, debug, and log incoming webhook requests in real time.
These tools help you verify that LangGraph Cloud is correctly triggering and sending webhooks to your service.
---
By following these steps, you can integrate webhooks into your LangGraph Cloud workflow, automating actions based on completed runs.
+294 -11
View File
@@ -22,7 +22,7 @@
"description": "A run is an invocation of a graph / assistant, with no state or memory persistence."
},
{
"name": "Crons (Enterprise-only)",
"name": "Crons (Plus tier)",
"description": "A cron is a periodic run that recurs on a given schedule. The repeats can be isolated, or share state in a thread"
},
{
@@ -805,6 +805,58 @@
}
}
},
"/threads/state/bulk": {
"post": {
"tags": [
"Threads"
],
"summary": "Bulk Update Thread State",
"description": "Create a new thread from a batch of state updates.",
"operationId": "bulk_update_thread_state_post",
"requestBody": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ThreadStateBulkUpdate"
}
}
},
"required": true
},
"responses": {
"200": {
"description": "Success",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Thread"
}
}
}
},
"409": {
"description": "Conflict",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ErrorResponse"
}
}
}
},
"422": {
"description": "Validation Error",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ErrorResponse"
}
}
}
}
}
}
},
"/threads/{thread_id}/state": {
"get": {
"tags": [
@@ -1342,6 +1394,21 @@
},
"name": "offset",
"in": "query"
},
{
"required": false,
"schema": {
"type": "string",
"enum": [
"pending",
"error",
"success",
"timeout",
"interrupted"
]
},
"name": "status",
"in": "query"
}
],
"responses": {
@@ -1458,7 +1525,7 @@
"/threads/{thread_id}/runs/crons": {
"post": {
"tags": [
"Crons (Enterprise-only)"
"Crons (Plus tier)"
],
"summary": "Create Thread Cron",
"description": "Create a cron to schedule runs on a thread.",
@@ -1836,6 +1903,17 @@
},
"name": "run_id",
"in": "path"
},
{
"required": false,
"schema": {
"type": "boolean",
"title": "Cancel on Disconnect",
"description": "If true, the run will be cancelled if the client disconnects.",
"default": false
},
"name": "cancel_on_disconnect",
"in": "query"
}
],
"responses": {
@@ -2032,7 +2110,7 @@
"/runs/crons": {
"post": {
"tags": [
"Crons (Enterprise-only)"
"Crons (Plus tier)"
],
"summary": "Create Cron",
"description": "Create a cron to schedule runs on new threads.",
@@ -2084,7 +2162,7 @@
"/runs/crons/search": {
"post": {
"tags": [
"Crons (Enterprise-only)"
"Crons (Plus tier)"
],
"summary": "Search Crons",
"description": "Search all active crons",
@@ -2190,6 +2268,68 @@
}
}
},
"/runs/cancel": {
"post": {
"tags": [
"Thread Runs"
],
"summary": "Cancel Runs",
"description": "Cancel one or more runs. Can cancel runs by thread ID and run IDs, or by status filter.",
"operationId": "cancel_runs_post",
"parameters": [
{
"description": "Action to take when cancelling the run. Possible values are `interrupt` or `rollback`. `interrupt` will simply cancel the run. `rollback` will cancel the run and delete the run and associated checkpoints afterwards.",
"required": false,
"schema": {
"type": "string",
"enum": [
"interrupt",
"rollback"
],
"title": "Action",
"default": "interrupt"
},
"name": "action",
"in": "query"
}
],
"requestBody": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/RunsCancel"
}
}
},
"required": true
},
"responses": {
"204": {
"description": "Success - Runs cancelled"
},
"404": {
"description": "Not Found",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ErrorResponse"
}
}
}
},
"422": {
"description": "Validation Error",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ErrorResponse"
}
}
}
}
}
}
},
"/runs/wait": {
"post": {
"tags": [
@@ -2373,7 +2513,7 @@
"/runs/crons/{cron_id}": {
"delete": {
"tags": [
"Crons (Enterprise-only)"
"Crons (Plus tier)"
],
"summary": "Delete Cron",
"description": "Delete a cron by ID.",
@@ -2936,7 +3076,7 @@
"type": "string",
"maxLength": 65536,
"minLength": 1,
"format": "uri",
"format": "uri-reference",
"title": "Webhook",
"description": "Webhook to call after LangGraph API call is done."
},
@@ -3216,7 +3356,11 @@
"description": "The command to run.",
"properties": {
"update": {
"type": "object",
"type": [
"object",
"array",
"null"
],
"title": "Update",
"description": "An update to the state."
},
@@ -3226,12 +3370,13 @@
"array",
"number",
"string",
"boolean",
"null"
],
"title": "Resume",
"description": "A value to pass to an interrupted node."
},
"send": {
"goto": {
"anyOf": [
{
"$ref": "#/components/schemas/Send"
@@ -3242,10 +3387,21 @@
"$ref": "#/components/schemas/Send"
}
},
{
"type": "string"
},
{
"type": "array",
"items": {
"type": "string"
}
},
{
"type": "null"
}
]
],
"title": "Goto",
"description": "Name of the node(s) to navigate to next or node(s) to be executed with a provided input."
}
}
},
@@ -3276,6 +3432,18 @@
{
"type": "object"
},
{
"type": "array"
},
{
"type": "string"
},
{
"type": "number"
},
{
"type": "boolean"
},
{
"type": "null"
}
@@ -3326,7 +3494,7 @@
"type": "string",
"maxLength": 65536,
"minLength": 1,
"format": "uri",
"format": "uri-reference",
"title": "Webhook",
"description": "Webhook to call after LangGraph API call is done."
},
@@ -3491,6 +3659,18 @@
{
"type": "object"
},
{
"type": "array"
},
{
"type": "string"
},
{
"type": "number"
},
{
"type": "boolean"
},
{
"type": "null"
}
@@ -3541,7 +3721,7 @@
"type": "string",
"maxLength": 65536,
"minLength": 1,
"format": "uri",
"format": "uri-reference",
"title": "Webhook",
"description": "Webhook to call after LangGraph API call is done."
},
@@ -3840,6 +4020,36 @@
"title": "If Exists",
"description": "How to handle duplicate creation. Must be either 'raise' (raise error if duplicate), or 'do_nothing' (return existing thread).",
"default": "raise"
},
"ttl": {
"type": "object",
"title": "TTL",
"description": "The time-to-live for the thread.",
"properties": {
"strategy": {
"type": "string",
"enum": ["delete"],
"description": "The TTL strategy. 'delete' removes the entire thread.",
"default": "delete"
},
"ttl": {
"type": "number",
"description": "The time-to-live in minutes from now until thread should be swept."
}
}
},
"supersteps": {
"type": "array",
"items": {
"type": "object",
"properties": {
"updates": {
"type": "array",
"items": { "$ref": "#/components/schemas/ThreadSuperstepUpdate" }
}
},
"required": ["updates"]
}
}
},
"type": "object",
@@ -4028,6 +4238,43 @@
"title": "ThreadStateUpdate",
"description": "Payload for updating the state of a thread."
},
"ThreadSuperstepUpdate": {
"properties": {
"values": {
"anyOf": [
{
"type": "array",
"items": {
"type": "object"
}
},
{
"type": "object"
},
{
"type": "null"
}
]
},
"command": {
"anyOf": [
{
"$ref": "#/components/schemas/Command"
},
{
"type": "null"
}
],
"description": "The command associated with the update."
},
"as_node": {
"type": "string",
"description": "Update the state as if this node had just executed."
}
},
"required": ["as_node"],
"type": "object"
},
"ThreadStateUpdateResponse": {
"properties": {
"checkpoint": {
@@ -4230,6 +4477,42 @@
},
"description": "Represents a single document or data entry in the graph's Store. Items are used to store cross-thread memories."
},
"RunsCancel": {
"type": "object",
"title": "RunsCancel",
"description": "Payload for cancelling runs.",
"properties": {
"status": {
"type": "string",
"enum": ["pending", "running", "all"],
"title": "Status",
"description": "Filter runs by status to cancel. Must be one of 'pending', 'running', or 'all'."
},
"thread_id": {
"type": "string",
"format": "uuid",
"title": "Thread Id",
"description": "The ID of the thread containing runs to cancel."
},
"run_ids": {
"type": "array",
"items": {
"type": "string",
"format": "uuid"
},
"title": "Run Ids",
"description": "List of run IDs to cancel."
}
},
"oneOf": [
{
"required": ["status"]
},
{
"required": ["thread_id", "run_ids"]
}
]
},
"SearchItemsResponse": {
"type": "object",
"required": [
+66 -7
View File
@@ -1,6 +1,6 @@
# LangGraph CLI
The LangGraph command line interface includes commands to build and run a LangGraph Cloud API server locally in [Docker](https://www.docker.com/). For development and testing, you can use the CLI to deploy a local API server as an alternative to the [Studio desktop app](../../concepts/langgraph_studio.md).
The LangGraph command line interface includes commands to build and run a LangGraph Cloud API server locally in [Docker](https://www.docker.com/). For development and testing, you can use the CLI to deploy a local API server.
## Installation
@@ -29,7 +29,7 @@ The LangGraph command line interface includes commands to build and run a LangGr
## Configuration File {#configuration-file}
The LangGraph CLI requires a JSON configuration file with the following keys:
The LangGraph CLI requires a JSON configuration file that follows this [schema](https://raw.githubusercontent.com/langchain-ai/langgraph/refs/heads/main/libs/cli/schemas/schema.json). It contains the following properties:
<div class="admonition tip">
<p class="admonition-title">Note</p>
@@ -42,15 +42,17 @@ The LangGraph CLI requires a JSON configuration file with the following keys:
| Key | Description |
| ------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| <span style="white-space: nowrap;">`dependencies`</span> | **Required**. Array of dependencies for LangGraph Cloud API server. Dependencies can be one of the following: (1) `"."`, which will look for local Python packages, (2) `pyproject.toml`, `setup.py` or `requirements.txt` in the app directory `"./local_package"`, or (3) a package name. |
| <span style="white-space: nowrap;">`dependencies`</span> | **Required**. Array of dependencies for LangGraph Cloud API server. Dependencies can be one of the following: <ul><li>A single period (`"."`), which will look for local Python packages.</li><li>The directory path where `pyproject.toml`, `setup.py` or `requirements.txt` is located.</br></br>For example, if `requirements.txt` is located in the root of the project directory, specify `"./"`. If it's located in a subdirectory called `local_package`, specify `"./local_package"`. Do not specify the string `"requirements.txt"` itself.</li><li>A Python package name.</li></ul> |
| <span style="white-space: nowrap;">`graphs`</span> | **Required**. Mapping from graph ID to path where the compiled graph or a function that makes a graph is defined. Example: <ul><li>`./your_package/your_file.py:variable`, where `variable` is an instance of `langgraph.graph.state.CompiledStateGraph`</li><li>`./your_package/your_file.py:make_graph`, where `make_graph` is a function that takes a config dictionary (`langchain_core.runnables.RunnableConfig`) and creates an instance of `langgraph.graph.state.StateGraph` / `langgraph.graph.state.CompiledStateGraph`.</li></ul> |
| <span style="white-space: nowrap;">`auth`</span> | _(Added in v0.0.11)_ Auth configuration containing the path to your authentication handler. Example: `./your_package/auth.py:auth`, where `auth` is an instance of `langgraph_sdk.Auth`. See [authentication guide](../../concepts/auth.md) for details. |
| <span style="white-space: nowrap;">`env`</span> | Path to `.env` file or a mapping from environment variable to its value. |
| <span style="white-space: nowrap;">`store`</span> | Configuration for adding semantic search to the BaseStore. Contains the following fields: <ul><li>`index`: Configuration for semantic search indexing with fields:<ul><li>`embed`: Embedding provider (e.g., "openai:text-embedding-3-small") or path to custom embedding function</li><li>`dims`: Dimension size of the embedding model. Used to initialize the vector table.</li><li>`fields` (optional): List of fields to index. Defaults to `["$"]`, which means to index entire documents. Can be specific fields like `["text", "summary", "some.value"]`</li></ul></li></ul> |
| <span style="white-space: nowrap;">`python_version`</span> | `3.11` or `3.12`. Defaults to `3.11`. |
| <span style="white-space: nowrap;">`store`</span> | Configuration for adding semantic search and/or time-to-live (TTL) to the BaseStore. Contains the following fields: <ul><li>`index` (optional): Configuration for semantic search indexing with fields `embed`, `dims`, and optional `fields`.</li><li>`ttl` (optional): Configuration for item expiration. An object with optional fields: `refresh_on_read` (boolean, defaults to `true`), `default_ttl` (float, lifespan in **minutes**, defaults to no expiration), and `sweep_interval_minutes` (integer, how often to check for expired items, defaults to no sweeping).</li></ul> |
| <span style="white-space: nowrap;">`python_version`</span> | `3.11`, `3.12`, or `3.13`. Defaults to `3.11`. |
| <span style="white-space: nowrap;">`node_version`</span> | Specify `node_version: 20` to use LangGraph.js. |
| <span style="white-space: nowrap;">`pip_config_file`</span> | Path to `pip` config file. |
| <span style="white-space: nowrap;">`dockerfile_lines`</span> | Array of additional lines to add to Dockerfile following the import from parent image. |
| <span style="white-space: nowrap;">`checkpointer`</span> | Configuration for the checkpointer. Contains a `ttl` field which is an object with the following keys: <ul><li>`strategy`: How to handle expired checkpoints (e.g., `"delete"`).</li><li>`sweep_interval_minutes`: How often to check for expired checkpoints (integer).</li><li>`default_ttl`: Default time-to-live for checkpoints in **minutes** (integer). Defines how long checkpoints are kept before the specified strategy is applied.</li></ul> |
| <span style="white-space: nowrap;">`http`</span> | HTTP server configuration with the following fields: <ul><li>`app`: Path to custom Starlette/FastAPI app (e.g., `"./src/agent/webapp.py:app"`). See [custom routes guide](../../how-tos/http/custom_routes.md).</li><li>`disable_assistants`: Disable `/assistants` routes</li><li>`disable_threads`: Disable `/threads` routes</li><li>`disable_runs`: Disable `/runs` routes</li><li>`disable_store`: Disable `/store` routes</li><li>`disable_meta`: Disable `/ok`, `/info`, `/metrics`, and `/docs` routes</li><li>`cors`: CORS configuration with fields for `allow_origins`, `allow_methods`, `allow_headers`, etc.</li></ul> |
=== "JS"
@@ -58,9 +60,10 @@ The LangGraph CLI requires a JSON configuration file with the following keys:
| ------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| <span style="white-space: nowrap;">`graphs`</span> | **Required**. Mapping from graph ID to path where the compiled graph or a function that makes a graph is defined. Example: <ul><li>`./src/graph.ts:variable`, where `variable` is an instance of `CompiledStateGraph`</li><li>`./src/graph.ts:makeGraph`, where `makeGraph` is a function that takes a config dictionary (`LangGraphRunnableConfig`) and creates an instance of `StateGraph` / `CompiledStateGraph`.</li></ul> |
| <span style="white-space: nowrap;">`env`</span> | Path to `.env` file or a mapping from environment variable to its value. |
| <span style="white-space: nowrap;">`store`</span> | Configuration for adding semantic search to the BaseStore. Contains the following fields: <ul><li>`index`: Configuration for semantic search indexing with fields:<ul><li>`embed`: Embedding provider (e.g., "openai:text-embedding-3-small") or path to custom embedding function</li><li>`dims`: Dimension size of the embedding model. Used to initialize the vector table.</li><li>`fields` (optional): List of fields to index. Defaults to `["$"]`, which means to index entire documents. Can be specific fields like `["text", "summary", "some.value"]`</li></ul></li></ul> |
| <span style="white-space: nowrap;">`store`</span> | Configuration for adding semantic search and/or time-to-live (TTL) to the BaseStore. Contains the following fields: <ul><li>`index` (optional): Configuration for semantic search indexing with fields `embed`, `dims`, and optional `fields`.</li><li>`ttl` (optional): Configuration for item expiration. An object with optional fields: `refresh_on_read` (boolean, defaults to `true`), `default_ttl` (float, lifespan in **minutes**, defaults to no expiration), and `sweep_interval_minutes` (integer, how often to check for expired items, defaults to no sweeping).</li></ul> |
| <span style="white-space: nowrap;">`node_version`</span> | Specify `node_version: 20` to use LangGraph.js. |
| <span style="white-space: nowrap;">`dockerfile_lines`</span> | Array of additional lines to add to Dockerfile following the import from parent image. |
| <span style="white-space: nowrap;">`checkpointer`</span> | Configuration for the checkpointer. Contains a `ttl` field which is an object with the following keys: <ul><li>`strategy`: How to handle expired checkpoints (e.g., `"delete"`).</li><li>`sweep_interval_minutes`: How often to check for expired checkpoints (integer).</li><li>`default_ttl`: Default time-to-live for checkpoints in **minutes** (integer). Defines how long checkpoints are kept before the specified strategy is applied.</li></ul> |
### Examples
@@ -81,7 +84,7 @@ The LangGraph CLI requires a JSON configuration file with the following keys:
All deployments come with a DB-backed BaseStore. Adding an "index" configuration to your `langgraph.json` will enable [semantic search](../deployment/semantic_search.md) within the BaseStore of your deployment.
The `fields` configuration determines which parts of your documents to embed:
The `index.fields` configuration determines which parts of your documents to embed:
- If omitted or set to `["$"]`, the entire document will be embedded
- To embed specific fields, use JSON path notation: `["metadata.title", "content.text"]`
@@ -170,6 +173,62 @@ The LangGraph CLI requires a JSON configuration file with the following keys:
See the [authentication conceptual guide](../../concepts/auth.md) for details, and the [setting up custom authentication](../../tutorials/auth/getting_started.md) guide for a practical walk through of the process.
#### Configuring Store Item Time-to-Live (TTL)
You can configure default data expiration for items/memories in the BaseStore using the `store.ttl` key. This determines how long items are retained after they are last accessed (with reads potentially refreshing the timer based on `refresh_on_read`). Note that these defaults can be overwritten on a per-call basis by modifying the corresponding arguments in `get`, `search`, etc.
The `ttl` configuration is an object containing optional fields:
- `refresh_on_read`: If `true` (the default), accessing an item via `get` or `search` resets its expiration timer. Set to `false` to only refresh TTL on writes (`put`).
- `default_ttl`: The default lifespan of an item in **minutes**. If not set, items do not expire by default.
- `sweep_interval_minutes`: How frequently (in minutes) the system should run a background process to delete expired items. If not set, sweeping does not occur automatically.
Here is an example enabling a 7-day TTL (10080 minutes), refreshing on reads, and sweeping every hour:
```json
{
"dependencies": ["."],
"graphs": {
"memory_agent": "./agent/graph.py:graph"
},
"store": {
"ttl": {
"refresh_on_read": true,
"sweep_interval_minutes": 60,
"default_ttl": 10080
}
}
}
```
#### Configuring Checkpoint Time-to-Live (TTL)
You can configure the time-to-live (TTL) for checkpoints using the `checkpointer` key. This determines how long checkpoint data is retained before being automatically handled according to the specified strategy (e.g., deletion). The `ttl` configuration is an object containing:
- `strategy`: The action to take on expired checkpoints (currently `"delete"` is the only accepted option).
- `sweep_interval_minutes`: How frequently (in minutes) the system checks for expired checkpoints.
- `default_ttl`: The default lifespan of a checkpoint in **minutes**.
Here's an example setting a default TTL of 30 days (43200 minutes):
```json
{
"dependencies": ["."],
"graphs": {
"chat": "./chat/graph.py:graph"
},
"checkpointer": {
"ttl": {
"strategy": "delete",
"sweep_interval_minutes": 10,
"default_ttl": 43200
}
}
}
```
In this example, checkpoints older than 30 days will be deleted, and the check runs every 10 minutes.
=== "JS"
+32
View File
@@ -2,6 +2,28 @@
The LangGraph Cloud Server supports specific environment variables for configuring a deployment.
## `BG_JOB_ISOLATED_LOOPS`
Set `BG_JOB_ISOLATED_LOOPS` to `True` to execute background runs in an isolated event loop separate from the serving API event loop.
This environment variable should be set to `True` if the implementation of a graph/node contains synchronous code. In this situation, the synchronous code will block the serving API event loop, which may cause the API to be unavailable. A symptom of an unavailable API is continuous application restarts due to failing health checks.
Defaults to `False`.
## `BG_JOB_TIMEOUT_SECS`
The timeout of a background run can be increased. However, the infrastructure for a Cloud SaaS deployment enforces a 1 hour timeout limit for API requests. This means the connection between client and server will timeout after 1 hour. This is not configurable.
A background run can execute for longer than 1 hour, but a client must reconnect to the server (e.g. join stream via `POST /threads/{thread_id}/runs/{run_id}/stream`) to retrieve output from the run if the run is taking longer than 1 hour.
Defaults to `3600`.
## `DD_API_KEY`
Specify `DD_API_KEY` (your [Datadog API Key](https://docs.datadoghq.com/account_management/api-app-keys/)) to automatically enable Datadog tracing for the deployment. Specify other [`DD_*` environment variables](https://ddtrace.readthedocs.io/en/stable/configuration.html) to configure the tracing instrumentation.
If `DD_API_KEY` is specified, the application process is wrapped in the [`ddtrace-run` command](https://ddtrace.readthedocs.io/en/stable/installation_quickstart.html). Other `DD_*` environment variables (e.g. `DD_SITE`, `DD_ENV`, `DD_SERVICE`, `DD_TRACE_ENABLED`) are typically needed to properly configure the tracing instrumentation. See [`DD_*` environment variables](https://ddtrace.readthedocs.io/en/stable/configuration.html) for more details.
## `LANGCHAIN_TRACING_SAMPLING_RATE`
Sampling rate for traces sent to LangSmith. Valid values: Any float between `0` and `1`.
@@ -22,6 +44,10 @@ Set this environment variable to have a BYOC deployment send traces to a self-ho
`SELF_HOSTED_LANGSMITH_HOSTNAME` is the hostname of the self-hosted LangSmith instance. It must be accessible to the BYOC deployment. `LANGSMITH_API_KEY` is a LangSmith API generated from the self-hosted LangSmith instance.
## `LOG_LEVEL`
Configure [log level](https://docs.python.org/3/library/logging.html#logging-levels). Defaults to `INFO`.
## `N_JOBS_PER_WORKER`
Number of jobs per worker for the LangGraph Cloud task queue. Defaults to `10`.
@@ -49,3 +75,9 @@ Database Connectivity:
- The externally managed Postgres instance must be accessible by the LangGraph Server service in the ECS cluster. The BYOC user is responsible for ensuring connectivity.
- For example, if an AWS RDS Postgres instance is provisioned, it can be provisioned in the same VPC (`langgraph-cloud-vpc`) as the ECS cluster with the `langgraph-cloud-service-sg` security group to ensure connectivity.
## `REDIS_URI_CUSTOM`
For [Bring Your Own Cloud (BYOC)](../../concepts/bring_your_own_cloud.md) deployments only.
Specify `REDIS_URI_CUSTOM` to use an externally managed Redis instance. The value of `REDIS_URI_CUSTOM` must be a valid [Redis connection URI](https://redis-py.readthedocs.io/en/stable/connections.html#redis.Redis.from_url).
+1 -1
View File
@@ -14,7 +14,7 @@ As a result, there are many different types of [agent architectures](https://blo
## Router
A router allows an LLM to select a single step from a specified set of options. This is an agent architecture that exhibits a relatively limited level of control because the LLM usually focuses on making a single decision and produces a specific output from limited set of pre-defined options. Routers typically employ a few different concepts to achieve this.
A router allows an LLM to select a single step from a specified set of options. This is an agent architecture that exhibits a relatively limited level of control because the LLM usually focuses on making a single decision and produces a specific output from a limited set of pre-defined options. Routers typically employ a few different concepts to achieve this.
### Structured Output
+2 -6
View File
@@ -2,10 +2,6 @@
LangGraph Platform provides a flexible authentication and authorization system that can integrate with most authentication schemes.
!!! note "Python only"
We currently only support custom authentication and authorization in Python deployments with `langgraph-api>=0.0.11`. Support for LangGraph.JS will be added soon.
## Core Concepts
### Authentication vs Authorization
@@ -146,7 +142,7 @@ The returned user information is available:
After authentication, LangGraph calls your [`@auth.on`](../cloud/reference/sdk/python_sdk_ref.md#langgraph_sdk.auth.Auth.on) handlers to control access to specific resources (e.g., threads, assistants, crons). These handlers can:
1. Add metadata to be saved during resource creation by mutating the `value["metadata"]` dictionary directly. See the [supported actions table](##supported-actions) for the list of types the value can take for each action.
1. Add metadata to be saved during resource creation by mutating the `value["metadata"]` dictionary directly. See the [supported actions table](#supported-actions) for the list of types the value can take for each action.
2. Filter resources by metadata during search/list or read operations by returning a [filter dictionary](#filter-operations).
3. Raise an HTTP exception if access is denied.
@@ -289,7 +285,7 @@ async def on_assistant_create(
)
```
Notice that we are mixing global and resource-specific handlers in the above example. Since each request is handled by the most specific handler, a request to create a `thread` would match the `on_thread_create` handler but NOT the `reject_unhandled_requests` handler. A request to `update` a thread, however would be handled by the global handler, since we don't have a more specific handler for that resource and action. Requests to create, update,
Notice that we are mixing global and resource-specific handlers in the above example. Since each request is handled by the most specific handler, a request to create a `thread` would match the `on_thread_create` handler but NOT the `reject_unhandled_requests` handler. A request to `update` a thread, however would be handled by the global handler, since we don't have a more specific handler for that resource and action.
### Filter Operations {#filter-operations}
+1 -1
View File
@@ -83,7 +83,7 @@ node at a time or if you want to pause the graph execution at specific nodes.
### `NodeInterrupt` exception
We recommend that you [**use the `interrupt` function instead**](#the-interrupt-function) of the `NodeInterrupt` exception if you're trying to implement
We recommend that you [**use the `interrupt` function instead**][langgraph.types.interrupt] of the `NodeInterrupt` exception if you're trying to implement
[human-in-the-loop](./human_in_the_loop.md) workflows. The `interrupt` function is easier to use and more flexible.
??? node "`NodeInterrupt` exception"
+35 -60
View File
@@ -10,90 +10,65 @@
There are 4 main options for deploying with the LangGraph Platform:
1. **[Self-Hosted Lite](#self-hosted-lite)**: Available for all plans.
1. **[Cloud SaaS](#cloud-saas)**: Available for **Plus** and **Enterprise** plans.
2. **[Self-Hosted Enterprise](#self-hosted-enterprise)**: Available for the **Enterprise** plan.
1. **[Self-Hosted Data Plane](#self-hosted-data-plane)**: Available for the **Enterprise** plan.
3. **[Cloud SaaS](#cloud-saas)**: Available for **Plus** and **Enterprise** plans.
1. **[Self-Hosted Control Plane](#self-hosted-control-plane)**: Available for the **Enterprise** plan.
4. **[Bring Your Own Cloud](#bring-your-own-cloud)**: Available only for **Enterprise** plans and **only on AWS**.
1. **[Standalone Container](#standalone-container)**: Available for all plans.
Please see the [LangGraph Platform Plans](./plans.md) for more information on the different plans.
The guide below will explain the differences between the deployment options.
## Self-Hosted Enterprise
!!! important
The Self-Hosted Enterprise version is only available for the **Enterprise** plan.
!!! warning "Note"
The LangGraph Platform Deployments view is optionally available for Self-Hosted Enterprise LangGraph deployments. With one click, self-hosted LangGraph deployments can be deployed in the same Kubernetes cluster where a self-hosted LangSmith instance is deployed.
With a Self-Hosted Enterprise deployment, you are responsible for managing the infrastructure, including setting up and maintaining required databases and Redis instances.
Youll build a Docker image using the [LangGraph CLI](./langgraph_cli.md), which can then be deployed on your own infrastructure.
For more information, please see:
* [Self-Hosted conceptual guide](./self_hosted.md)
* [Self-Hosted Deployment how-to guide](../how-tos/deploy-self-hosted.md)
## Self-Hosted Lite
!!! important
The Self-Hosted Lite version is available for all plans.
!!! warning "Note"
The LangGraph Platform Deployments view is optionally available for Self-Hosted Lite LangGraph deployments. With one click, self-hosted LangGraph deployments can be deployed in the same Kubernetes cluster where a self-hosted LangSmith instance is deployed.
The Self-Hosted Lite deployment option is a free (up to 1 million nodes executed per year), limited version of LangGraph Platform that you can run locally or in a self-hosted manner.
With a Self-Hosted Lite deployment, you are responsible for managing the infrastructure, including setting up and maintaining required databases and Redis instances.
Youll build a Docker image using the [LangGraph CLI](./langgraph_cli.md), which can then be deployed on your own infrastructure.
[Cron jobs](../cloud/how-tos/cron_jobs.md) are not available for Self-Hosted Lite deployments.
For more information, please see:
* [Self-Hosted conceptual guide](./self_hosted.md)
* [Self-Hosted deployment how-to guide](../how-tos/deploy-self-hosted.md)
## Cloud SaaS
!!! important
The [Cloud SaaS](./langgraph_cloud.md) deployment option is a fully managed model for deployment where we manage the [control plane](./langgraph_control_plane.md) and [data plane](./langgraph_data_plane.md) in our cloud. This option provides a simple way to deploy and manage your LangGraph Servers.
The Cloud SaaS version of LangGraph Platform is only available for **Plus** and **Enterprise** plans.
The [Cloud SaaS](./langgraph_cloud.md) version of LangGraph Platform is hosted as part of [LangSmith](https://smith.langchain.com/).
The Cloud SaaS version of LangGraph Platform provides a simple way to deploy and manage your LangGraph applications.
This deployment option provides access to the LangGraph Platform UI (within LangSmith) and an integration with GitHub, allowing you to deploy code from any of your repositories on GitHub.
Connect your GitHub repositories to the platform and deploy your LangGraph Servers from the [Control Plane UI](./langgraph_control_plane.md#control-plane-ui). The build process (i.e. CI/CD) is managed internally by the platform.
For more information, please see:
* [Cloud SaaS Conceptual Guide](./langgraph_cloud.md)
* [How to deploy to Cloud SaaS](../cloud/deployment/cloud.md)
## Self-Hosted Data Plane
## Bring Your Own Cloud
The [Self-Hosted Data Plane](./langgraph_self_hosted_data_plane.md) deployment option is a "hybrid" model for deployemnt where we manage the [control plane](./langgraph_control_plane.md) in our cloud and you manage the [data plane](./langgraph_data_plane.md) in your cloud. This option provides a way to securely manage your data plane infrastructure, while offloading control plane management to us.
!!! important
Build a Docker image using the [LangGraph CLI](./langgraph_cli.md) and deploy your LangGraph Server from the [Control Plane UI](./langgraph_control_plane.md#control-plane-ui).
The Bring Your Own Cloud version of LangGraph Platform is only available for **Enterprise** plans.
Supported Compute Platforms: [Kubernetes](https://kubernetes.io/), [Amazon ECS](https://aws.amazon.com/ecs/) (coming soon!)
For more information, please see:
This combines the best of both worlds for Cloud and Self-Hosted. Create your deployments through the LangGraph Platform UI (within LangSmith) and we manage the infrastructure so you don't have to. The infrastructure all runs within your cloud. This is currently only available on AWS.
* [Self-Hosted Data Plane Conceptual Guide](./langgraph_self_hosted_data_plane.md)
* [How to deploy the Self-Hosted Data Plane](../cloud/deployment/self_hosted_data_plane.md)
For more information please see:
## Self-Hosted Control Plane
* [Bring Your Own Cloud Conceptual Guide](./bring_your_own_cloud.md)
The [Self-Hosted Control Plane](./langgraph_self_hosted_control_plane.md) deployment option is a fully self-hosted model for deployment where you manage the [control plane](./langgraph_control_plane.md) and [data plane](./langgraph_data_plane.md) in your cloud. This option give you full control and responsibility of the control plane and data plane infrastructure.
Build a Docker image using the [LangGraph CLI](./langgraph_cli.md) and deploy your LangGraph Server from the [Control Plane UI](./langgraph_control_plane.md#control-plane-ui).
Supported Compute Platforms: [Kubernetes](https://kubernetes.io/)
For more information, please see:
* [Self-Hosted Control Plane Conceptual Guide](./langgraph_self_hosted_control_plane.md)
* [How to deploy the Self-Hosted Control Plane](../cloud/deployment/self_hosted_control_plane.md)
## Standalone Container
The [Standalone Container](./langgraph_standalone_container.md) deployment option is the least restrictive model for deployment. Deploy standalone instances of a LangGraph Server in your cloud.
Build a Docker image using the [LangGraph CLI](./langgraph_cli.md) and deploy your LangGraph Server using the container deployment tooling of your choice. Images can be deployed to any compute platform.
For more information, please see:
* [Sandalone Container Conceptual Guide](./langgraph_standalone_container.md)
* [How to deploy a Standalone Container](../cloud/deployment/standalone_container.md)
## Related
+1 -1
View File
@@ -7,7 +7,7 @@ LangGraph's built-in [persistence](./persistence.md) layer provides durable exec
!!! tip
If you are using LangGraph with a checkpointer, you already have durable execution enabled. You can pause and resume workflows at any point, even after interruptions or failures.
To make the most of durable execution, ensure that your workflow is designed to be [deterministic](#determinism-and-consistent-replay) and [idempotent](#idempotency) and wrap any side effects or non-deterministic operations inside [tasks](./functional_api.md#task). You can use [tasks](./functional_api.md#task) from both the [StateGraph (Graph API)](./low_level.md) and the [Functional API](./functional_api.md).
To make the most of durable execution, ensure that your workflow is designed to be [deterministic](#determinism-and-consistent-replay) and [idempotent](#determinism-and-consistent-replay) and wrap any side effects or non-deterministic operations inside [tasks](./functional_api.md#task). You can use [tasks](./functional_api.md#task) from both the [StateGraph (Graph API)](./low_level.md) and the [Functional API](./functional_api.md).
## Requirements
+7 -1
View File
@@ -36,7 +36,7 @@ LangGraph is a stateful, orchestration framework that brings added control to ag
| Concurrency Control | Simple threading | Supports double-texting |
| Scheduling | None | Cron scheduling |
| Monitoring | None | Integrated with LangSmith for observability |
| IDE integration | LangGraph Studio for Desktop | LangGraph Studio for Desktop & Cloud |
| IDE integration | LangGraph Studio | LangGraph Studio |
## What are my deployment options for LangGraph Platform?
@@ -62,3 +62,9 @@ Yes! You can use LangGraph with any LLMs. The main reason we use LLMs that suppo
## Does LangGraph work with OSS LLMs?
Yes! LangGraph is totally ambivalent to what LLMs are used under the hood. The main reason we use closed LLMs in most of the tutorials is that they seamlessly support tool calling, while OSS LLMs often don't. But tool calling is not necessary (see [this section](#does-langgraph-work-with-llms-that-dont-support-tool-calling)) so you can totally use LangGraph with OSS LLMs.
## Can I use LangGraph Studio without logging to LangSmith
Yes! You can use the [development version of LangGraph Server](../tutorials/langgraph-platform/local-server.md) to run the backend locally.
This will connect to the studio frontend hosted as part of LangSmith.
If you set an environment variable of `LANGSMITH_TRACING=false` then no traces will be sent to LangSmith.
+2
View File
@@ -23,9 +23,11 @@ This provides a minimal abstraction for building workflows with state management
Below we demonstrate a simple application that writes an essay and [interrupts](human_in_the_loop.md) to request human review.
```python
from langgraph.checkpoint.memory import MemorySaver
from langgraph.func import entrypoint, task
from langgraph.types import interrupt
@task
def write_essay(topic: str) -> str:
"""Write an essay about the given topic."""
+1 -1
View File
@@ -2,7 +2,7 @@
## LLM applications
LLMs make it possible to embed intelligence into a new class of applications. There are many patterns for building applications that use LLMs. [Workflows](https://www.anthropic.com/research/building-effective-agents) have scaffolding of predefined code paths around LLM calls. LLMs can direct the control flow through these predefined code paths, which some consider to be an "[agentic system](https://www.anthropic.com/research/building-effective-agents)". In other cases, it's possible to remove this scaffolding, creating autonomous agents that can [plan](https://huyenchip.com/2025/01/07/agents.html), take actions via [tool calls](https://python.langchain.com/docs/concepts/tool_calling/), and directly respond [to the feedback from their own actions](https://research.google/blog/react-synergizing-reasoning-and-acting-in-language-models/) with further actions.
LLMs make it possible to embed intelligence into a new class of applications. There are many patterns for building applications that use LLMs. Workflows have scaffolding of predefined code paths around LLM calls. LLMs can direct the control flow through these predefined code paths, which some consider to be an "agentic system". In other cases, it's possible to remove this scaffolding, creating autonomous agents that can [plan](https://huyenchip.com/2025/01/07/agents.html), take actions via [tool calls](https://python.langchain.com/docs/concepts/tool_calling/), and directly respond [to the feedback from their own actions](https://research.google/blog/react-synergizing-reasoning-and-acting-in-language-models/) with further actions.
![Agent Workflow](img/agent_workflow.png)
+2 -6
View File
@@ -647,19 +647,15 @@ def node_in_parent_graph(state: State):
This will print out
```pycon
--- First invocation ---
In parent node: {'foo': 'bar'}
Entered `parent_node` a total of 1 times
Entered `node_in_subgraph` a total of 1 times
Entered human_node in sub-graph a total of 1 times
{'__interrupt__': (Interrupt(value='what is your name?', resumable=True, ns=['parent_node:0b23d72f-aaba-0329-1a59-ca4f3c8bad3b', 'human_node:25df717c-cb80-57b0-7410-44e20aac8f3c'], when='during'),)}
{'__interrupt__': (Interrupt(value='what is your name?', resumable=True, ns=['parent_node:4c3a0248-21f0-1287-eacf-3002bc304db4', 'human_node:2fe86d52-6f70-2a3f-6b2f-b1eededd6348'], when='during'),)}
--- Resuming ---
In parent node: {'foo': 'bar'}
Entered `parent_node` a total of 2 times
Entered human_node in sub-graph a total of 2 times
Got an answer of 35
{'parent_node': None}
{'parent_node': {'state_counter': 1}}
```
Binary file not shown.

After

Width:  |  Height:  |  Size: 437 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 668 KiB

+10 -6
View File
@@ -7,7 +7,7 @@ description: Conceptual Guide for LangGraph
This guide provides explanations of the key concepts behind the LangGraph framework and AI applications more broadly.
We recommend that you go through at least the [Quick Start](../tutorials/introduction.ipynb) before diving into the conceptual guide. This will provide practical context that will make it easier to understand the concepts discussed here.
We recommend that you go through at least the [Quickstart](../tutorials/introduction.ipynb) before diving into the conceptual guide. This will provide practical context that will make it easier to understand the concepts discussed here.
The conceptual guide does not cover step-by-step instructions or specific implementation examples — those are found in the [Tutorials](../tutorials/index.md) and [How-to guides](../how-tos/index.md). For detailed reference material, please see the [API reference](../reference/index.md).
@@ -30,6 +30,7 @@ The conceptual guide does not cover step-by-step instructions or specific implem
- [Streaming](streaming.md): Streaming is crucial for enhancing the responsiveness of applications built on LLMs. By displaying output progressively, even before a complete response is ready, streaming significantly improves user experience (UX), particularly when dealing with the latency of LLMs.
- [Functional API](functional_api.md): `@entrypoint` and `@task` decorators that allow you to add LangGraph functionality to an existing codebase.
- [Durable Execution](durable_execution.md): LangGraph's built-in [persistence](./persistence.md) layer provides durable execution for workflows, ensuring that the state of each execution step is saved to a durable store.
- [Pregel](pregel.md): Pregel is LangGraph's runtime, which is responsible for managing the execution of LangGraph applications.
- [FAQ](faq.md): Frequently asked questions about LangGraph.
## LangGraph Platform
@@ -47,7 +48,8 @@ The LangGraph Platform offers a few different deployment options described in th
- [Why LangGraph Platform?](./langgraph_platform.md): The LangGraph platform is an opinionated way to deploy and manage LangGraph applications. This guide provides an overview of the key features and concepts behind LangGraph Platform.
- [Platform Architecture](./platform_architecture.md): A high-level overview of the architecture of the LangGraph Platform.
- [Deployment Options](./deployment_options.md): LangGraph Platform offers four deployment options: [Self-Hosted Lite](./self_hosted.md#self-hosted-lite), [Self-Hosted Enterprise](./self_hosted.md#self-hosted-enterprise), [bring your own cloud (BYOC)](./bring_your_own_cloud.md), and [Cloud SaaS](./langgraph_cloud.md). This guide explains the differences between these options, and which Plans they are available on.
- [Scalability and Resilience](./scalability_and_resilience.md): LangGraph Platform is designed to be scalable and resilient. This document explains how the platform achieves this.
- [Deployment Options](./deployment_options.md): LangGraph Platform offers four deployment options: [Cloud SaaS](./langgraph_cloud.md), [Self-Hosted Data Plane](./langgraph_self_hosted_data_plane.md), [Self-Hosted Control Plane](./langgraph_self_hosted_control_plane.md), and [Standalone Container](./langgraph_standalone_container.md). This guide explains the differences between these options, and which Plans they are available on.
- [Plans](./plans.md): LangGraph Platforms offer three different plans: Developer, Plus, Enterprise. This guide explains the differences between these options, what deployment options are available for each, and how to sign up for each one.
- [Template Applications](./template_applications.md): Reference applications designed to help you get started quickly when building with LangGraph.
@@ -60,6 +62,8 @@ The LangGraph Platform comprises several components that work together to suppor
- [LangGraph CLI](./langgraph_cli.md): LangGraph CLI is a command-line interface that helps to interact with a local LangGraph
- [Python/JS SDK](./sdk.md): The Python/JS SDK provides a programmatic way to interact with deployed LangGraph Applications.
- [Remote Graph](../how-tos/use-remote-graph.md): A RemoteGraph allows you to interact with any deployed LangGraph application as though it were running locally.
- [LangGraph Control Plane](./langgraph_control_plane.md): The LangGraph Control Plane refers to the Control Plane UI where users create and update LangGraph Servers and the Control Plane APIs that support the UI experience.
- [LangGraph Data Plane](./langgraph_data_plane.md): The LangGraph Data Plane refers to LangGraph Servers, the corresponding infrastructure for each server, and the "listener" application that continuously polls for updates from the LangGraph Control Plane.
### LangGraph Server
@@ -72,7 +76,7 @@ The LangGraph Platform comprises several components that work together to suppor
### Deployment Options
- [Self-Hosted Lite](./self_hosted.md): A free (up to 1 million nodes executed per year), limited version of LangGraph Platform that you can run locally or in a self-hosted manner
- [Cloud SaaS](./langgraph_cloud.md): Hosted as part of LangSmith.
- [Bring Your Own Cloud](./bring_your_own_cloud.md): We manage the infrastructure, so you don't have to, but the infrastructure all runs within your cloud.
- [Self-Hosted Enterprise](./self_hosted.md): Completely managed by you.
- [Cloud SaaS](../concepts/langgraph_cloud.md): Connect to your GitHub repositories and deploy LangGraph Servers to LangChain's cloud. We manage everything.
- [Self-Hosted Data Plane](../concepts/langgraph_self_hosted_data_plane.md): Create deployments from the [Control Plane UI](../concepts/langgraph_control_plane.md#control-plane-ui) and deploy LangGraph Servers to your cloud. We manage the [control plane](../concepts/langgraph_control_plane.md), you manage the deployments.
- [Self-Hosted Control Plane](../concepts/langgraph_self_hosted_control_plane.md#control-plane-ui): Create deployments from a self-hosted [Control Plane UI](../concepts/langgraph_control_plane.md) and deploy LangGraph Servers to your cloud. You manage everything.
- [Standalone Container](../concepts/langgraph_standalone_container.md): Deploy LangGraph Server Docker images however you like.
+1 -1
View File
@@ -4,7 +4,7 @@
- [LangGraph Platform](./langgraph_platform.md)
- [LangGraph Server](./langgraph_server.md)
The LangGraph CLI is a multi-platform command-line tool for building and running the [LangGraph API server](./langgraph_server.md) locally. This offers an alternative to the [LangGraph Studio desktop app](./langgraph_studio.md) for developing and testing agents across all major operating systems (Linux, Windows, MacOS). The resulting server includes all API endpoints for your graph's runs, threads, assistants, etc. as well as the other services required to run your agent, including a managed database for checkpointing and storage.
The LangGraph CLI is a multi-platform command-line tool for building and running the [LangGraph API server](./langgraph_server.md) locally. The resulting server includes all API endpoints for your graph's runs, threads, assistants, etc. as well as the other services required to run your agent, including a managed database for checkpointing and storage.
## Installation
+8 -76
View File
@@ -1,85 +1,17 @@
# Cloud SaaS
!!! info "Prerequisites"
- [LangGraph Platform](./langgraph_platform.md)
- [LangGraph Server](./langgraph_server.md)
To deploy a [LangGraph Server](../concepts/langgraph_server.md), follow the how-to guide for [how to deploy to Cloud SaaS](../cloud/deployment/cloud.md).
## Overview
LangGraph's Cloud SaaS is a managed service for deploying LangGraph Servers, regardless of its definition or dependencies. The service offers managed implementations of checkpointers and stores, allowing you to focus on building the right cognitive architecture for your use case. By handling scalable & secure infrastructure, LangGraph Cloud SaaS offers the fastest path to getting your LangGraph Server deployed to production.
The Cloud SaaS deployment option is a fully managed model for deployment where we manage the [control plane](./langgraph_control_plane.md) and [data plane](./langgraph_data_plane.md) in our cloud.
## Deployment
A **deployment** is an instance of a LangGraph Server. A single deployment can have many [revisions](#revision). When a deployment is created, all the necessary infrastructure (e.g. database, containers, secrets store) are automatically provisioned. See the [architecture diagram](#architecture) below for more details.
Resource Allocation:
| **Deployment Type** | **CPU** | **Memory** | **Scaling** |
|---------------------|---------|------------|---------------------|
| Development | 1 CPU | 1 GB | Up to 1 container |
| Production | 2 CPU | 2 GB | Up to 10 containers |
See the [how-to guide](../cloud/deployment/cloud.md#create-new-deployment) for creating a new deployment.
## Revision
A revision is an iteration of a [deployment](#deployment). When a new deployment is created, an initial revision is automatically created. To deploy new code changes or update environment variable configurations for a deployment, a new revision must be created. When a revision is created, a new container image is built automatically.
See the [how-to guide](../cloud/deployment/cloud.md#create-new-revision) for creating a new revision.
## Persistence
A dedicated database is automatically created for each deployment. The database serves as the [persistence layer](../concepts/persistence.md) for the deployment.
When defining a graph to be deployed to LangGraph Cloud SaaS, a [checkpointer](../concepts/persistence.md#checkpointer-libraries) should not be configured by the user. Instead, a checkpointer is automatically configured for the graph.
There is no direct access to the database. All access to the database occurs through the LangGraph Server APIs.
## Autoscaling
`Production` type deployments automatically scale up to 10 containers. Scaling is based on the current request load for a single container. Specifically, the autoscaling implementation scales the deployment so that each container is processing about 10 concurrent requests. For example...
- If the deployment is processing 20 concurrent requests, the deployment will scale up from 1 container to 2 containers (20 requests / 2 containers = 10 requests per container).
- If a deployment of 2 containers is processing 10 requests, the deployment will scale down from 2 containers to 1 container (10 requests / 1 container = 10 requests per container).
10 concurrent requests per container is the target threshold. However, 10 concurrent requests per container is not a hard limit. The number of concurrent requests can exceed 10 if there is a sudden burst of requests.
Scale down actions are delayed for 30 minutes before any action is taken. In other words, if the autoscaling implementation decides to scale down a deployment, it will first wait for 30 minutes before scaling down. After 30 minutes, the concurrency metric is recomputed and the deployment will scale down if the concurrency metric has met the target threshold. Otherwise, the deployment remains scaled up. This "cool down" period ensures that deployments do not scale up and down too frequently.
In the future, the autoscaling implementation may evolve to accommodate other metrics such as background run queue size.
## Asynchronous Deployment
Infrastructure for [deployments](#deployment) and [revisions](#revision) are provisioned and deployed asynchronously. They are not deployed immediately after submission. Currently, deployment can take up to several minutes.
- When a new deployment is created, a new database is created for the deployment. Database creation is a one-time step. This step contributes to a longer deployment time for the initial revision of the deployment.
- When a subsequent revision is created for a deployment, there is no database creation step. The deployment time for a subsequent revision is significantly faster compared to the deployment time of the initial revision.
- The deployment process for each revision contains a build step, which can take up to a few minutes.
## LangSmith Integration
A [LangSmith](https://docs.smith.langchain.com/) tracing project is automatically created for each deployemnt. The tracing project has the same name as the deployment. When creating a deployment, the `LANGCHAIN_TRACING_V2` and `LANGCHAIN_API_KEY` environment variables do not need to be specified; they are set internally, automatically. Traces are created for each run and are emitted to the tracing project automatically.
When a deployment is deleted, the traces and the tracing project are not deleted.
## Automatic Deletion
Deployments are automatically deleted after 28 consecutive days of non-use (it is in an unused state). A deployment is in an unused state if there are no traces emitted to LangSmith from the deployment after 28 consecutive days. On any given day, if a deployment emits a trace to LangSmith, the counter for consecutive days of non-use is reset.
- An email notification is sent after 7 consecutive days of non-use.
- A deployment is deleted after 28 consecutive days of non-use.
!!! danger "Data Cannot Be Recovered"
After a deployment is deleted, the data (i.e. [persistence](#persistence)) from the deployment cannot be recovered.
| | [Control Plane](../concepts/langgraph_control_plane.md) | [Data Plane](../concepts/langgraph_data_plane.md) |
|-------------------|-------------------|------------|
| **What is it?** | <ul><li>Control Plane UI for creating deployments and revisions</li><li>Control Plane APIs for creating deployments and revisions</li></ul> | <ul><li>Data plane "listener" for reconciling deployments with control plane state</li><li>LangGraph Servers</li><li>Postgres, Redis, etc</li></ul> |
| **Where is it hosted?** | LangChain's cloud | LangChain's cloud |
| **Who provisions and manages it?** | LangChain | LangChain |
## Architecture
!!! warning "Subject to Change"
The Cloud SaaS deployment architecture may change in the future.
A high-level diagram of a Cloud SaaS deployment.
![diagram](img/langgraph_cloud_architecture.png)
## Related
- [Deployment Options](./deployment_options.md)
![Cloud SaaS](./img/self_hosted_control_plane_architecture.png)
@@ -0,0 +1,98 @@
# LangGraph Control Plane
The term "control plane" is used broadly to refer to the Control Plane UI where users create and update [LangGraph Servers](./langgraph_server.md) (deployments) and the Control Plane APIs that support the UI experience.
When a user makes an update through the Control Plane UI, the update is stored in the control plane state. The [LangGraph Data Plane](./langgraph_data_plane.md) "listener" application polls for these updates by calling the Control Plane APIs.
## Control Plane UI
From the Control Plane UI, you can:
- View a list of outstanding deployments.
- View details of an individual deployment.
- Create a new deployment.
- Update a deployment.
- Update environment variables for a deployment.
- View build and server logs of a deployment.
- Delete a deployment.
The Control Plane UI is embedded in [LangSmith](https://docs.smith.langchain.com/langgraph_cloud).
## Control Plane API
This section describes data model of the LangGraph Control Plane API. Control Plane API is used to create, update, and delete deployments. However, they are not publicly accessible.
### Deployment
A deployment is an instance of a LangGraph Server. A single deployment can have many revisions.
### Revision
A revision is an iteration of a deployment. When a new deployment is created, an initial revision is automatically created. To deploy code changes or update environment variables for a deployment, a new revision must be created.
### Environment Variable
Environment variables are set for a deployment. All environment variables are stored as secrets (i.e. saved in a secrets store).
## Control Plane Features
This section describes various features of the control plane.
### Deployment Types
For simplicity, the control plane offers two deployment types with different resource allocations: `Development` and `Production`.
| **Deployment Type** | **CPU** | **Memory** | **Scaling** |
|---------------------|---------|------------|---------------------|
| Development | 1 CPU | 1 GB | Up to 1 container |
| Production | 2 CPU | 2 GB | Up to 10 containers |
CPU and memory resources are per container.
!!! info "For [Cloud SaaS](../concepts/langgraph_cloud.md)"
For `Production` type deployments, resources can be manually increased on a case-by-case basis depending on use case and capacity constraints. Contact support@langchain.dev to request an increase in resources.
!!! info "For [Self-Hosted Data Plane](../concepts/langgraph_self_hosted_data_plane.md) and [Self-Hosted Control Plane](../concepts/langgraph_self_hosted_control_plane.md)"
Resources for [Self-Hosted Data Plane](../concepts/langgraph_data_plane.md) and [Self-Hosted Control Plane](../concepts/langgraph_control_plane.md) deployments can be fully customized.
### Database Provisioning
The control plane and [LangGraph Data Plane](./langgraph_data_plane.md) "listener" application coordinate to automatically create a Postgres database for each deployment. The database serves as the [persistence layer](../concepts/persistence.md) for the deployment.
When implementing a LangGraph application, a [checkpointer](../concepts/persistence.md#checkpointer-libraries) does not need to be configured by the developer. Instead, a checkpointer is automatically configured for the graph. Any checkpointer configured for a graph will be replaced by the one that is automatically configured.
There is no direct access to the database. All access to the database occurs through the [LangGraph Server](../concepts/langgraph_server.md).
The database is never deleted until the deployment itself is deleted. See [Automatic Deletion](#automatic-deletion) for additional details.
!!! info "For [Self-Hosted Data Plane](../concepts/langgraph_self_hosted_data_plane.md) and [Self-Hosted Control Plane](../concepts/langgraph_self_hosted_control_plane.md)"
A custom Postgres instance can be configured for [Self-Hosted Data Plane](../concepts/langgraph_data_plane.md) and [Self-Hosted Control Plane](../concepts/langgraph_control_plane.md) deployments.
### Asynchronous Deployment
Infrastructure for deployments and revisions are provisioned and deployed asynchronously. They are not deployed immediately after submission. Currently, deployment can take up to several minutes.
- When a new deployment is created, a new database is created for the deployment. Database creation is a one-time step. This step contributes to a longer deployment time for the initial revision of the deployment.
- When a subsequent revision is created for a deployment, there is no database creation step. The deployment time for a subsequent revision is significantly faster compared to the deployment time of the initial revision.
- The deployment process for each revision contains a build step, which can take up to a few minutes.
The control plane and [LangGraph Data Plane](./langgraph_data_plane.md) "listener" application coordinate to achieve asynchronous deployments.
### Automatic Deletion
!!! info "Only for [Cloud SaaS](../concepts/langgraph_cloud.md)"
Automatic deletion of deployments is only available for [Cloud SaaS](../concepts/langgraph_cloud.md).
The control plane automatically deletes deployments after 28 consecutive days of non-use (it is in an unused state). A deployment is in an unused state if there are no traces emitted to LangSmith from the deployment after 28 consecutive days. On any given day, if a deployment emits a trace to LangSmith, the counter for consecutive days of non-use is reset.
- An email notification is sent after 7 consecutive days of non-use.
- A deployment is deleted after 28 consecutive days of non-use.
!!! danger "Data Cannot Be Recovered"
After a deployment is deleted, the data (e.g. Postgres) from the deployment cannot be recovered.
### LangSmith Integration
A [LangSmith](https://docs.smith.langchain.com/) tracing project is automatically created for each deployment. The tracing project has the same name as the deployment. When creating a deployment, the `LANGCHAIN_TRACING` and `LANGSMITH_API_KEY`/`LANGCHAIN_API_KEY` environment variables do not need to be specified; they are set automatically by the control plane.
When a deployment is deleted, the traces and the tracing project are not deleted.
@@ -0,0 +1,74 @@
# LangGraph Data Plane
The term "data plane" is used broadly to refer to [LangGraph Servers](./langgraph_server.md) (deployments), the corresponding infrastructure for each server, and the "listener" application that continuously polls for updates from the [LangGraph Control Plane](./langgraph_control_plane.md).
## Server Infrastructure
In addition to the [LangGraph Server](./langgraph_server.md) itself, the following infrastructure for each server are also included in the broad definition of "data plane":
- [Postgres](../concepts/platform_architecture.md#how-we-use-postgres)
- [Redis](../concepts/platform_architecture.md#how-we-use-redis)
- Secrets store
- Autoscalers
See [LangGraph Platform Architecture](../concepts/platform_architecture.md) for more details.
## "Listener" Application
The data plane "listener" application periodically calls [Control Plane APIs](../concepts/langgraph_control_plane.md#control-plane-api) to:
- Determine if new deployments should be created.
- Determine if existing deployments should be updated (i.e. new revisions).
- Determine if existing deployments should be deleted.
In other words, the data plane "listener" reads the latest state of the control plane (desired state) and takes action to reconcile outstanding deployments (current state) to match the latest state.
## Data Plane Features
This section describes various features of the data plane.
### Lite vs Enterprise
There are two versions of the LangGraph Server: `Lite` and `Enterprise`.
The `Lite` version is a limited version of the LangGraph Server that you can run locally or in a self-hosted manner (up to 1 million nodes executed per year). `Lite` is only available for the [Standalone Container](../concepts/langgraph_standalone_container.md) deployment option.
The `Enterprise` version is the full version of the LangGraph Server. To use the `Enterprise` version, you must acquire a license key that you will need to specify when running the Docker image. To acquire a license key, please email sales@langchain.dev. `Enterprise` is available for [Cloud SaaS](../concepts/langgraph_cloud.md), [Self-Hosted Data Plane](../concepts/langgraph_self_hosted_data_plane.md), and [Self-Hosted Control Plane](../concepts/langgraph_self_hosted_control_plane.md) deployment options.
Feature Differences:
| | Lite | Enterprise |
|-------|------------|------------|
| [Cron Jobs](../concepts/langgraph_server.md#cron-jobs) |❌|✅|
| [Custom Authentication](../concepts/auth.md) |❌|✅|
### Autoscaling
[`Production` type](../concepts/langgraph_control_plane.md#deployment-types) deployments automatically scale up to 10 containers. Scaling is based on the current request load for a single container. Specifically, the autoscaling implementation scales the deployment so that each container is processing about 10 concurrent requests. For example...
- If the deployment is processing 20 concurrent requests, the deployment will scale up from 1 container to 2 containers (20 requests / 2 containers = 10 requests per container).
- If a deployment of 2 containers is processing 10 requests, the deployment will scale down from 2 containers to 1 container (10 requests / 1 container = 10 requests per container).
10 concurrent requests per container is the target threshold. However, 10 concurrent requests per container is not a hard limit. The number of concurrent requests can exceed 10 if there is a sudden burst of requests.
Scale down actions are delayed for 30 minutes before any action is taken. In other words, if the autoscaling implementation decides to scale down a deployment, it will first wait for 30 minutes before scaling down. After 30 minutes, the concurrency metric is recomputed and the deployment will scale down if the concurrency metric has met the target threshold. Otherwise, the deployment remains scaled up. This "cool down" period ensures that deployments do not scale up and down too frequently.
In the future, the autoscaling implementation may evolve to accommodate other metrics such as background run queue size.
### Static IP Addresses
!!! info "Only for Cloud SaaS"
Static IP addresses are only available for [Cloud SaaS](../concepts/langgraph_cloud.md).
All traffic from deployments created after January 6th 2025 will come through a NAT gateway. This NAT gateway will have several static IP addresses depending on the data region. Refer to the table below for the list of static IP addresses:
| US | EU |
|----------------|----------------|
| 35.197.29.146 | 34.13.192.67 |
| 34.145.102.123 | 34.147.105.64 |
| 34.169.45.153 | 34.90.22.166 |
| 34.82.222.17 | 34.147.36.213 |
| 35.227.171.135 | 34.32.137.113 |
| 34.169.88.30 | 34.91.238.184 |
| 34.19.93.202 | 35.204.101.241 |
| 34.19.34.50 | 35.204.48.32 |
+7
View File
@@ -1,3 +1,8 @@
---
search:
boost: 2
---
# LangGraph Platform
## Overview
@@ -11,6 +16,8 @@ The LangGraph Platform consists of several components that work together to supp
- [LangGraph CLI](./langgraph_cli.md): LangGraph CLI is a command-line interface that helps to interact with a local LangGraph
- [Python/JS SDK](./sdk.md): The Python/JS SDK provides a programmatic way to interact with deployed LangGraph Applications.
- [Remote Graph](../how-tos/use-remote-graph.md): A RemoteGraph allows you to interact with any deployed LangGraph application as though it were running locally.
- [LangGraph Control Plane](./langgraph_control_plane.md): The LangGraph Control Plane refers to the Control Plane UI where users create and update LangGraph Servers and the Control Plane APIs that support the UI experience.
- [LangGraph Data Plane](./langgraph_data_plane.md): The LangGraph Data Plane refers to LangGraph Servers, the corresponding infrastructure for each server, and the "listener" application that continuously polls for updates from the LangGraph Control Plane.
![](img/lg_platform.png)
@@ -0,0 +1,23 @@
# Self-Hosted Control Plane
To deploy a [LangGraph Server](../concepts/langgraph_server.md), follow the how-to guide for [how to deploy the Self-Hosted Control Plane](../cloud/deployment/self_hosted_control_plane.md).
## Overview
The Self-Hosted Control Plane deployment option is a fully self-hosted model for deployment where you manage the [control plane](./langgraph_control_plane.md) and [data plane](./langgraph_data_plane.md) in your cloud (this option implies that the data plane is self-hosted).
| | [Control Plane](../concepts/langgraph_control_plane.md) | [Data Plane](../concepts/langgraph_data_plane.md) |
|-------------------|-------------------|------------|
| **What is it?** | <ul><li>Control Plane UI for creating deployments and revisions</li><li>Control Plane APIs for creating deployments and revisions</li></ul> | <ul><li>Data plane "listener" for reconciling deployments with control plane state</li><li>LangGraph Servers</li><li>Postgres, Redis, etc</li></ul> |
| **Where is it hosted?** | Your cloud | Your cloud |
| **Who provisions and manages it?** | You | You |
## Architecture
![Self-Hosted Control Plane Architecture](./img/self_hosted_control_plane_architecture.png)
## Compute Platforms
### Kubernetes
The Self-Hosted Control Plane deployment option supports deploying control plane and data plane infrastructure to any Kubernetes cluster.
@@ -0,0 +1,27 @@
# Self-Hosted Data Plane
To deploy a [LangGraph Server](../concepts/langgraph_server.md), follow the how-to guide for [how to deploy the Self-Hosted Data Plane](../cloud/deployment/self_hosted_data_plane.md).
## Overview
LangGraph Platform's Self-Hosted Data Plane deployment option is a "hybrid" model for deployemnt where we manage the [control plane](./langgraph_control_plane.md) in our cloud and you manage the [data plane](./langgraph_data_plane.md) in your cloud.
| | [Control Plane](../concepts/langgraph_control_plane.md) | [Data Plane](../concepts/langgraph_data_plane.md) |
|-------------------|-------------------|------------|
| **What is it?** | <ul><li>Control Plane UI for creating deployments and revisions</li><li>Control Plane APIs for creating deployments and revisions</li></ul> | <ul><li>Data plane "listener" for reconciling deployments with control plane state</li><li>LangGraph Servers</li><li>Postgres, Redis, etc</li></ul> |
| **Where is it hosted?** | LangChain's cloud | Your cloud |
| **Who provisions and manages it?** | LangChain | You |
## Architecture
![Self-Hosted Data Plane Architecture](./img/self_hosted_data_plane_architecture.png)
## Compute Platforms
### Kubernetes
The Self-Hosted Data Plane deployment option supports deploying data plane infrastructure to any Kubernetes cluster.
### Amazon ECS
Coming soon...
@@ -0,0 +1,27 @@
# Standalone Container
To deploy a [LangGraph Server](../concepts/langgraph_server.md), follow the how-to guide for [how to deploy a Standalone Container](../cloud/deployment/standalone_container.md).
## Overview
The Standalone Container deployment option is the least restrictive model for deployment. There is no [control plane](./langgraph_control_plane.md). [Data plane](./langgraph_data_plane.md) infrastructure is managed by you.
| | [Control Plane](../concepts/langgraph_control_plane.md) | [Data Plane](../concepts/langgraph_data_plane.md) |
|-------------------|-------------------|------------|
| **What is it?** | n/a | <ul><li>LangGraph Servers</li><li>Postgres, Redis, etc</li></ul> |
| **Where is it hosted?** | n/a | Your cloud |
| **Who provisions and manages it?** | n/a | You |
## Architecture
![Standalone Container](./img/langgraph_platform_deployment_architecture.png)
## Compute Platforms
### Kubernetes
The Standalone Container deployment option supports deploying data plane infrastructure to a Kubernetes cluster.
### Docker
The Standalone Container deployment option supports deploying data plane infrastructure to any Docker-supported compute platform.
+71 -64
View File
@@ -7,7 +7,7 @@
LangGraph Studio offers a new way to develop LLM applications by providing a specialized agent IDE that enables visualization, interaction, and debugging of complex agentic applications.
With visual graphs and the ability to edit state, you can better understand agent workflows and iterate faster. LangGraph Studio integrates with LangSmith allowing you to collaborate with teammates to debug failure modes.
With visual graphs and the ability to edit state, you can better understand agent workflows and iterate faster. LangGraph Studio integrates with LangSmith allowing you to collaborate with teammates to debug failure modes.
![](img/lg_studio.png)
@@ -15,7 +15,7 @@ With visual graphs and the ability to edit state, you can better understand agen
The key features of LangGraph Studio are:
- Visualizes your graph
- Visualize your graphs
- Test your graph by running it from the UI
- Debug your agent by [modifying its state and rerunning](human_in_the_loop.md)
- Create and manage [assistants](assistants.md)
@@ -23,86 +23,54 @@ The key features of LangGraph Studio are:
- View and manage [long term memory](memory.md)
- Add node input/outputs to [LangSmith](https://smith.langchain.com/) datasets for testing
## Types
## Getting started
### Development server with web UI
There are two ways to connect your LangGraph app with the studio:
You can [run a local in-memory development server](../tutorials/langgraph-platform/local-server.md) that can be used to connect a local LangGraph app with a web version of the studio.
For example, if you start the local server with `langgraph dev` (running at `http://127.0.0.1:2024` by default), you can connect to the studio by navigating to:
### Deployed Application
If you have deployed your LangGraph application on LangGraph Platform, you can access the studio as part of that deployment. To do so, navigate to the deployment in LangGraph Platform within the LangSmith UI and click the "LangGraph Studio" button.
### Local Development Server
If you have a LangGraph application that is [running locally in-memory](../tutorials/langgraph-platform/local-server.md), you can connect it to LangGraph Studio in the browser within LangSmith.
By default, starting the local server with `langgraph dev` will run the server at `http://127.0.0.1:2024` and automatically open Studio in your browser. However, you can also manually connect to Studio by either:
1. In LangGraph Platform, clicking the "LangGraph Studio" button and entering the server URL in the dialog that appears.
or
2. Navigating to the URL in your browser:
```
https://smith.langchain.com/studio/?baseUrl=http://127.0.0.1:2024
```
See [instructions here](../cloud/reference/cli.md#dev) for more information.
## Related
The web UI version of the studio will connect to your locally running server — your agent is still running locally and never leaves your device.
For more information please see the following:
### Cloud studio
- [LangGraph Studio how-to guides](../how-tos/index.md#langgraph-studio)
- [LangGraph CLI Documentation](../cloud/reference/cli.md)
If you have deployed your LangGraph application on LangGraph Platform (Cloud), you can access the studio as part of that
### Desktop app
LangGraph Studio is available as a [desktop app](https://studio.langchain.com/) for MacOS users.
While in Beta, LangGraph Studio is available for free to all [LangSmith](https://smith.langchain.com/) users on any plan tier.
## Studio FAQs
## LangGraph Studio FAQs
### Why is my project failing to start?
There are a few reasons that your project might fail to start, here are some of the most common ones.
#### Docker issues (desktop only)
LangGraph Studio (desktop) requires Docker Desktop version 4.24 or higher. Please make sure you have a version of Docker installed that satisfies that requirement and also make sure you have the Docker Desktop app up and running before trying to use LangGraph Studio. In addition, make sure you have docker-compose updated to version 2.22.0 or higher.
#### Configuration or environment issues
Another reason your project might fail to start is because your configuration file is defined incorrectly, or you are missing required environment variables.
!!! Important "Note (desktop only)"
LangGraph Studio Desktop automatically populates `LANGCHAIN_*` environment variables for license verification and tracing, regardless of the contents of the `.env` file. All other environment variables defined in `.env` will be read as normal.
#### Incorrect data region (desktop only)
If you receive a license verification error when attempting to start the LangGraph Server, you may be logged into the incorrect LangSmith data region. Ensure that you're logged into the correct LangSmith data region and ensure that the LangSmith account has access to LangGraph platform.
1. In the top right-hand corner, click the user icon and select `Logout`.
1. At the login screen, click the `Data Region` dropdown menu and select the appropriate data region. Then click `Login to LangSmith`.
A project may fail to start if the configuration file is defined incorrectly, or if required environment variables are missing. See [here](../cloud/reference/cli.md#configuration-file) for how your configuration file should be defined.
### How does interrupt work?
When you select the `Interrupts` dropdown and select a node to interrupt the graph will pause execution before and after (unless the node goes straight to `END`) that node has run. This means that you will be able to both edit the state before the node is ran and the state after the node has ran. This is intended to allow developers more fine-grained control over the behavior of a node and make it easier to observe how the node is behaving. You will not be able to edit the state after the node has ran if the node is the final node in the graph.
### How do I reload the app? (desktop only)
For more information on interrupts and human in the loop, see [here](./human_in_the_loop.md).
If you would like to reload the app, don't use Command+R as you might normally do. Instead, close and reopen the app for a full refresh.
### How does automatic rebuilding work? (desktop only)
One of the key features of LangGraph Studio is that it automatically rebuilds your image when you change the source code. This allows for a super fast development and testing cycle which makes it easy to iterate on your graph. There are two different ways that LangGraph rebuilds your image: either by editing the image or completely rebuilding it.
#### Rebuilds from source code changes
If you modified the source code only (no configuration or dependency changes!) then the image does not require a full rebuild, and LangGraph Studio will only update the relevant parts. The UI status in the bottom left will switch from `Online` to `Stopping` temporarily while the image gets edited. The logs will be shown as this process is happening, and after the image has been edited the status will change back to `Online` and you will be able to run your graph with the modified code!
#### Rebuilds from configuration or dependency changes
If you edit your graph configuration file (`langgraph.json`) or the dependencies (either `pyproject.toml` or `requirements.txt`) then the entire image will be rebuilt. This will cause the UI to switch away from the graph view and start showing the logs of the new image building process. This can take a minute or two, and once it is done your updated image will be ready to use!
### Why is my graph taking so long to startup? (desktop only)
The LangGraph Studio interacts with a local LangGraph API server. To stay aligned with ongoing updates, the LangGraph API requires regular rebuilding. As a result, you may occasionally experience slight delays when starting up your project.
## Why are extra edges showing up in my graph?
### Why are extra edges showing up in my graph?
If you don't define your conditional edges carefully, you might notice extra edges appearing in your graph. This is because without proper definition, LangGraph Studio assumes the conditional edge could access all other nodes. In order for this to not be the case, you need to be explicit about how you define the nodes the conditional edge routes to. There are two ways you can do this:
### Solution 1: Include a path map
#### Solution 1: Include a path map
The first way to solve this is to add path maps to your conditional edges. A path map is just a dictionary or array that maps the possible outputs of your router function with the names of the nodes that each output corresponds to. The path map is passed as the third argument to the `add_conditional_edges` function like so:
@@ -120,7 +88,7 @@ The first way to solve this is to add path maps to your conditional edges. A pat
In this case, the routing function returns either True or False, which map to `node_b` and `node_c` respectively.
### Solution 2: Update the typing of the router (Python only)
#### Solution 2: Update the typing of the router (Python only)
Instead of passing a path map, you can also be explicit about the typing of your routing function by specifying the nodes it can map to using the `Literal` python definition. Here is an example of how to define a routing function in that way:
@@ -132,9 +100,48 @@ def routing_function(state: GraphState) -> Literal["node_b","node_c"]:
return "node_c"
```
### Studio Desktop FAQs
## Related
!!! warning "Deprecation Warning"
In order to support a wider range of platforms and users, we now recommend following the above instructions to connect to LangGraph Studio using the development server instead of the desktop app.
For more information please see the following:
The LangGraph Studio Desktop App is a standalone application that allows you to connect to your LangGraph application and visualize and interact with your graph. It is available for MacOS only and requires Docker to be installed.
* [LangGraph Studio how-to guides](../how-tos/index.md#langgraph-studio)
#### Why is my project failing to start?
In addition to the reasons listed above, for the desktop app there are a few more reasons that your project might fail to start:
!!! Important "Note "
LangGraph Studio Desktop automatically populates `LANGCHAIN_*` environment variables for license verification and tracing, regardless of the contents of the `.env` file. All other environment variables defined in `.env` will be read as normal.
##### Docker issues
LangGraph Studio (desktop) requires Docker Desktop version 4.24 or higher. Please make sure you have a version of Docker installed that satisfies that requirement and also make sure you have the Docker Desktop app up and running before trying to use LangGraph Studio. In addition, make sure you have docker-compose updated to version 2.22.0 or higher.
##### Incorrect data region
If you receive a license verification error when attempting to start the LangGraph Server, you may be logged into the incorrect LangSmith data region. Ensure that you're logged into the correct LangSmith data region and ensure that the LangSmith account has access to LangGraph platform.
1. In the top right-hand corner, click the user icon and select `Logout`.
1. At the login screen, click the `Data Region` dropdown menu and select the appropriate data region. Then click `Login to LangSmith`.
### How do I reload the app?
If you would like to reload the app, don't use Command+R as you might normally do. Instead, close and reopen the app for a full refresh.
### How does automatic rebuilding work?
One of the key features of LangGraph Studio is that it automatically rebuilds your image when you change the source code. This allows for a super fast development and testing cycle which makes it easy to iterate on your graph. There are two different ways that LangGraph rebuilds your image: either by editing the image or completely rebuilding it.
#### Rebuilds from source code changes
If you modified the source code only (no configuration or dependency changes!) then the image does not require a full rebuild, and LangGraph Studio will only update the relevant parts. The UI status in the bottom left will switch from `Online` to `Stopping` temporarily while the image gets edited. The logs will be shown as this process is happening, and after the image has been edited the status will change back to `Online` and you will be able to run your graph with the modified code!
#### Rebuilds from configuration or dependency changes
If you edit your graph configuration file (`langgraph.json`) or the dependencies (either `pyproject.toml` or `requirements.txt`) then the entire image will be rebuilt. This will cause the UI to switch away from the graph view and start showing the logs of the new image building process. This can take a minute or two, and once it is done your updated image will be ready to use!
### Why is my graph taking so long to startup?
The LangGraph Studio interacts with a local LangGraph API server. To stay aligned with ongoing updates, the LangGraph API requires regular rebuilding. As a result, you may occasionally experience slight delays when starting up your project.
+2 -2
View File
@@ -310,7 +310,7 @@ graph.add_conditional_edges(START, routing_function, {True: "node_b", False: "no
## `Send`
By default, `Nodes` and `Edges` are defined ahead of time and operate on the same shared state. However, there can be cases where the exact edges are not known ahead of time and/or you may want different versions of `State` to exist at the same time. A common example of this is with `map-reduce` design patterns. In this design pattern, a first node may generate a list of objects, and you may want to apply some other node to all those objects. The number of objects may be unknown ahead of time (meaning the number of edges may not be known) and the input `State` to the downstream `Node` should be different (one for each generated object).
By default, `Nodes` and `Edges` are defined ahead of time and operate on the same shared state. However, there can be cases where the exact edges are not known ahead of time and/or you may want different versions of `State` to exist at the same time. A common example of this is with [map-reduce](https://langchain-ai.github.io/langgraph/how-tos/map-reduce/) design patterns. In this design pattern, a first node may generate a list of objects, and you may want to apply some other node to all those objects. The number of objects may be unknown ahead of time (meaning the number of edges may not be known) and the input `State` to the downstream `Node` should be different (one for each generated object).
To support this design pattern, LangGraph supports returning [`Send`][langgraph.types.Send] objects from conditional edges. `Send` takes two arguments: first is the name of the node, and second is the state to pass to that node.
@@ -360,7 +360,7 @@ Use [conditional edges](#conditional-edges) to route between nodes conditionally
If you are using [subgraphs](#subgraphs), you might want to navigate from a node within a subgraph to a different subgraph (i.e. a different node in the parent graph). To do so, you can specify `graph=Command.PARENT` in `Command`:
```python
def my_node(state: State) -> Command[Literal["my_other_node"]]:
def my_node(state: State) -> Command[Literal["other_subgraph"]]:
return Command(
update={"foo": "bar"},
goto="other_subgraph", # where `other_subgraph` is a node in the parent graph
+1 -1
View File
@@ -275,7 +275,7 @@ See this how-to [video](https://www.youtube.com/watch?v=37VaU7e7t5o) for example
[Procedural memory](https://en.wikipedia.org/wiki/Procedural_memory), in both humans and AI agents, involves remembering the rules used to perform tasks. In humans, procedural memory is like the internalized knowledge of how to perform tasks, such as riding a bike via basic motor skills and balance. Episodic memory, on the other hand, involves recalling specific experiences, such as the first time you successfully rode a bike without training wheels or a memorable bike ride through a scenic route. For AI agents, procedural memory is a combination of model weights, agent code, and agent's prompt that collectively determine the agent's functionality.
In practice, it is fairly uncommon for agents to modify their model weights or rewrite their code. However, it is more common for agents to [modify their own prompts](https://docs.anthropic.com/en/docs/build-with-claude/prompt-engineering/prompt-generator).
In practice, it is fairly uncommon for agents to modify their model weights or rewrite their code. However, it is more common for agents to modify their own prompts.
One effective approach to refining an agent's instructions is through ["Reflection"](https://blog.langchain.dev/reflection-agents/) or meta-prompting. This involves prompting the agent with its current instructions (e.g., the system prompt) along with recent conversations or explicit user feedback. The agent then refines its own instructions based on this input. This method is particularly useful for tasks where instructions are challenging to specify upfront, as it allows the agent to learn and adapt from its interactions.
+7 -5
View File
@@ -50,7 +50,7 @@ def agent(state) -> Command[Literal["agent", "another_agent"]]:
In a more complex scenario where each agent node is itself a graph (i.e., a [subgraph](./low_level.md#subgraphs)), a node in one of the agent subgraphs might want to navigate to a different agent. For example, if you have two agents, `alice` and `bob` (subgraph nodes in a parent graph), and `alice` needs to navigate to `bob`, you can set `graph=Command.PARENT` in the `Command` object:
```python
def some_node_inside_alice(state)
def some_node_inside_alice(state):
return Command(
goto="bob",
update={"my_state_key": "my_state_value"},
@@ -89,7 +89,7 @@ def transfer_to_bob(state):
)
```
This is a special case of updating the graph state from tools where in addition the state update, the control flow is included as well.
This is a special case of updating the graph state from tools where, in addition to the state update, the control flow is included as well.
!!! important
@@ -112,6 +112,7 @@ In this architecture, agents are defined as graph nodes. Each agent can communic
```python
from typing import Literal
from langchain_openai import ChatOpenAI
from langgraph.types import Command
from langgraph.graph import StateGraph, MessagesState, START, END
model = ChatOpenAI()
@@ -158,6 +159,7 @@ In this architecture, we define agents as nodes and add a supervisor node (LLM)
```python
from typing import Literal
from langchain_openai import ChatOpenAI
from langgraph.types import Command
from langgraph.graph import StateGraph, MessagesState, START, END
model = ChatOpenAI()
@@ -233,7 +235,7 @@ supervisor = create_react_agent(model, tools)
### Hierarchical
As you add more agents to your system, it might become too hard for the supervisor to manage all of them. The supervisor might start making poor decisions about which agent to call next, the context might become too complex for a single supervisor to keep track of. In other words, you end up with the same problems that motivated the multi-agent architecture in the first place.
As you add more agents to your system, it might become too hard for the supervisor to manage all of them. The supervisor might start making poor decisions about which agent to call next, or the context might become too complex for a single supervisor to keep track of. In other words, you end up with the same problems that motivated the multi-agent architecture in the first place.
To address this, you can design your system _hierarchically_. For example, you can create separate, specialized teams of agents managed by individual supervisors, and a top-level supervisor to manage the teams.
@@ -337,9 +339,9 @@ builder.add_edge("agent_1", "agent_2")
## Communication between agents
The most important thing when building multi-agent systems is figuring out how the agents communicate. There are few different considerations:
The most important thing when building multi-agent systems is figuring out how the agents communicate. There are a few different considerations:
- Do agents communicate via [**via graph state or via tool calls**](#graph-state-vs-tool-calls)?
- Do agents communicate [**via graph state or via tool calls**](#graph-state-vs-tool-calls)?
- What if two agents have [**different state schemas**](#different-state-schemas)?
- How to communicate over a [**shared message list**](#shared-message-list)?
+19 -7
View File
@@ -4,6 +4,10 @@ LangGraph has a built-in persistence layer, implemented through checkpointers. W
![Checkpoints](img/persistence/checkpoints.jpg)
!!! info "LangGraph API handles checkpointing automatically"
When using the LangGraph API, you don't need to implement or configure checkpointers manually. The API handles all persistence infrastructure for you behind the scenes.
## Threads
A thread is a unique ID or [thread identifier](#threads) assigned to each checkpoint saved by a checkpointer. When invoking graph with a checkpointer, you **must** specify a `thread_id` as part of the `configurable` portion of the config:
@@ -26,13 +30,13 @@ Let's see what checkpoints are saved when a simple graph is invoked as follows:
```python
from langgraph.graph import StateGraph, START, END
from langgraph.checkpoint.memory import MemorySaver
from langgraph.checkpoint.memory import InMemorySaver
from typing import Annotated
from typing_extensions import TypedDict
from operator import add
class State(TypedDict):
foo: int
foo: str
bar: Annotated[list[str], add]
def node_a(state: State):
@@ -49,7 +53,7 @@ workflow.add_edge(START, "node_a")
workflow.add_edge("node_a", "node_b")
workflow.add_edge("node_b", END)
checkpointer = MemorySaver()
checkpointer = InMemorySaver()
graph = workflow.compile(checkpointer=checkpointer)
config = {"configurable": {"thread_id": "1"}}
@@ -223,6 +227,10 @@ But, what if we want to retain some information *across threads*? Consider the c
With checkpointers alone, we cannot share information across threads. This motivates the need for the [`Store`](../reference/store.md#langgraph.store.base.BaseStore) interface. As an illustration, we can define an `InMemoryStore` to store information about a user across threads. We simply compile our graph with a checkpointer, as before, and with our new `in_memory_store` variable.
!!! info "LangGraph API handles stores automatically"
When using the LangGraph API, you don't need to implement or configure stores manually. The API handles all storage infrastructure for you behind the scenes.
### Basic Usage
First, let's showcase this in isolation without using LangGraph.
@@ -232,7 +240,7 @@ from langgraph.store.memory import InMemoryStore
in_memory_store = InMemoryStore()
```
Memories are namespaced by a `tuple`, which in this specific example will be `(<user_id>, "memories")`. The namespace can be any length and represent anything, does not have be user specific.
Memories are namespaced by a `tuple`, which in this specific example will be `(<user_id>, "memories")`. The namespace can be any length and represent anything, does not have to be user specific.
```python
user_id = "1"
@@ -324,10 +332,10 @@ store.put(
With this all in place, we use the `in_memory_store` in LangGraph. The `in_memory_store` works hand-in-hand with the checkpointer: the checkpointer saves state to threads, as discussed above, and the `in_memory_store` allows us to store arbitrary information for access *across* threads. We compile the graph with both the checkpointer and the `in_memory_store` as follows.
```python
from langgraph.checkpoint.memory import MemorySaver
from langgraph.checkpoint.memory import InMemorySaver
# We need this because we want to enable threads (conversations)
checkpointer = MemorySaver()
checkpointer = InMemorySaver()
# ... Define the graph ...
@@ -387,6 +395,9 @@ We can access the memories and use them in our model call.
def call_model(state: MessagesState, config: RunnableConfig, *, store: BaseStore):
# Get the user id from the config
user_id = config["configurable"]["user_id"]
# Namespace the memory
namespace = (user_id, "memories")
# Search based on the most recent message
memories = store.search(
@@ -437,6 +448,7 @@ Under the hood, checkpointing is powered by checkpointer objects that conform to
* `langgraph-checkpoint-sqlite`: An implementation of LangGraph checkpointer that uses SQLite database ([SqliteSaver][langgraph.checkpoint.sqlite.SqliteSaver] / [AsyncSqliteSaver][langgraph.checkpoint.sqlite.aio.AsyncSqliteSaver]). Ideal for experimentation and local workflows. Needs to be installed separately.
* `langgraph-checkpoint-postgres`: An advanced checkpointer that uses Postgres database ([PostgresSaver][langgraph.checkpoint.postgres.PostgresSaver] / [AsyncPostgresSaver][langgraph.checkpoint.postgres.aio.AsyncPostgresSaver]), used in LangGraph Cloud. Ideal for using in production. Needs to be installed separately.
### Checkpointer interface
Each checkpointer conforms to [BaseCheckpointSaver][langgraph.checkpoint.base.BaseCheckpointSaver] interface and implements the following methods:
@@ -449,7 +461,7 @@ Each checkpointer conforms to [BaseCheckpointSaver][langgraph.checkpoint.base.Ba
If the checkpointer is used with asynchronous graph execution (i.e. executing the graph via `.ainvoke`, `.astream`, `.abatch`), asynchronous versions of the above methods will be used (`.aput`, `.aput_writes`, `.aget_tuple`, `.alist`).
!!! note Note
For running your graph asynchronously, you can use `MemorySaver`, or async versions of Sqlite/Postgres checkpointers -- `AsyncSqliteSaver` / `AsyncPostgresSaver` checkpointers.
For running your graph asynchronously, you can use `InMemorySaver`, or async versions of Sqlite/Postgres checkpointers -- `AsyncSqliteSaver` / `AsyncPostgresSaver` checkpointers.
### Serializer
+347
View File
@@ -0,0 +1,347 @@
# LangGraph's Runtime (Pregel)
[Pregel][langgraph.pregel.Pregel] implements LangGraph's runtime, managing the execution of LangGraph applications.
Compiling a [StateGraph][langgraph.graph.StateGraph] or creating an [entrypoint][langgraph.func.entrypoint] produces a [Pregel][langgraph.pregel.Pregel] instance that can be invoked with input.
This guide explains the runtime at a high level and provides instructions for directly implementing applications with Pregel.
> **Note:** The [Pregel][langgraph.pregel.Pregel] runtime is named after [Google's Pregel algorithm](https://research.google/pubs/pub37252/), which describes an efficient method for large-scale parallel computation using graphs.
## Overview
In LangGraph, Pregel combines [**actors**](https://en.wikipedia.org/wiki/Actor_model) and **channels** into a single application. **Actors** read data from channels and write data to channels. Pregel organizes the execution of the application into multiple steps, following the **Pregel Algorithm**/**Bulk Synchronous Parallel** model.
Each step consists of three phases:
- **Plan**: Determine which **actors** to execute in this step. For example, in the first step, select the **actors** that subscribe to the special **input** channels; in subsequent steps, select the **actors** that subscribe to channels updated in the previous step.
- **Execution**: Execute all selected **actors** in parallel, until all complete, or one fails, or a timeout is reached. During this phase, channel updates are invisible to actors until the next step.
- **Update**: Update the channels with the values written by the **actors** in this step.
Repeat until no **actors** are selected for execution, or a maximum number of steps is reached.
## Actors
An **actor** is a [PregelNode][langgraph.pregel.read.PregelNode]. It subscribes to channels, reads data from them, and writes data to them. It can be thought of as an **actor** in the Pregel algorithm. [PregelNodes][langgraph.pregel.read.PregelNode] implement LangChain's Runnable interface.
## Channels
Channels are used to communicate between actors (PregelNodes). Each channel has a value type, an update type, and an update function which takes a sequence of updates and modifies the stored value. Channels can be used to send data from one chain to another, or to send data from a chain to itself in a future step. LangGraph provides a number of built-in channels:
### Basic channels: LastValue and Topic
- [LastValue][langgraph.channels.LastValue]: The default channel, stores the last value sent to the channel, useful for input and output values, or for sending data from one step to the next.
- [Topic][langgraph.channels.Topic]: A configurable PubSub Topic, useful for sending multiple values between **actors**, or for accumulating output. Can be configured to deduplicate values or to accumulate values over the course of multiple steps.
### Advanced channels: Context and BinaryOperatorAggregate
- `Context`: exposes the value of a context manager, managing its lifecycle. Useful for accessing external resources that require setup and/or teardown; e.g., `client = Context(httpx.Client)`.
- [BinaryOperatorAggregate][langgraph.channels.BinaryOperatorAggregate]: stores a persistent value, updated by applying a binary operator to the current value and each update sent to the channel, useful for computing aggregates over multiple steps; e.g.,`total = BinaryOperatorAggregate(int, operator.add)`
## Examples
While most users will interact with Pregel through the [StateGraph][langgraph.graph.StateGraph] API or
the [entrypoint][langgraph.func.entrypoint] decorator, it is possible to interact with Pregel directly.
Below are a few different examples to give you a sense of the Pregel API.
=== "Single node"
```python
from langgraph.channels import EphemeralValue
from langgraph.pregel import Pregel, Channel
node1 = (
Channel.subscribe_to("a")
| (lambda x: x + x)
| Channel.write_to("b")
)
app = Pregel(
nodes={"node1": node1},
channels={
"a": EphemeralValue(str),
"b": EphemeralValue(str),
},
input_channels=["a"],
output_channels=["b"],
)
app.invoke({"a": "foo"})
```
```con
{'b': 'foofoo'}
```
=== "Multiple nodes"
```python
from langgraph.channels import LastValue, EphemeralValue
from langgraph.pregel import Pregel, Channel
node1 = (
Channel.subscribe_to("a")
| (lambda x: x + x)
| Channel.write_to("b")
)
node2 = (
Channel.subscribe_to("b")
| (lambda x: x + x)
| Channel.write_to("c")
)
app = Pregel(
nodes={"node1": node1, "node2": node2},
channels={
"a": EphemeralValue(str),
"b": LastValue(str),
"c": EphemeralValue(str),
},
input_channels=["a"],
output_channels=["b", "c"],
)
app.invoke({"a": "foo"})
```
```con
{'b': 'foofoo', 'c': 'foofoofoofoo'}
```
=== "Topic"
```python
from langgraph.channels import EphemeralValue, Topic
from langgraph.pregel import Pregel, Channel
node1 = (
Channel.subscribe_to("a")
| (lambda x: x + x)
| {
"b": Channel.write_to("b"),
"c": Channel.write_to("c")
}
)
node2 = (
Channel.subscribe_to("b")
| (lambda x: x + x)
| {
"c": Channel.write_to("c"),
}
)
app = Pregel(
nodes={"node1": node1, "node2": node2},
channels={
"a": EphemeralValue(str),
"b": EphemeralValue(str),
"c": Topic(str, accumulate=True),
},
input_channels=["a"],
output_channels=["c"],
)
app.invoke({"a": "foo"})
```
```pycon
{'c': ['foofoo', 'foofoofoofoo']}
```
=== "BinaryOperatorAggregate"
This examples demonstrates how to use the BinaryOperatorAggregate channel to implement a reducer.
```python
from langgraph.channels import EphemeralValue, BinaryOperatorAggregate
from langgraph.pregel import Pregel, Channel
node1 = (
Channel.subscribe_to("a")
| (lambda x: x + x)
| {
"b": Channel.write_to("b"),
"c": Channel.write_to("c")
}
)
node2 = (
Channel.subscribe_to("b")
| (lambda x: x + x)
| {
"c": Channel.write_to("c"),
}
)
def reducer(current, update):
if current:
return current + " | " + "update"
else:
return update
app = Pregel(
nodes={"node1": node1, "node2": node2},
channels={
"a": EphemeralValue(str),
"b": EphemeralValue(str),
"c": BinaryOperatorAggregate(str, operator=reducer),
},
input_channels=["a"],
output_channels=["c"],
)
app.invoke({"a": "foo"})
```
=== "Cycle"
This example demonstrates how to introduce a cycle in the graph, by having
a chain write to a channel it subscribes to. Execution will continue
until a None value is written to the channel.
```python
from langgraph.channels import EphemeralValue
from langgraph.pregel import Pregel, Channel, ChannelWrite, ChannelWriteEntry
example_node = (
Channel.subscribe_to("value")
| (lambda x: x + x if len(x) < 10 else None)
| ChannelWrite(writes=[ChannelWriteEntry(channel="value", skip_none=True)])
)
app = Pregel(
nodes={"example_node": example_node},
channels={
"value": EphemeralValue(str),
},
input_channels=["value"],
output_channels=["value"],
)
app.invoke({"value": "a"})
```
```pycon
{'value': 'aaaaaaaaaaaaaaaa'}
```
## High-level API
LangGraph provides two high-level APIs for creating a Pregel application: the [StateGraph (Graph API)](./low_level.md) and the [Functional API](functional_api.md).
=== "StateGraph (Graph API)"
The [StateGraph (Graph API)][langgraph.graph.StateGraph] is a higher-level abstraction that simplifies the creation of Pregel applications. It allows you to define a graph of nodes and edges. When you compile the graph, the StateGraph API automatically creates the Pregel application for you.
```python
from typing import TypedDict, Optional
from langgraph.constants import START
from langgraph.graph import StateGraph
class Essay(TypedDict):
topic: str
content: Optional[str]
score: Optional[float]
def write_essay(essay: Essay):
return {
"content": f"Essay about {essay['topic']}",
}
def score_essay(essay: Essay):
return {
"score": 10
}
builder = StateGraph(Essay)
builder.add_node(write_essay)
builder.add_node(score_essay)
builder.add_edge(START, "write_essay")
# Compile the graph.
# This will return a Pregel instance.
graph = builder.compile()
```
The compiled Pregel instance will be associated with a list of nodes and channels. You can inspect the nodes and channels by printing them.
```python
print(graph.nodes)
```
You will see something like this:
```pycon
{'__start__': <langgraph.pregel.read.PregelNode at 0x7d05e3ba1810>,
'write_essay': <langgraph.pregel.read.PregelNode at 0x7d05e3ba14d0>,
'score_essay': <langgraph.pregel.read.PregelNode at 0x7d05e3ba1710>}
```
```python
print(graph.channels)
```
You should see something like this
```pycon
{'topic': <langgraph.channels.last_value.LastValue at 0x7d05e3294d80>,
'content': <langgraph.channels.last_value.LastValue at 0x7d05e3295040>,
'score': <langgraph.channels.last_value.LastValue at 0x7d05e3295980>,
'__start__': <langgraph.channels.ephemeral_value.EphemeralValue at 0x7d05e3297e00>,
'write_essay': <langgraph.channels.ephemeral_value.EphemeralValue at 0x7d05e32960c0>,
'score_essay': <langgraph.channels.ephemeral_value.EphemeralValue at 0x7d05e2d8ab80>,
'branch:__start__:__self__:write_essay': <langgraph.channels.ephemeral_value.EphemeralValue at 0x7d05e32941c0>,
'branch:__start__:__self__:score_essay': <langgraph.channels.ephemeral_value.EphemeralValue at 0x7d05e2d88800>,
'branch:write_essay:__self__:write_essay': <langgraph.channels.ephemeral_value.EphemeralValue at 0x7d05e3295ec0>,
'branch:write_essay:__self__:score_essay': <langgraph.channels.ephemeral_value.EphemeralValue at 0x7d05e2d8ac00>,
'branch:score_essay:__self__:write_essay': <langgraph.channels.ephemeral_value.EphemeralValue at 0x7d05e2d89700>,
'branch:score_essay:__self__:score_essay': <langgraph.channels.ephemeral_value.EphemeralValue at 0x7d05e2d8b400>,
'start:write_essay': <langgraph.channels.ephemeral_value.EphemeralValue at 0x7d05e2d8b280>}
```
=== "Functional API"
In the [Functional API](functional_api.md), you can use an [`entrypoint`][langgraph.func.entrypoint] to create
a Pregel application. The `entrypoint` decorator allows you to define a function that takes input and returns output.
```python
from typing import TypedDict, Optional
from langgraph.checkpoint.memory import InMemorySaver
from langgraph.func import entrypoint
class Essay(TypedDict):
topic: str
content: Optional[str]
score: Optional[float]
checkpointer = InMemorySaver()
@entrypoint(checkpointer=checkpointer)
def write_essay(essay: Essay):
return {
"content": f"Essay about {essay['topic']}",
}
print("Nodes: ")
print(write_essay.nodes)
print("Channels: ")
print(write_essay.channels)
```
```pycon
Nodes:
{'write_essay': <langgraph.pregel.read.PregelNode object at 0x7d05e2f9aad0>}
Channels:
{'__start__': <langgraph.channels.ephemeral_value.EphemeralValue object at 0x7d05e2c906c0>, '__end__': <langgraph.channels.last_value.LastValue object at 0x7d05e2c90c40>, '__previous__': <langgraph.channels.last_value.LastValue object at 0x7d05e1007280>}
```
@@ -0,0 +1,35 @@
# LangGraph Platform: Scalability & Resilience
LangGraph Platform is designed to scale horizontally with your workload. Each instance of the service is stateless, and keeps no resources in memory. The service is designed to gracefully handle new instances being added or removed, including hard shutdown cases.
## Server scalability
As you add more instances to a service, they will share the HTTP load as long as an appropriate load balancer mechanism is placed in front of them. In most deployment modalities we configure a load balancer for the service automatically. In the “self-hosted without control plane” modality its your responsibility to add a load balancer. Since the instances are stateless any load balancing strategy will work, no session stickiness is needed, or recommended. Any instance of the server can communicate with any queue instance (through Redis PubSub), meaning that requests to cancel or stream an in-progress run can be handled by any arbitrary instance.
## Queue scalability
As you add more instances to a service, they will increase run throughput linearly, as each instance is configured to handle a set number of concurrent runs (by default 10). Each attempt for each run will be handled by a single instance, with exactly-once semantics enforced through Postgress MVCC model (refer to section below for crash resilience details). Attempts that fail due to transient database errors are retried up to 3 times. We do not make use of long-lived transactions or locks, this enables us to make more efficient use of Postgres resources.
## Resilience
While a run is being handled by a queue instance, a periodic heartbeat timestamp will be recorded in Redis by that queue worker.
When a graceful shutdown request is received (SIGINT) an instance enters shutdown mode, which
- stops accepting new HTTP requests
- gives any in-progress runs a limited number of seconds to finish (if not finished it will be put back in the queue)
- stops the instance from picking up more runs from the queue
If a hard shutdown occurs, eg. due to a server crash, or an infra failure, any runs that were in progress will be picked up by a periodic sweeper task that looks for in-progress runs that have breached their heartbeat window, which will put them back in the queue for another instance to pick them up.
## Postgres resilience
For deployment modalities where we manage the Postgres database we have periodic backups, continuously replicated standby replicas for automatic failover. Optionally, on request, we can also setup read replicas as well as other advanced failover capabilities.
All communication with Postgres implements retries for retry-able errors. If Postgres is momentarily unavailable, such as during a database restart, most/all traffic should continue to succeed. Prolonged failure of the Postgres instance will switch traffic to the failover replica. If the failover replica also fails before the primary is brought back online the service would become unavailable.
## Redis resilience
All data that requires durable storage is stored in Postgres, not Redis. Redis is used only for ephemeral metadata, and communication between instances. Refer to the [architecture](./platform_architecture.md) page for more details on how we use Redis. Therefore we place no durability requirements on Redis.
All communication with Redis implements retries for retry-able errors. If Redis is momentarily unavailable, such as during a database restart, most/all traffic should continue to succeed. Prolonged failure of Redis will render the LGP service unavailable.
@@ -1,3 +1,8 @@
---
search:
exclude: true
---
# Human-in-the-loop
!!! note "Use the `interrupt` function instead."
+1 -1
View File
@@ -33,7 +33,7 @@
" )\n",
"```\n",
"\n",
"If you are using [subgraphs](#subgraphs), you might want to navigate from a node a subgraph to a different subgraph (i.e. a different node in the parent graph). To do so, you can specify `graph=Command.PARENT` in `Command`:\n",
"If you are using [subgraphs](#subgraphs), you might want to navigate from a node within a subgraph to a different subgraph (i.e. a different node in the parent graph). To do so, you can specify `graph=Command.PARENT` in `Command`:\n",
"\n",
"```python\n",
"def my_node(state: State) -> Command[Literal[\"my_other_node\"]]:\n",
File diff suppressed because one or more lines are too long
@@ -122,20 +122,18 @@
"\n",
"# For this tutorial we will use custom tool that returns pre-defined values for weather in two cities (NYC & SF)\n",
"\n",
"from typing import Literal\n",
"\n",
"from langchain_core.tools import tool\n",
"\n",
"\n",
"@tool\n",
"def get_weather(city: Literal[\"nyc\", \"sf\"]):\n",
"def get_weather(location: str) -> str:\n",
" \"\"\"Use this to get weather information.\"\"\"\n",
" if city == \"nyc\":\n",
" if any([city in location.lower() for city in [\"nyc\", \"new york city\"]]):\n",
" return \"It might be cloudy in nyc\"\n",
" elif city == \"sf\":\n",
" elif any([city in location.lower() for city in [\"sf\", \"san francisco\"]]):\n",
" return \"It's always sunny in sf\"\n",
" else:\n",
" raise AssertionError(\"Unknown city\")\n",
" return f\"I am not sure what the weather is in {location}\"\n",
"\n",
"\n",
"tools = [get_weather]\n",
@@ -220,7 +218,7 @@
"id": "838a043f-90ad-4e69-9d1d-6e22db2c346c",
"metadata": {},
"source": [
"Notice that when we pass the same the same thread ID, the chat history is preserved"
"Notice that when we pass the same thread ID, the chat history is preserved."
]
},
{
+82
View File
@@ -0,0 +1,82 @@
# How to add custom lifespan events
When deploying agents on the LangGraph platform, you often need to initialize resources like database connections when your server starts up, and ensure they're properly closed when it shuts down. Lifespan events let you hook into your server's startup and shutdown sequence to handle these critical setup and teardown tasks.
This works the same way as [adding custom routes](./custom_routes.md) - you just need to provide your own [`Starlette`](https://www.starlette.io/applications/) app (including [`FastAPI`](https://fastapi.tiangolo.com/), [`FastHTML`](https://fastht.ml/) and other compatible apps).
Below is an example using FastAPI.
???+ note "Python only"
We currently only support custom lifespan events in Python deployments with `langgraph-api>=0.0.26`.
## Create app
Starting from an **existing** LangGraph Platform application, add the following lifespan code to your `webapp.py` file. If you are starting from scratch, you can create a new app from a template using the CLI.
```bash
langgraph new --template=new-langgraph-project-python my_new_project
```
Once you have a LangGraph project, add the following app code:
```python
# ./src/agent/webapp.py
from contextlib import asynccontextmanager
from fastapi import FastAPI
from sqlalchemy.ext.asyncio import create_async_engine, AsyncSession
from sqlalchemy.orm import sessionmaker
@asynccontextmanager
async def lifespan(app: FastAPI):
# for example...
engine = create_async_engine("postgresql+asyncpg://user:pass@localhost/db")
# Create reusable session factory
async_session = sessionmaker(engine, class_=AsyncSession)
# Store in app state
app.state.db_session = async_session
yield
# Clean up connections
await engine.dispose()
# highlight-next-line
app = FastAPI(lifespan=lifespan)
# ... can add custom routes if needed.
```
## Configure `langgraph.json`
Add the following to your `langgraph.json` file. Make sure the path points to the `webapp.py` file you created above.
```json
{
"dependencies": ["."],
"graphs": {
"agent": "./src/agent/graph.py:graph"
},
"env": ".env",
"http": {
"app": "./src/agent/webapp.py:app"
}
// Other configuration options like auth, store, etc.
}
```
## Start server
Test the server out locally:
```bash
langgraph dev --no-browser
```
You should see your startup message printed when the server starts, and your cleanup message when you stop it with Ctrl+C.
## Deploying
You can deploy your app as-is to the managed langgraph cloud or to your self-hosted platform.
## Next steps
Now that you've added lifespan events to your deployment, you can use similar techniques to add [custom routes](./custom_routes.md) or [custom middleware](./custom_middleware.md) to further customize your server's behavior.
@@ -0,0 +1,75 @@
# How to add custom middleware
When deploying agents on the LangGraph platform, you can add custom middleware to your server to handle cross-cutting concerns like logging request metrics, injecting or checking headers, and enforcing security policies without modifying core server logic. This works the same way as [adding custom routes](./custom_routes.md) - you just need to provide your own [`Starlette`](https://www.starlette.io/applications/) app (including [`FastAPI`](https://fastapi.tiangolo.com/), [`FastHTML`](https://fastht.ml/) and other compatible apps).
Adding middleware lets you intercept and modify requests and responses globally across your deployment, whether they're hitting your custom endpoints or the built-in LangGraph Platform APIs.
Below is an example using FastAPI.
???+ note "Python only"
We currently only support custom middleware in Python deployments with `langgraph-api>=0.0.26`.
## Create app
Starting from an **existing** LangGraph Platform application, add the following middleware code to your `webapp.py` file. If you are starting from scratch, you can create a new app from a template using the CLI.
```bash
langgraph new --template=new-langgraph-project-python my_new_project
```
Once you have a LangGraph project, add the following app code:
```python
# ./src/agent/webapp.py
from fastapi import FastAPI, Request
from starlette.middleware.base import BaseHTTPMiddleware
# highlight-next-line
app = FastAPI()
class CustomHeaderMiddleware(BaseHTTPMiddleware):
async def dispatch(self, request: Request, call_next):
response = await call_next(request)
response.headers['X-Custom-Header'] = 'Hello from middleware!'
return response
# Add the middleware to the app
app.add_middleware(CustomHeaderMiddleware)
```
## Configure `langgraph.json`
Add the following to your `langgraph.json` file. Make sure the path points to the `webapp.py` file you created above.
```json
{
"dependencies": ["."],
"graphs": {
"agent": "./src/agent/graph.py:graph"
},
"env": ".env",
"http": {
"app": "./src/agent/webapp.py:app"
}
// Other configuration options like auth, store, etc.
}
```
## Start server
Test the server out locally:
```bash
langgraph dev --no-browser
```
Now any request to your server will include the custom header `X-Custom-Header` in its response.
## Deploying
You can deploy this app as-is to the managed langgraph cloud or to your self-hosted platform.
## Next steps
Now that you've added custom middleware to your deployment, you can use similar techniques to add [custom routes](./custom_routes.md) or define [custom lifespan events](./custom_lifespan.md) to further customize your server's behavior.
+78
View File
@@ -0,0 +1,78 @@
# How to add custom routes
When deploying agents on the LangGraph platform, your server automatically exposes routes for creating runs and threads, interacting with the long-term memory store, managing configurable assistants, and other core functionality ([see all default API endpoints](../../cloud/reference/api/api_ref.md)).
You can add custom routes by providing your own [`Starlette`](https://www.starlette.io/applications/) app (including [`FastAPI`](https://fastapi.tiangolo.com/), [`FastHTML`](https://fastht.ml/) and other compatible apps). You make LangGraph Platform aware of this by providing a path to the app in your `langgraph.json` configuration file. (`"http": {"app": "path/to/app.py:app"}`).
Defining a custom app object lets you add any routes you'd like, so you can do anything from adding a `/login` endpoint to writing an entire full-stack web-app, all deployed in a single LangGraph deployment.
Below is an example using FastAPI.
???+ note "Python only"
We currently only support custom authentication and authorization in Python deployments with `langgraph-api>=0.0.26`.
## Create app
Starting from an **existing** LangGraph Platform application, add the following custom route code to your `webapp.py` file. If you are starting from scratch, you can create a new app from a template using the CLI.
```bash
langgraph new --template=new-langgraph-project-python my_new_project
```
Once you have a LangGraph project, add the following app code:
```python
# ./src/agent/webapp.py
from fastapi import FastAPI
# highlight-next-line
app = FastAPI()
@app.get("/hello")
def read_root():
return {"Hello": "World"}
```
## Configure `langgraph.json`
Add the following to your `langgraph.json` file. Make sure the path points to the `app.py` file you created above.
```json
{
"dependencies": ["."],
"graphs": {
"agent": "./src/agent/graph.py:graph"
},
"env": ".env",
"http": {
"app": "./src/agent/webapp.py:app"
}
// Other configuration options like auth, store, etc.
}
```
## Start server
Test the server out locally:
```bash
langgraph dev --no-browser
```
If you navigate to `localhost:2024/hello` in your browser (2024 is the default development port), you should see the `hello` endpoint returning `{"Hello": "World"}`.
!!! note "Shadowing default endpoints"
The routes you create in the app are given priority over the system defaults, meaning you can shadow and redefine the behavior of any default endpoint.
## Deploying
You can deploy this app as-is to the managed langgraph cloud or to your self-hosted platform.
## Next steps
Now that you've added a custom route to your deployment, you can use this same technique to further customize how your server behaves, such as defining custom [custom middleware](./custom_middleware.md) and [custom lifespan events](./custom_lifespan.md).
@@ -397,7 +397,8 @@
"# We define a fake node to ask the human\n",
"def ask_human(state):\n",
" tool_call_id = state[\"messages\"][-1].tool_calls[0][\"id\"]\n",
" location = interrupt(\"Please provide your location:\")\n",
" ask = AskHuman.model_validate(state[\"messages\"][-1].tool_calls[0][\"args\"])\n",
" location = interrupt(ask.question)\n",
" tool_message = [{\"tool_call_id\": tool_call_id, \"type\": \"tool\", \"content\": location}]\n",
" return {\"messages\": tool_message}\n",
"\n",
@@ -491,7 +492,7 @@
" \"messages\": [\n",
" (\n",
" \"user\",\n",
" \"Use the search tool to ask the user where they are, then look up the weather there\",\n",
" \"Ask the user where they are, then look up the weather there\",\n",
" )\n",
" ]\n",
" },\n",
+24 -9
View File
@@ -59,12 +59,10 @@ LangGraph makes it easy to manage conversation [memory](../concepts/memory.md) i
[Human-in-the-loop](../concepts/human_in_the_loop.md) functionality allows
you to involve humans in the decision-making process of your graph. These how-to guides show how to implement human-in-the-loop workflows in your graph.
Key workflows:
- [How to wait for user input](human_in_the_loop/wait-user-input.ipynb): A basic example that shows how to implement a human-in-the-loop workflow in your graph using the `interrupt` function.
- [How to review tool calls](human_in_the_loop/review-tool-calls.ipynb): Incorporate human-in-the-loop for reviewing/editing/accepting tool call requests before they executed using the `interrupt` function.
Other methods:
@@ -165,6 +163,7 @@ These guides show how to use the prebuilt ReAct agent:
- [How to add human-in-the-loop processes to a ReAct agent](create-react-agent-hitl.ipynb)
- [How to return structured output from a ReAct agent](create-react-agent-structured-output.ipynb)
- [How to add semantic search for long-term memory to a ReAct agent](memory/semantic-search.ipynb#using-in-create-react-agent)
- [How to manage message history in a ReAct agent](create-react-agent-manage-message-history.ipynb)
Interested in further customizing the ReAct agent? This guide provides an
overview of its underlying implementation to help you customize for your own needs:
@@ -200,21 +199,29 @@ Learn how to set up your app for deployment to LangGraph Platform:
- [How to test locally](../cloud/deployment/test_locally.md)
- [How to rebuild graph at runtime](../cloud/deployment/graph_rebuild.md)
- [How to use LangGraph Platform to deploy CrewAI, AutoGen, and other frameworks](autogen-langgraph-platform.ipynb)
- [How to integrate LangGraph into your React application](../cloud/how-tos/use_stream_react.md)
### Deployment
LangGraph applications can be deployed using LangGraph Cloud, which provides a range of services to help you deploy, manage, and scale your applications.
LangGraph applications can be deployed using LangGraph Platform, which provides a range of services to help you deploy, manage, and scale your applications.
- [How to deploy to LangGraph cloud](../cloud/deployment/cloud.md)
- [How to deploy to a self-hosted environment](./deploy-self-hosted.md)
- [How to deploy to Cloud SaaS](../cloud/deployment/cloud.md)
- [How to deploy the Self-Hosted Data Plane](../cloud/deployment/self_hosted_data_plane.md)
- [How to deploy the Self-Hosted Control Plane](../cloud/deployment/self_hosted_control_plane.md)
- [How to deploy a Standalone Container](../cloud/deployment/standalone_container.md)
- [How to interact with the deployment using RemoteGraph](./use-remote-graph.md)
- [How to add TTLs to your LangGraph application](./ttl/configure_ttl.md)
### Authentication & Access Control
- [How to add custom authentication](./auth/custom_auth.md)
- [How to update the security schema of your OpenAPI spec](./auth/openapi_security.md)
### Modifying the API
- [How to add custom routes](./http/custom_routes.md)
- [How to add custom middleware](./http/custom_middleware.md)
- [How to add custom lifespan events](./http/custom_lifespan.md)
### Assistants
[Assistants](../concepts/assistants.md) is a configured instance of a template.
@@ -253,6 +260,13 @@ Streaming the results of your LLM application is vital for ensuring a good user
- [How to stream in debug mode](../cloud/how-tos/stream_debug.md)
- [How to stream multiple modes](../cloud/how-tos/stream_multiple.md)
### Frontend and Generative UI
With LangGraph Platform you can integrate LangGraph agents into your React applications and colocate UI components with your agent code.
- [How to integrate LangGraph into your React application](../cloud/how-tos/use_stream_react.md)
- [How to implement Generative User Interfaces with LangGraph](../cloud/how-tos/generative_ui_react.md)
### Human-in-the-loop
When designing complex graphs, relying entirely on the LLM for decision-making can be risky, particularly when it involves tools that interact with files, APIs, or databases. These interactions may lead to unintended data access or modifications, depending on the use case. To mitigate these risks, LangGraph allows you to integrate human-in-the-loop behavior, ensuring your LLM applications operate as intended without undesirable outcomes.
@@ -284,12 +298,13 @@ Graph execution can take a while, and sometimes users may change their mind abou
LangGraph Studio is a built-in UI for visualizing, testing, and debugging your agents.
- [How to connect to a LangGraph Cloud deployment](../cloud/how-tos/test_deployment.md)
- [How to connect to a LangGraph Platform deployment](../cloud/how-tos/test_deployment.md)
- [How to connect to a local dev server](../how-tos/local-studio.md)
- [How to connect to a local deployment (Docker)](../cloud/how-tos/test_local_deployment.md)
- [How to test your graph in LangGraph Studio (MacOS only)](../cloud/how-tos/invoke_studio.md)
- [How to interact with threads in LangGraph Studio](../cloud/how-tos/threads_studio.md)
- [How to add nodes as dataset examples in LangGraph Studio](../cloud/how-tos/datasets_studio.md)
- [How to engineer prompts in LangGraph Studio](../cloud/how-tos/iterate_graph_studio.md)
- [How to test your agent against remote traces](../cloud/how-tos/clone_traces_studio.md)
## Troubleshooting
@@ -305,4 +320,4 @@ These are the guides for resolving common errors you may find while building wit
These guides provide troubleshooting information for errors that are specific to the LangGraph Platform.
- [INVALID_LICENSE](../troubleshooting/errors/INVALID_LICENSE.md)
- [INVALID_LICENSE](../troubleshooting/errors/INVALID_LICENSE.md)
+5 -15
View File
@@ -1,15 +1,6 @@
# How to connect a local agent to LangGraph Studio
This guide shows you how to connect your local agent to [LangGraph Studio](../concepts/langgraph_studio.md) for visualization, interaction, and debugging.
## Connection Options
There are two ways to connect your local agent to LangGraph Studio:
- [Development Server](../concepts/langgraph_studio.md#development-server-with-web-ui): Python package, all platforms, no Docker
- [LangGraph Desktop](../concepts/langgraph_studio.md#desktop-app): Application, Mac only, requires Docker
In this guide we will cover how to use the development server as that is generally an easier and better experience.
This guide shows you how to connect your local agent to [LangGraph Studio](../concepts/langgraph_studio.md) for visualization, interaction, and debugging using the development server.
## Setup your application
@@ -24,9 +15,8 @@ You will need to make sure to install the `inmem` extras.
???+ note "Minimum version"
The minimum version to use the `inmem` extra with `langgraph-cli` is `0.1.55`.
Python 3.11 or higher is required.
The minimum version to use the `inmem` extra with `langgraph-cli` is `0.1.55`.
Python 3.11 or higher is required.
```shell
pip install -U "langgraph-cli[inmem]"
@@ -41,7 +31,7 @@ pip install -U "langgraph-cli[inmem]"
langgraph dev
```
This will look for the `langgraph.json` file in your current directory.
This will look for the `langgraph.json` file in your current directory.
In there, it will find the paths to the graph(s), and start those up.
It will then automatically connect to the cloud-hosted studio.
@@ -89,4 +79,4 @@ Then attach your preferred debugger:
2. Click + and select "Python Debug Server"
3. Set IDE host name: `localhost`
4. Set port: `5678` (or the port number you chose in the previous step)
5. Click "OK" and start debugging
5. Click "OK" and start debugging
+1 -1
View File
@@ -207,7 +207,7 @@
"\n",
"\n",
"# Here we define the logic to map out over the generated subjects\n",
"# We will use this an edge in the graph\n",
"# We will use this as an edge in the graph\n",
"def continue_to_jokes(state: OverallState):\n",
" # We will return a list of `Send` objects\n",
" # Each `Send` object consists of the name of a node in the graph\n",
@@ -10,6 +10,7 @@
"One of the most common use cases for persistence is to use it to keep track of conversation history. This is great - it makes it easy to continue conversations. As conversations get longer and longer, however, this conversation history can build up and take up more and more of the context window. This can often be undesirable as it leads to more expensive and longer calls to the LLM, and potentially ones that error. One way to work around that is to create a summary of the conversation to date, and use that with the past N messages. This guide will go through an example of how to do that.\n",
"\n",
"This will involve a few steps:\n",
"\n",
"- Check if the conversation is too long (can be done by checking number of messages or length of messages)\n",
"- If yes, the create summary (will need a prompt for this)\n",
"- Then remove all except the last N messages\n",
@@ -98,7 +99,7 @@
"from typing import Literal\n",
"\n",
"from langchain_anthropic import ChatAnthropic\n",
"from langchain_core.messages import SystemMessage, RemoveMessage\n",
"from langchain_core.messages import SystemMessage, RemoveMessage, HumanMessage\n",
"from langgraph.checkpoint.memory import MemorySaver\n",
"from langgraph.graph import MessagesState, StateGraph, START, END\n",
"\n",
@@ -7,7 +7,7 @@
"source": [
"# How to manage conversation history\n",
"\n",
"One of the most common use cases for persistence is to use it to keep track of conversation history. This is great - it makes it easy to continue conversations. As conversations get longer and longer, however, this conversation history can build up and take up more and more of the context window. This can often be undesirable as it leads to more expensive and longer calls to the LLM, and potentially ones that error. In order to prevent this from happening, you need to probably manage the conversation history.\n",
"One of the most common use cases for persistence is to use it to keep track of conversation history. This is great - it makes it easy to continue conversations. As conversations get longer and longer, however, this conversation history can build up and take up more and more of the context window. This can often be undesirable as it leads to more expensive and longer calls to the LLM, and potentially ones that error. In order to prevent this from happening, you need to properly manage the conversation history.\n",
"\n",
"Note: this guide focuses on how to do this in LangGraph, where you can fully customize how this is done. If you want a more off-the-shelf solution, you can look into functionality provided in LangChain:\n",
"\n",
@@ -38,7 +38,7 @@
" </p>\n",
"</div> \n",
"\n",
"The core technique the examples below is to **annotate** a parameter as \"injected\", meaning it will be injected by your program and should not be seen or populated by the LLM. Let the following codesnippet serve as a tl;dr:\n",
"The core technique in the examples below is to **annotate** a parameter as \"injected\", meaning it will be injected by your program and should not be seen or populated by the LLM. Let the following codesnippet serve as a tl;dr:\n",
"\n",
"```python\n",
"from typing import Annotated\n",
@@ -16,6 +16,10 @@
" - [Memory](../../concepts/memory/)\n",
" - [Chat Models](https://python.langchain.com/docs/concepts/chat_models/)\n",
"\n",
"!!! info \"Not needed for LangGraph API users\"\n",
"\n",
" If you're using the LangGraph API, you needn't manually implement a checkpointer. The API automatically handles checkpointing for you. This guide is relevant when implementing LangGraph in your own custom server.\n",
"\n",
"Many AI applications need memory to share context across multiple interactions on the same [thread](../../concepts/persistence#threads) (e.g., multiple turns of a conversation). In LangGraph functional API, this kind of memory can be added to any [entrypoint()][langgraph.func.entrypoint] workflow using [thread-level persistence](https://langchain-ai.github.io/langgraph/concepts/persistence).\n",
"\n",
"When creating a LangGraph workflow, you can set it up to persist its results by using a [checkpointer](https://langchain-ai.github.io/langgraph/reference/checkpoints/#basecheckpointsaver):\n",
+4
View File
@@ -31,6 +31,10 @@
" </p>\n",
"</div> \n",
"\n",
"!!! info \"Not needed for LangGraph API users\"\n",
"\n",
" If you're using the LangGraph API, you needn't manually implement a checkpointer. The API automatically handles checkpointing for you. This guide is relevant when implementing LangGraph in your own custom server.\n",
"\n",
"Many AI applications need memory to share context across multiple interactions. In LangGraph, this kind of memory can be added to any [StateGraph](https://langchain-ai.github.io/langgraph/reference/graphs/#langgraph.graph.StateGraph) using [thread-level persistence](https://langchain-ai.github.io/langgraph/concepts/persistence) .\n",
"\n",
"When creating any LangGraph graph, you can set it up to persist its state by adding a [checkpointer](https://langchain-ai.github.io/langgraph/reference/checkpoints/#basecheckpointsaver) when compiling the graph:\n",
+5 -1
View File
@@ -26,6 +26,10 @@
" </p>\n",
"</div> \n",
"\n",
"!!! info \"Not needed for LangGraph API users\"\n",
"\n",
" If you're using the LangGraph API, you needn't manually implement a checkpointer. The API automatically handles checkpointing for you. This guide is relevant when implementing LangGraph in your own custom server.\n",
"\n",
"When creating LangGraph agents, you can also set them up so that they persist their state. This allows you to do things like interact with an agent multiple times and have it remember previous interactions.\n",
"\n",
"This how-to guide shows how to use `Postgres` as the backend for persisting checkpoint state using the [`langgraph-checkpoint-postgres`](https://github.com/langchain-ai/langgraph/tree/main/libs/checkpoint-postgres) library.\n",
@@ -44,7 +48,7 @@
"...\n",
"```\n",
"\n",
"!!! info \"Setup\"",
"!!! info \"Setup\"\n",
"\n",
" You need to run `.setup()` once on your checkpointer to initialize the database before you can use it."
]
@@ -65,7 +65,7 @@
"\n",
"**Pros and Cons**\n",
"\n",
"The benefit to this format is that you only need one LLM, and can save money and latency because of this. The downside to this option is that it isn't guaranteed that the single LLM will call the correct tool when you want it to. We can help the LLM by setting `tool_choice` to `any` when we use `bind_tools` which forces the LLM to select at least one tool at every turn, but this is far from a fool proof strategy. In addition, another downside is that the agent might call *multiple* tools, so we need to check for this explicitly in our routing function (or if we are using OpenAI we an set `parallell_tool_calling=False` to ensure only one tool is called at a time).\n",
"The benefit to this format is that you only need one LLM, and can save money and latency because of this. The downside to this option is that it isn't guaranteed that the single LLM will call the correct tool when you want it to. We can help the LLM by setting `tool_choice` to `any` when we use `bind_tools` which forces the LLM to select at least one tool at every turn, but this is far from a foolproof strategy. In addition, another downside is that the agent might call *multiple* tools, so we need to check for this explicitly in our routing function (or if we are using OpenAI we can set `parallell_tool_calling=False` to ensure only one tool is called at a time).\n",
"\n",
"**Option 2**\n",
"\n",
+229
View File
@@ -266,6 +266,235 @@
" print(\"An exception was raised because bad_node sets `a` to an integer.\")\n",
" print(e)"
]
},
{
"cell_type": "markdown",
"id": "2270bc3c",
"metadata": {},
"source": [
"## Multiple Nodes\n",
"\n",
"Run-time validation will also work in a multi-node graph. In the example below `bad_node` updates `a` to an integer. \n",
"\n",
"Because run-time validation occurs on **inputs**, the validation error will occur when `ok_node` is called (not when `bad_node` returns an update to the state which is inconsistent with the schema)."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "d832cdcc",
"metadata": {},
"outputs": [],
"source": [
"from langgraph.graph import StateGraph, START, END\n",
"from typing_extensions import TypedDict\n",
"\n",
"from pydantic import BaseModel\n",
"\n",
"\n",
"# The overall state of the graph (this is the public state shared across nodes)\n",
"class OverallState(BaseModel):\n",
" a: str\n",
"\n",
"\n",
"def bad_node(state: OverallState):\n",
" return {\n",
" \"a\": 123 # Invalid\n",
" }\n",
"\n",
"\n",
"def ok_node(state: OverallState):\n",
" return {\"a\": \"goodbye\"}\n",
"\n",
"\n",
"# Build the state graph\n",
"builder = StateGraph(OverallState)\n",
"builder.add_node(bad_node)\n",
"builder.add_node(ok_node)\n",
"builder.add_edge(START, \"bad_node\")\n",
"builder.add_edge(\"bad_node\", \"ok_node\")\n",
"builder.add_edge(\"ok_node\", END)\n",
"graph = builder.compile()\n",
"\n",
"# Test the graph with a valid input\n",
"try:\n",
" graph.invoke({\"a\": \"hello\"})\n",
"except Exception as e:\n",
" print(\"An exception was raised because bad_node sets `a` to an integer.\")\n",
" print(e)"
]
},
{
"cell_type": "markdown",
"id": "456b1f77",
"metadata": {},
"source": [
"## Advanced Pydantic Model Usage\n",
"\n",
"This section covers more advanced topics when using Pydantic models with LangGraph.\n",
"\n",
"### Serialization Behavior\n",
"\n",
"When using Pydantic models as state schemas, it's important to understand how serialization works, especially when:\n",
"- Passing Pydantic objects as inputs\n",
"- Receiving outputs from the graph\n",
"- Working with nested Pydantic models\n",
"\n",
"Let's see these behaviors in action:"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "0e919cdc",
"metadata": {},
"outputs": [],
"source": [
"from langgraph.graph import StateGraph, START, END\n",
"from pydantic import BaseModel\n",
"\n",
"\n",
"class NestedModel(BaseModel):\n",
" value: str\n",
"\n",
"\n",
"class ComplexState(BaseModel):\n",
" text: str\n",
" count: int\n",
" nested: NestedModel\n",
"\n",
"\n",
"def process_node(state: ComplexState):\n",
" # Node receives a validated Pydantic object\n",
" print(f\"Input state type: {type(state)}\")\n",
" print(f\"Nested type: {type(state.nested)}\")\n",
"\n",
" # Return a dictionary update\n",
" return {\"text\": state.text + \" processed\", \"count\": state.count + 1}\n",
"\n",
"\n",
"# Build the graph\n",
"builder = StateGraph(ComplexState)\n",
"builder.add_node(\"process\", process_node)\n",
"builder.add_edge(START, \"process\")\n",
"builder.add_edge(\"process\", END)\n",
"graph = builder.compile()\n",
"\n",
"# Create a Pydantic instance for input\n",
"input_state = ComplexState(text=\"hello\", count=0, nested=NestedModel(value=\"test\"))\n",
"print(f\"Input object type: {type(input_state)}\")\n",
"\n",
"# Invoke graph with a Pydantic instance\n",
"result = graph.invoke(input_state)\n",
"print(f\"Output type: {type(result)}\")\n",
"print(f\"Output content: {result}\")\n",
"\n",
"# Convert back to Pydantic model if needed\n",
"output_model = ComplexState(**result)\n",
"print(f\"Converted back to Pydantic: {type(output_model)}\")"
]
},
{
"cell_type": "markdown",
"id": "f13f28ce",
"metadata": {},
"source": [
"### Runtime Type Coercion\n",
"\n",
"Pydantic performs runtime type coercion for certain data types. This can be helpful but also lead to unexpected behavior if you're not aware of it."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "faf59316",
"metadata": {},
"outputs": [],
"source": [
"from langgraph.graph import StateGraph, START, END\n",
"from pydantic import BaseModel\n",
"\n",
"\n",
"class CoercionExample(BaseModel):\n",
" # Pydantic will coerce string numbers to integers\n",
" number: int\n",
" # Pydantic will parse string booleans to bool\n",
" flag: bool\n",
"\n",
"\n",
"def inspect_node(state: CoercionExample):\n",
" print(f\"number: {state.number} (type: {type(state.number)})\")\n",
" print(f\"flag: {state.flag} (type: {type(state.flag)})\")\n",
" return {}\n",
"\n",
"\n",
"builder = StateGraph(CoercionExample)\n",
"builder.add_node(\"inspect\", inspect_node)\n",
"builder.add_edge(START, \"inspect\")\n",
"builder.add_edge(\"inspect\", END)\n",
"graph = builder.compile()\n",
"\n",
"# Demonstrate coercion with string inputs that will be converted\n",
"result = graph.invoke({\"number\": \"42\", \"flag\": \"true\"})\n",
"\n",
"# This would fail with a validation error\n",
"try:\n",
" graph.invoke({\"number\": \"not-a-number\", \"flag\": \"true\"})\n",
"except Exception as e:\n",
" print(f\"\\nExpected validation error: {e}\")"
]
},
{
"cell_type": "markdown",
"id": "2844475b",
"metadata": {},
"source": [
"### Working with Message Models\n",
"\n",
"When working with LangChain message types in your state schema, there are important considerations for serialization. You should use `AnyMessage` (rather than `BaseMessage`) for proper serialization/deserialization when using message objects over the wire:"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "bd0734b0",
"metadata": {},
"outputs": [],
"source": [
"from langgraph.graph import StateGraph, START, END\n",
"from pydantic import BaseModel\n",
"from langchain_core.messages import HumanMessage, AIMessage, AnyMessage\n",
"from typing import List\n",
"\n",
"\n",
"class ChatState(BaseModel):\n",
" messages: List[AnyMessage]\n",
" context: str\n",
"\n",
"\n",
"def add_message(state: ChatState):\n",
" return {\"messages\": state.messages + [AIMessage(content=\"Hello there!\")]}\n",
"\n",
"\n",
"builder = StateGraph(ChatState)\n",
"builder.add_node(\"add_message\", add_message)\n",
"builder.add_edge(START, \"add_message\")\n",
"builder.add_edge(\"add_message\", END)\n",
"graph = builder.compile()\n",
"\n",
"# Create input with a message\n",
"initial_state = ChatState(\n",
" messages=[HumanMessage(content=\"Hi\")], context=\"Customer support chat\"\n",
")\n",
"\n",
"result = graph.invoke(initial_state)\n",
"print(f\"Output: {result}\")\n",
"\n",
"# Convert back to Pydantic model to see message types\n",
"output_model = ChatState(**result)\n",
"for i, msg in enumerate(output_model.messages):\n",
" print(f\"Message {i}: {type(msg).__name__} - {msg.content}\")"
]
}
],
"metadata": {
-210
View File
@@ -1,210 +0,0 @@
{
"cells": [
{
"cell_type": "markdown",
"id": "3631f2b9-aa79-472e-a9d6-9125a90ee704",
"metadata": {},
"source": [
"# How to configure multiple streaming modes at the same time"
]
},
{
"cell_type": "markdown",
"id": "858c7499-0c92-40a9-bd95-e5a5a5817e92",
"metadata": {},
"source": [
"This guide covers how to configure multiple streaming modes at the same time."
]
},
{
"cell_type": "markdown",
"id": "7c2f84f1-0751-4779-97d4-5cbb286093b7",
"metadata": {},
"source": [
"## Setup\n",
"\n",
"First, let's install the required packages and set our API keys"
]
},
{
"cell_type": "code",
"execution_count": 1,
"id": "6b4285e4-7434-4971-bde0-aabceef8ee7e",
"metadata": {},
"outputs": [],
"source": [
"%%capture --no-stderr\n",
"%pip install -U langgraph langchain-openai langchain-community"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "f7f9f24a-e3d0-422b-8924-47950b2facd6",
"metadata": {},
"outputs": [],
"source": [
"import getpass\n",
"import os\n",
"\n",
"\n",
"def _set_env(var: str):\n",
" if not os.environ.get(var):\n",
" os.environ[var] = getpass.getpass(f\"{var}: \")\n",
"\n",
"\n",
"_set_env(\"OPENAI_API_KEY\")"
]
},
{
"cell_type": "markdown",
"id": "4e48aa9e",
"metadata": {},
"source": [
"<div class=\"admonition tip\">\n",
" <p class=\"admonition-title\">Set up <a href=\"https://smith.langchain.com\">LangSmith</a> for LangGraph development</p>\n",
" <p style=\"padding-top: 5px;\">\n",
" Sign up for LangSmith to quickly spot issues and improve the performance of your LangGraph projects. LangSmith lets you use trace data to debug, test, and monitor your LLM apps built with LangGraph — read more about how to get started <a href=\"https://docs.smith.langchain.com\">here</a>. \n",
" </p>\n",
"</div>"
]
},
{
"cell_type": "markdown",
"id": "cc82c21f",
"metadata": {},
"source": [
"## Define the graph\n",
"\n",
"We'll be using a simple ReAct agent for this guide."
]
},
{
"cell_type": "code",
"execution_count": 3,
"id": "85cf2e23-29f2-40cc-b302-5377b3b49da9",
"metadata": {},
"outputs": [],
"source": [
"from typing import Literal\n",
"from langchain_community.tools.tavily_search import TavilySearchResults\n",
"from langchain_core.runnables import ConfigurableField\n",
"from langchain_core.tools import tool\n",
"from langchain_openai import ChatOpenAI\n",
"from langgraph.prebuilt import create_react_agent\n",
"\n",
"\n",
"@tool\n",
"def get_weather(city: Literal[\"nyc\", \"sf\"]):\n",
" \"\"\"Use this to get weather information.\"\"\"\n",
" if city == \"nyc\":\n",
" return \"It might be cloudy in nyc\"\n",
" elif city == \"sf\":\n",
" return \"It's always sunny in sf\"\n",
" else:\n",
" raise AssertionError(\"Unknown city\")\n",
"\n",
"\n",
"tools = [get_weather]\n",
"\n",
"model = ChatOpenAI(model_name=\"gpt-4o\", temperature=0)\n",
"graph = create_react_agent(model, tools)"
]
},
{
"cell_type": "markdown",
"id": "48a7751c-3f06-452b-89f4-70267e4dd305",
"metadata": {},
"source": [
"## Stream multiple"
]
},
{
"cell_type": "code",
"execution_count": 4,
"id": "e9e9ffb0-2cd5-466f-b70b-b6ed51b852d1",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Receiving new event of type: debug...\n",
"{'type': 'task', 'timestamp': '2024-06-25T16:12:29.144117+00:00', 'step': 1, 'payload': {'id': '8399d8fd-4b28-515a-b0e9-1679557c0953', 'name': 'agent', 'input': {'messages': [HumanMessage(content=\"what's the weather in sf\", id='44ff9154-9485-49c9-b679-791314cc19e3')], 'is_last_step': False}, 'triggers': ['start:agent']}}\n",
"\n",
"\n",
"\n",
"Receiving new event of type: updates...\n",
"{'agent': {'messages': [AIMessage(content='', additional_kwargs={'tool_calls': [{'id': 'call_gZEyPpcgwnzsnee1HH4geKmB', 'function': {'arguments': '{\"city\":\"sf\"}', 'name': 'get_weather'}, 'type': 'function'}]}, response_metadata={'token_usage': {'completion_tokens': 14, 'prompt_tokens': 57, 'total_tokens': 71}, 'model_name': 'gpt-4o-2024-05-13', 'system_fingerprint': 'fp_3e7d703517', 'finish_reason': 'tool_calls', 'logprobs': None}, id='run-37ca191f-f68f-4a70-8924-a40f90c8c0ed-0', tool_calls=[{'name': 'get_weather', 'args': {'city': 'sf'}, 'id': 'call_gZEyPpcgwnzsnee1HH4geKmB'}], usage_metadata={'input_tokens': 57, 'output_tokens': 14, 'total_tokens': 71})]}}\n",
"\n",
"\n",
"\n",
"Receiving new event of type: debug...\n",
"{'type': 'task_result', 'timestamp': '2024-06-25T16:12:29.802322+00:00', 'step': 1, 'payload': {'id': '8399d8fd-4b28-515a-b0e9-1679557c0953', 'name': 'agent', 'result': [('messages', [AIMessage(content='', additional_kwargs={'tool_calls': [{'id': 'call_gZEyPpcgwnzsnee1HH4geKmB', 'function': {'arguments': '{\"city\":\"sf\"}', 'name': 'get_weather'}, 'type': 'function'}]}, response_metadata={'token_usage': {'completion_tokens': 14, 'prompt_tokens': 57, 'total_tokens': 71}, 'model_name': 'gpt-4o-2024-05-13', 'system_fingerprint': 'fp_3e7d703517', 'finish_reason': 'tool_calls', 'logprobs': None}, id='run-37ca191f-f68f-4a70-8924-a40f90c8c0ed-0', tool_calls=[{'name': 'get_weather', 'args': {'city': 'sf'}, 'id': 'call_gZEyPpcgwnzsnee1HH4geKmB'}], usage_metadata={'input_tokens': 57, 'output_tokens': 14, 'total_tokens': 71})])]}}\n",
"\n",
"\n",
"\n",
"Receiving new event of type: debug...\n",
"{'type': 'task', 'timestamp': '2024-06-25T16:12:29.802738+00:00', 'step': 2, 'payload': {'id': 'f22971bf-6eff-55a2-84ab-fb97f629b133', 'name': 'tools', 'input': {'messages': [HumanMessage(content=\"what's the weather in sf\", id='44ff9154-9485-49c9-b679-791314cc19e3'), AIMessage(content='', additional_kwargs={'tool_calls': [{'id': 'call_gZEyPpcgwnzsnee1HH4geKmB', 'function': {'arguments': '{\"city\":\"sf\"}', 'name': 'get_weather'}, 'type': 'function'}]}, response_metadata={'token_usage': {'completion_tokens': 14, 'prompt_tokens': 57, 'total_tokens': 71}, 'model_name': 'gpt-4o-2024-05-13', 'system_fingerprint': 'fp_3e7d703517', 'finish_reason': 'tool_calls', 'logprobs': None}, id='run-37ca191f-f68f-4a70-8924-a40f90c8c0ed-0', tool_calls=[{'name': 'get_weather', 'args': {'city': 'sf'}, 'id': 'call_gZEyPpcgwnzsnee1HH4geKmB'}], usage_metadata={'input_tokens': 57, 'output_tokens': 14, 'total_tokens': 71})], 'is_last_step': False}, 'triggers': ['branch:agent:should_continue:tools']}}\n",
"\n",
"\n",
"\n",
"Receiving new event of type: updates...\n",
"{'tools': {'messages': [ToolMessage(content=\"It's always sunny in sf\", name='get_weather', tool_call_id='call_gZEyPpcgwnzsnee1HH4geKmB')]}}\n",
"\n",
"\n",
"\n",
"Receiving new event of type: debug...\n",
"{'type': 'task_result', 'timestamp': '2024-06-25T16:12:29.806676+00:00', 'step': 2, 'payload': {'id': 'f22971bf-6eff-55a2-84ab-fb97f629b133', 'name': 'tools', 'result': [('messages', [ToolMessage(content=\"It's always sunny in sf\", name='get_weather', tool_call_id='call_gZEyPpcgwnzsnee1HH4geKmB')])]}}\n",
"\n",
"\n",
"\n",
"Receiving new event of type: debug...\n",
"{'type': 'task', 'timestamp': '2024-06-25T16:12:29.807014+00:00', 'step': 3, 'payload': {'id': '3e1a91b9-b94c-56a7-ace5-6fd8ee73fe8d', 'name': 'agent', 'input': {'messages': [HumanMessage(content=\"what's the weather in sf\", id='44ff9154-9485-49c9-b679-791314cc19e3'), AIMessage(content='', additional_kwargs={'tool_calls': [{'id': 'call_gZEyPpcgwnzsnee1HH4geKmB', 'function': {'arguments': '{\"city\":\"sf\"}', 'name': 'get_weather'}, 'type': 'function'}]}, response_metadata={'token_usage': {'completion_tokens': 14, 'prompt_tokens': 57, 'total_tokens': 71}, 'model_name': 'gpt-4o-2024-05-13', 'system_fingerprint': 'fp_3e7d703517', 'finish_reason': 'tool_calls', 'logprobs': None}, id='run-37ca191f-f68f-4a70-8924-a40f90c8c0ed-0', tool_calls=[{'name': 'get_weather', 'args': {'city': 'sf'}, 'id': 'call_gZEyPpcgwnzsnee1HH4geKmB'}], usage_metadata={'input_tokens': 57, 'output_tokens': 14, 'total_tokens': 71}), ToolMessage(content=\"It's always sunny in sf\", name='get_weather', id='afc3ceaa-6663-4f7a-b874-e77e5515b175', tool_call_id='call_gZEyPpcgwnzsnee1HH4geKmB')], 'is_last_step': False}, 'triggers': ['tools']}}\n",
"\n",
"\n",
"\n",
"Receiving new event of type: updates...\n",
"{'agent': {'messages': [AIMessage(content='The weather in San Francisco is currently sunny.', response_metadata={'token_usage': {'completion_tokens': 10, 'prompt_tokens': 84, 'total_tokens': 94}, 'model_name': 'gpt-4o-2024-05-13', 'system_fingerprint': 'fp_3e7d703517', 'finish_reason': 'stop', 'logprobs': None}, id='run-575efeca-fdeb-4b4f-80f8-08ff177c34a5-0', usage_metadata={'input_tokens': 84, 'output_tokens': 10, 'total_tokens': 94})]}}\n",
"\n",
"\n",
"\n",
"Receiving new event of type: debug...\n",
"{'type': 'task_result', 'timestamp': '2024-06-25T16:12:30.355658+00:00', 'step': 3, 'payload': {'id': '3e1a91b9-b94c-56a7-ace5-6fd8ee73fe8d', 'name': 'agent', 'result': [('messages', [AIMessage(content='The weather in San Francisco is currently sunny.', response_metadata={'token_usage': {'completion_tokens': 10, 'prompt_tokens': 84, 'total_tokens': 94}, 'model_name': 'gpt-4o-2024-05-13', 'system_fingerprint': 'fp_3e7d703517', 'finish_reason': 'stop', 'logprobs': None}, id='run-575efeca-fdeb-4b4f-80f8-08ff177c34a5-0', usage_metadata={'input_tokens': 84, 'output_tokens': 10, 'total_tokens': 94})])]}}\n",
"\n",
"\n",
"\n"
]
}
],
"source": [
"inputs = {\"messages\": [(\"human\", \"what's the weather in sf\")]}\n",
"async for event, chunk in graph.astream(inputs, stream_mode=[\"updates\", \"debug\"]):\n",
" print(f\"Receiving new event of type: {event}...\")\n",
" print(chunk)\n",
" print(\"\\n\\n\")"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3 (ipykernel)",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.11.9"
}
},
"nbformat": 4,
"nbformat_minor": 5
}
+102
View File
@@ -0,0 +1,102 @@
# How to add TTLs to your LangGraph application
!!! tip "Prerequisites"
This guide assumes familiarity with the [LangGraph Platform](../../concepts/index.md#langgraph-platform), [Persistence](../../concepts/persistence.md), and [Cross-thread persistence](../../concepts/persistence.md#memory-store) concepts.
???+ note "LangGraph platform only"
TTLs are only supported for LangGraph platform deployments. This guide does not apply to LangGraph OSS.
The LangGraph Platform persists both [checkpoints](../../concepts/persistence.md#checkpoints) (thread state) and [cross-thread memories](../../concepts/persistence.md#memory-store) (store items). Configure Time-to-Live (TTL) policies in `langgraph.json` to automatically manage the lifecycle of this data, preventing indefinite accumulation.
## Configuring Checkpoint TTL
Checkpoints capture the state of conversation threads. Setting a TTL ensures old checkpoints and threads are automatically deleted.
Add a `checkpointer.ttl` configuration to your `langgraph.json` file:
```json
{
"dependencies": ["."],
"graphs": {
"agent": "./agent.py:graph"
},
"checkpointer": {
"ttl": {
"strategy": "delete",
"sweep_interval_minutes": 60,
"default_ttl": 43200
}
}
}
```
* `strategy`: Specifies the action taken on expiration. Currently, only `"delete"` is supported, which deletes all checkpoints in the thread upon expiration.
* `sweep_interval_minutes`: Defines how often, in minutes, the system checks for expired checkpoints.
* `default_ttl`: Sets the default lifespan of checkpoints in minutes (e.g., 43200 minutes = 30 days).
## Configuring Store Item TTL
Store items allow cross-thread data persistence. Configuring TTL for store items helps manage memory by removing stale data.
Add a `store.ttl` configuration to your `langgraph.json` file:
```json
{
"dependencies": ["."],
"graphs": {
"agent": "./agent.py:graph"
},
"store": {
"ttl": {
"refresh_on_read": true,
"sweep_interval_minutes": 120,
"default_ttl": 10080
}
}
}
```
* `refresh_on_read`: (Optional, default `true`) If `true`, accessing an item via `get` or `search` resets its expiration timer. If `false`, TTL only refreshes on `put`.
* `sweep_interval_minutes`: (Optional) Defines how often, in minutes, the system checks for expired items. If omitted, no sweeping occurs.
* `default_ttl`: (Optional) Sets the default lifespan of store items in minutes (e.g., 10080 minutes = 7 days). If omitted, items do not expire by default.
## Combining TTL Configurations
You can configure TTLs for both checkpoints and store items in the same `langgraph.json` file to set different policies for each data type. Here is an example:
```json
{
"dependencies": ["."],
"graphs": {
"agent": "./agent.py:graph"
},
"checkpointer": {
"ttl": {
"strategy": "delete",
"sweep_interval_minutes": 60,
"default_ttl": 43200
}
},
"store": {
"ttl": {
"refresh_on_read": true,
"sweep_interval_minutes": 120,
"default_ttl": 10080
}
}
}
```
## Runtime Overrides
The default `store.ttl` settings from `langgraph.json` can be overridden at runtime by providing specific TTL values in SDK method calls like `get`, `put`, and `search`.
## Deployment Process
After configuring TTLs in `langgraph.json`, deploy or restart your LangGraph application for the changes to take effect. Use `langgraph dev` for local development or `langgraph up` for Docker deployment.
See the [langgraph.json CLI reference][configuration-file] for more details on the other configurable options.

Some files were not shown because too many files have changed in this diff Show More