Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
05f21a384b | ||
|
|
29e9ee2d7b | ||
|
|
173627a94c | ||
|
|
edd7d608cd | ||
|
|
8977a35060 | ||
|
|
0a6e5a18bb | ||
|
|
71bf2f9e85 | ||
|
|
b03c647677 | ||
|
|
5d49188d3e | ||
|
|
deeb2d6e92 | ||
|
|
0db67d4196 | ||
|
|
56c9c210c3 | ||
|
|
3398715258 | ||
|
|
38d806733d | ||
|
|
86ddd8da10 | ||
|
|
a5f5d0c4df | ||
|
|
cba7d21732 | ||
|
|
b6ea73ff24 | ||
|
|
1a477e57ff | ||
|
|
7486adabdf | ||
|
|
12ad47e4e8 | ||
|
|
90f7f776cf | ||
|
|
c7306f7aed | ||
|
|
20bd71e289 | ||
|
|
283485753f | ||
|
|
ba7f9975fa | ||
|
|
8c4904bee9 | ||
|
|
6bb06b8702 | ||
|
|
7a16e33833 | ||
|
|
3da5c73a04 | ||
|
|
e818f83a92 | ||
|
|
e478a8deb9 | ||
|
|
4bbdfbf381 | ||
|
|
db1fbe74cc | ||
|
|
01ce86ad9b | ||
|
|
d5f73fe37b | ||
|
|
5a200cd89e | ||
|
|
6082bcf8d3 | ||
|
|
18a9ae45f3 | ||
|
|
83bf004ad7 | ||
|
|
72114c6c33 | ||
|
|
88b57df15b | ||
|
|
abfb88e5d7 | ||
|
|
49f063e076 | ||
|
|
30f9bcd8de | ||
|
|
6ee112851c | ||
|
|
960f612dd7 | ||
|
|
43af618bb5 | ||
|
|
9b87b45322 | ||
|
|
39adc05357 | ||
|
|
c5ac80d2f0 | ||
|
|
2fc941c1df | ||
|
|
7bafc5dd36 | ||
|
|
c78588b995 | ||
|
|
ecb15acb80 | ||
|
|
07ba931105 | ||
|
|
88ccde6274 | ||
|
|
5cca153b72 | ||
|
|
63ebb3a846 | ||
|
|
48c08421fa | ||
|
|
cd967c40ac | ||
|
|
854b76addd | ||
|
|
73b3535c4d | ||
|
|
3e0629c56c | ||
|
|
04dd69b1cd | ||
|
|
ff22eb6495 | ||
|
|
07ca03ff15 | ||
|
|
6eea15ec3b | ||
|
|
0e111b2f44 | ||
|
|
b526fe0a4b | ||
|
|
062bf4d717 | ||
|
|
173f4f6ccf | ||
|
|
9a45a5b0f2 | ||
|
|
2c557e9e46 | ||
|
|
6c34e599ab | ||
|
|
d4224a7abb | ||
|
|
c700dab97c | ||
|
|
704b78b8fe | ||
|
|
2ed453debe | ||
|
|
62b2580ad5 | ||
|
|
dfbf0ddbcb | ||
|
|
41bb20ee5e | ||
|
|
560d6a1f65 | ||
|
|
dc6fa9ed30 | ||
|
|
a9be75f745 | ||
|
|
20e3469296 | ||
|
|
233cca1357 | ||
|
|
d1ac0a0e13 | ||
|
|
5071a6cd97 | ||
|
|
72d7b23638 | ||
|
|
64aa1e6cd8 | ||
|
|
d6f2f0c90d | ||
|
|
5a7edead8c | ||
|
|
8ff5c43cf0 | ||
|
|
0eb32a4251 | ||
|
|
3d12a2df59 | ||
|
|
04d3c9d30f | ||
|
|
cddcf35c09 | ||
|
|
5eefc1d55d | ||
|
|
c9d4f1d77d | ||
|
|
1e2888ce39 | ||
|
|
4d1b3370df | ||
|
|
bf5017f6e0 | ||
|
|
64086aa814 | ||
|
|
2a7d48582f | ||
|
|
b7bd87a063 | ||
|
|
2a825cc0e0 | ||
|
|
436902e5a3 | ||
|
|
0ac6a96c6e | ||
|
|
d9856d92af | ||
|
|
b3487cbc49 | ||
|
|
d06075cbcf | ||
|
|
e0be9ae2ef | ||
|
|
19cfe3a0a9 | ||
|
|
99a87abaa5 | ||
|
|
a03cb0b16d | ||
|
|
4be86b2a51 | ||
|
|
06e660a845 | ||
|
|
794dc1ae92 | ||
|
|
6e7bfecbbc | ||
|
|
fa080ea689 | ||
|
|
9fb06fc5af | ||
|
|
5debbb23ca | ||
|
|
7dcc760fd8 | ||
|
|
fdb9b9b8e0 | ||
|
|
2f51a15064 | ||
|
|
d2acacfc8f | ||
|
|
622a15b89e | ||
|
|
bf50938de5 | ||
|
|
d67a500cd9 | ||
|
|
c6f5e561ec | ||
|
|
288fe12933 | ||
|
|
5b58efc8d7 | ||
|
|
2e1e582991 | ||
|
|
72260e64d5 | ||
|
|
3193f5d063 | ||
|
|
1b9093459c | ||
|
|
392805938e | ||
|
|
4fb2aeacc7 | ||
|
|
8252668bcc | ||
|
|
27e4b0fcfe | ||
|
|
ba388e25b3 | ||
|
|
947a233fc5 | ||
|
|
b76dc8ae0a | ||
|
|
cbbfaba1fd | ||
|
|
e9aec77893 | ||
|
|
44691b69a3 | ||
|
|
067c4dd246 | ||
|
|
ccc21974e0 | ||
|
|
a6e66746f7 | ||
|
|
3a17df6106 | ||
|
|
52c2837e42 | ||
|
|
cee6a450dc | ||
|
|
0b3bf37a55 | ||
|
|
305a676675 | ||
|
|
5b73e38c38 | ||
|
|
41fb5ec77c | ||
|
|
cff349e22e | ||
|
|
8f32fc4819 | ||
|
|
5690555394 | ||
|
|
933d6aa8f5 | ||
|
|
7d5621a84f | ||
|
|
5f1213a1c7 | ||
|
|
a98f9542fa | ||
|
|
d2e854b04f | ||
|
|
c5b118a672 | ||
|
|
aee39605e0 | ||
|
|
72bec9161a | ||
|
|
ae17e77522 | ||
|
|
a96fc75c55 | ||
|
|
d541ed90d5 | ||
|
|
7d7708fe42 | ||
|
|
c757247858 | ||
|
|
5a0228cb13 | ||
|
|
4abfc7702d | ||
|
|
a5495e84c8 | ||
|
|
4f353dac31 | ||
|
|
4c89bb39d4 | ||
|
|
05a4fcc8bb | ||
|
|
7ebd6f5e1f | ||
|
|
adac016e33 | ||
|
|
0a1dd7a01a | ||
|
|
7e08339335 | ||
|
|
e1d4b5552d | ||
|
|
2d13904abf | ||
|
|
dfeb9d3b46 | ||
|
|
81935a73d8 | ||
|
|
615fc8b4ae | ||
|
|
13e6f6cbde | ||
|
|
e89633f30b | ||
|
|
0bbf5829e8 | ||
|
|
7ed5288f8f | ||
|
|
cba240e70e | ||
|
|
e9b5046076 | ||
|
|
af6552a17e | ||
|
|
e38c30a434 | ||
|
|
e41dea4cf9 | ||
|
|
f9f8c19ec4 | ||
|
|
64ab3217f6 | ||
|
|
9af243d138 | ||
|
|
3f1d440aee | ||
|
|
78901599e6 | ||
|
|
958c0df2d7 | ||
|
|
6919de8b3e | ||
|
|
e9a66cef46 | ||
|
|
728679e48e | ||
|
|
f90c81f280 | ||
|
|
f118a61101 | ||
|
|
8963bb2b68 | ||
|
|
499a1812e8 | ||
|
|
2cb81201b2 | ||
|
|
494cd4f6ad | ||
|
|
9226b42150 | ||
|
|
5e0a843423 | ||
|
|
6e54f74fa9 | ||
|
|
ffb8400b19 | ||
|
|
b6b40149a9 | ||
|
|
5eecd2ac3a | ||
|
|
c38f7be89c | ||
|
|
2d406f03a2 | ||
|
|
1c48ec0aba | ||
|
|
4dda404da3 | ||
|
|
cce9801a8b | ||
|
|
67e8f8fc11 | ||
|
|
3a9247728b | ||
|
|
33766eb2ff | ||
|
|
6fe319ed1b | ||
|
|
3878addbe0 | ||
|
|
55f922cf2f | ||
|
|
9a5dc5d8f2 | ||
|
|
90b3da5959 | ||
|
|
d2275a6727 | ||
|
|
0c590afb27 | ||
|
|
6efeefe424 | ||
|
|
da8b8c606a | ||
|
|
dcda8c24d6 | ||
|
|
e3d697620b | ||
|
|
30883729f0 | ||
|
|
1c403f34c8 | ||
|
|
9bd78ed483 | ||
|
|
a77db7d73d | ||
|
|
e85b7e6cd9 | ||
|
|
94fa46f9fa | ||
|
|
e50110ba91 | ||
|
|
fd64ada9de | ||
|
|
b15ec09c3b | ||
|
|
5e9e7b79fe | ||
|
|
c49a077789 | ||
|
|
881b07cf7f | ||
|
|
0425d4e65d | ||
|
|
118016a21c | ||
|
|
bda3c3add9 | ||
|
|
067b99c789 | ||
|
|
aef463c633 | ||
|
|
673cc5ad1a | ||
|
|
e9e9a96a0d | ||
|
|
cf7136297e | ||
|
|
e5aae80e3a | ||
|
|
f629f68ec3 | ||
|
|
575de221fe | ||
|
|
d2fc5f0a0f | ||
|
|
8e4b8b11ff | ||
|
|
2808a7859a | ||
|
|
fb3c61ea4f | ||
|
|
69cecd872c | ||
|
|
9abc1c8174 | ||
|
|
de90ced29d | ||
|
|
b8b973fc0c | ||
|
|
89e3709a2a | ||
|
|
a7f012a19c | ||
|
|
9b05ab6453 | ||
|
|
5401d2ea81 | ||
|
|
4401612aa6 | ||
|
|
49bb08a3f9 | ||
|
|
4f2e9b838f | ||
|
|
d30da72f6e | ||
|
|
7f079adfee | ||
|
|
4c74af606f | ||
|
|
900824089b | ||
|
|
522caa643f | ||
|
|
ef71656f05 | ||
|
|
3ba7c7fbed | ||
|
|
5cdab86d48 | ||
|
|
f5fe7e5195 | ||
|
|
2b728410e9 | ||
|
|
30221da4a8 | ||
|
|
1c5a354a7d | ||
|
|
bfd271e00e | ||
|
|
9647b1e55f | ||
|
|
e4aa204110 | ||
|
|
2c29edadec | ||
|
|
96847e644b | ||
|
|
4b102638c2 | ||
|
|
7021ce3742 | ||
|
|
d0c0aa9697 | ||
|
|
520de30350 | ||
|
|
81c0d47363 | ||
|
|
87603d8a00 | ||
|
|
7ad7329c7d | ||
|
|
e981d27f84 | ||
|
|
71db4f2ad5 | ||
|
|
4ced277e2d | ||
|
|
34738fa566 | ||
|
|
0286c38784 | ||
|
|
fb5a1c4028 | ||
|
|
39d85466f8 | ||
|
|
3c797529bb | ||
|
|
0d185d43ed | ||
|
|
70b8391a89 | ||
|
|
1a37f2d5a2 | ||
|
|
949af8abe5 | ||
|
|
094255c3fe | ||
|
|
b6055ff3fe | ||
|
|
e082ba4f85 | ||
|
|
f36b7f61fb | ||
|
|
4095f0a927 | ||
|
|
8af09714ff | ||
|
|
5d7e818882 | ||
|
|
37429ff73b | ||
|
|
af7515c37a | ||
|
|
b97cda4290 | ||
|
|
01fed0fae2 | ||
|
|
2ac22f8246 | ||
|
|
ae2e8d7e5e | ||
|
|
5526486a0b | ||
|
|
0f8fc4fe68 | ||
|
|
10859da99a | ||
|
|
b285a118a7 | ||
|
|
6853d045b6 | ||
|
|
d8cc9c9680 | ||
|
|
723d6f8a84 | ||
|
|
696a922241 | ||
|
|
c598fee7d6 | ||
|
|
6da6c4443a | ||
|
|
2ee5b8e9d1 | ||
|
|
aadbcb443a | ||
|
|
a88794b74e | ||
|
|
556733c77c | ||
|
|
3d16acf3f5 | ||
|
|
ad63b730b3 | ||
|
|
dd733a3389 |
@@ -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
|
||||
|
||||
@@ -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 check --lock
|
||||
|
||||
- name: Install dependencies
|
||||
if: steps.changed-files.outputs.all
|
||||
# Also installs dev/lint/test/typing dependencies, to ensure we have
|
||||
|
||||
@@ -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:
|
||||
@@ -39,12 +39,6 @@ jobs:
|
||||
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||
password: ${{ secrets.DOCKERHUB_RO_TOKEN }}
|
||||
|
||||
- name: Check Lock
|
||||
shell: bash
|
||||
working-directory: ${{ inputs.working-directory }}
|
||||
run: |
|
||||
poetry check --lock
|
||||
|
||||
- name: Install dependencies
|
||||
shell: bash
|
||||
working-directory: ${{ inputs.working-directory }}
|
||||
|
||||
@@ -4,7 +4,7 @@ on:
|
||||
workflow_call:
|
||||
|
||||
env:
|
||||
POETRY_VERSION: "1.7.1"
|
||||
POETRY_VERSION: "2.1.2"
|
||||
|
||||
jobs:
|
||||
build:
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -4,7 +4,7 @@ on:
|
||||
workflow_call:
|
||||
|
||||
env:
|
||||
POETRY_VERSION: "1.7.1"
|
||||
POETRY_VERSION: "2.1.2"
|
||||
|
||||
jobs:
|
||||
build:
|
||||
|
||||
@@ -8,7 +8,7 @@ on:
|
||||
- "libs/**"
|
||||
|
||||
env:
|
||||
POETRY_VERSION: "1.7.1"
|
||||
POETRY_VERSION: "2.1.2"
|
||||
|
||||
jobs:
|
||||
benchmark:
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -17,7 +17,7 @@ concurrency:
|
||||
cancel-in-progress: true
|
||||
|
||||
env:
|
||||
POETRY_VERSION: "1.7.1"
|
||||
POETRY_VERSION: "2.1.2"
|
||||
|
||||
jobs:
|
||||
changes:
|
||||
|
||||
@@ -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
|
||||
@@ -118,7 +99,7 @@ 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/.*" \
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -10,7 +10,7 @@ on:
|
||||
|
||||
env:
|
||||
PYTHON_VERSION: "3.11"
|
||||
POETRY_VERSION: "1.7.1"
|
||||
POETRY_VERSION: "2.1.2"
|
||||
|
||||
jobs:
|
||||
build:
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -40,6 +40,9 @@ agent.invoke(
|
||||
)
|
||||
```
|
||||
|
||||
> [!TIP]
|
||||
> Check out [this guide](https://langchain-ai.github.io/langgraph/tutorials/workflows/) that walks through implementing common patterns (workflows and agents) in LangGraph.
|
||||
|
||||
## Why use LangGraph?
|
||||
|
||||
LangGraph is built for developers who want to build powerful, adaptable AI agents. Developers choose LangGraph for:
|
||||
|
||||
@@ -19,7 +19,7 @@ build-prebuilt:
|
||||
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
|
||||
poetry run python -m _scripts.third_party_page.create_third_party_page stats.yml docs/agents/prebuilt.md --language python
|
||||
|
||||
build-docs: build-typedoc build-prebuilt
|
||||
poetry run python -m mkdocs build --clean -f mkdocs.yml --strict
|
||||
|
||||
@@ -45,6 +45,8 @@ MANUAL_API_REFERENCES_LANGGRAPH = [
|
||||
(["langgraph.constants"], "langgraph.types", "Interrupt", "types"),
|
||||
(["langgraph.constants"], "langgraph.types", "interrupt", "types"),
|
||||
(["langgraph.constants"], "langgraph.types", "Command", "types"),
|
||||
(["langgraph.config"], "langgraph.config", "get_stream_writer", "config"),
|
||||
(["langgraph.config"], "langgraph.config", "get_store", "config"),
|
||||
(["langgraph.func"], "langgraph.func", "entrypoint", "func"),
|
||||
(["langgraph.func"], "langgraph.func", "task", "func"),
|
||||
(["langgraph.types"], "langgraph.types", "RetryPolicy", "types"),
|
||||
@@ -56,6 +58,7 @@ MANUAL_API_REFERENCES_LANGGRAPH = [
|
||||
([], "langgraph.checkpoint.base", "SerializerProtocol", "checkpoints"),
|
||||
([], "langgraph.checkpoint.serde.jsonplus", "JsonPlusSerializer", "checkpoints"),
|
||||
([], "langgraph.checkpoint.memory", "MemorySaver", "checkpoints"),
|
||||
([], "langgraph.checkpoint.memory", "InMemorySaver", "checkpoints"),
|
||||
([], "langgraph.checkpoint.sqlite.aio", "AsyncSqliteSaver", "checkpoints"),
|
||||
([], "langgraph.checkpoint.sqlite", "SqliteSaver", "checkpoints"),
|
||||
([], "langgraph.checkpoint.postgres.aio", "AsyncPostgresSaver", "checkpoints"),
|
||||
@@ -214,7 +217,7 @@ def update_markdown_with_imports(markdown: str, path: str) -> str:
|
||||
path: The path of the file where the markdown content originated.
|
||||
|
||||
Returns:
|
||||
Updated markdown with API reference links appended to Python code blocks.
|
||||
Updated markdown with API reference links prepended to Python code blocks.
|
||||
|
||||
Example:
|
||||
Given a markdown with a Python code block:
|
||||
@@ -237,7 +240,7 @@ def update_markdown_with_imports(markdown: str, path: str) -> str:
|
||||
match (re.Match): The regex match object containing the code block.
|
||||
|
||||
Returns:
|
||||
str: The modified code block with API reference links appended if applicable.
|
||||
str: The modified code block with API reference links prepended if applicable.
|
||||
"""
|
||||
indent = match.group("indent")
|
||||
code_block = match.group("code")
|
||||
@@ -253,8 +256,8 @@ def update_markdown_with_imports(markdown: str, path: str) -> str:
|
||||
api_links = " | ".join(
|
||||
f'<a href="{imp["docs"]}">{imp["imported"]}</a>' for imp in imports
|
||||
)
|
||||
# Return the code block with appended API reference links
|
||||
return f"{original_code_block}\n\n{indent}API Reference: {api_links}"
|
||||
# Return the code block with prepended API reference links
|
||||
return f"{indent}API Reference: {api_links}\n\n{original_code_block}"
|
||||
|
||||
# Apply the replace_code_block function to all matches in the markdown
|
||||
updated_markdown = code_block_pattern.sub(replace_code_block, markdown)
|
||||
|
||||
@@ -31,6 +31,8 @@ REDIRECT_MAP = {
|
||||
"cloud/concepts/api.md": "concepts/langgraph_server.md",
|
||||
"cloud/concepts/cloud.md": "concepts/langgraph_cloud.md",
|
||||
"cloud/faq/studio.md": "concepts/langgraph_studio.md#studio-faqs",
|
||||
# misc
|
||||
"prebuilt.md": "agents/prebuilt.md"
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -20,7 +20,6 @@ BLOCKLIST_COMMANDS = (
|
||||
|
||||
NOTEBOOKS_NO_CASSETTES = (
|
||||
"docs/how-tos/visualization.ipynb",
|
||||
"docs/how-tos/many-tools.ipynb"
|
||||
)
|
||||
|
||||
NOTEBOOKS_NO_EXECUTION = [
|
||||
@@ -49,7 +48,10 @@ NOTEBOOKS_NO_EXECUTION = [
|
||||
"docs/how-tos/map-reduce.ipynb", # flakiness from structured output, only when running with VCR
|
||||
"docs/tutorials/tot/tot.ipynb",
|
||||
"docs/how-tos/visualization.ipynb",
|
||||
"docs/tutorials/llm-compiler/LLMCompiler.ipynb"
|
||||
"docs/how-tos/streaming-specific-nodes.ipynb",
|
||||
"docs/tutorials/llm-compiler/LLMCompiler.ipynb",
|
||||
"docs/tutorials/customer-support/customer-support.ipynb", # relies on openai embeddings, doesn't play well w/ VCR
|
||||
"docs/how-tos/many-tools.ipynb", # relies on openai embeddings, doesn't play well w/ VCR
|
||||
]
|
||||
|
||||
|
||||
@@ -86,6 +88,12 @@ def has_blocklisted_command(code: str, metadata: dict) -> bool:
|
||||
return True
|
||||
return False
|
||||
|
||||
def add_mermaid_retries(code: str) -> str:
|
||||
return code.replace(
|
||||
"draw_mermaid_png()",
|
||||
"draw_mermaid_png(max_retries=10, retry_delay=2.0)"
|
||||
)
|
||||
|
||||
|
||||
def add_vcr_to_notebook(
|
||||
notebook: nbformat.NotebookNode, cassette_prefix: str
|
||||
@@ -180,6 +188,15 @@ def add_vcr_to_notebook(
|
||||
return notebook
|
||||
|
||||
|
||||
def add_mermaid_retries_to_notebook(notebook: nbformat.NotebookNode) -> nbformat.NotebookNode:
|
||||
for cell in notebook.cells:
|
||||
if cell.cell_type != "code":
|
||||
continue
|
||||
|
||||
cell.source = add_mermaid_retries(cell.source)
|
||||
return notebook
|
||||
|
||||
|
||||
def process_notebooks(should_comment_install_cells: bool) -> None:
|
||||
for directory in NOTEBOOK_DIRS:
|
||||
for root, _, files in os.walk(directory):
|
||||
@@ -201,6 +218,8 @@ def process_notebooks(should_comment_install_cells: bool) -> None:
|
||||
notebook, cassette_prefix=cassette_prefix
|
||||
)
|
||||
|
||||
notebook = add_mermaid_retries_to_notebook(notebook)
|
||||
|
||||
if notebook_path in NOTEBOOKS_NO_EXECUTION:
|
||||
# Add a cell at the beginning to indicate that this notebook should not be executed
|
||||
warning_cell = nbformat.v4.new_markdown_cell(
|
||||
|
||||
@@ -9,10 +9,7 @@ import yaml
|
||||
|
||||
MARKDOWN = """\
|
||||
[//]: # (This file is automatically generated using a script in docs/_scripts. Do not edit this file directly!)
|
||||
# 🚀 Prebuilt Agents
|
||||
|
||||
LangGraph includes a prebuilt React agent. For more information on how to use it,
|
||||
check out our [how-to guides](https://langchain-ai.github.io/langgraph/how-tos/#prebuilt-react-agent).
|
||||
# Community Agents
|
||||
|
||||
If you’re looking for other prebuilt libraries, explore the community-built options
|
||||
below. These libraries can extend LangGraph's functionality in various ways.
|
||||
|
||||
@@ -36,6 +36,6 @@ packages:
|
||||
- name: "langgraph-reflection"
|
||||
repo: "langchain-ai/langgraph-reflection"
|
||||
description: "LangGraph agent that runs a reflection step."
|
||||
- name: "langmanus"
|
||||
repo: "langmanus/langmanus"
|
||||
description: "A community-driven AI automation framework that builds upon the incredible work of the open source community. Our goal is to combine language models with specialized tools for tasks like web search, crawling, and Python code execution, while giving back to the community that made this possible."
|
||||
- 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==
|
||||
@@ -10,14 +10,17 @@ This list of companies using LangGraph and their success stories is compiled fro
|
||||
| [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/) |
|
||||
@@ -25,3 +28,4 @@ This list of companies using LangGraph and their success stories is compiled fro
|
||||
| [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/) |
|
||||
| [Vodafone](https://www.vodafone.com/) | Telecommunications | Code generation; internal search | [Case study, 2025](https://blog.langchain.dev/customers-vodafone/) |
|
||||
|
||||
@@ -0,0 +1,209 @@
|
||||
# Agents
|
||||
|
||||
## What is an agent?
|
||||
|
||||
An *agent* consists of three components: a **large language model (LLM)**, a set of **tools** it can use, and a **prompt** that provides instructions.
|
||||
|
||||
The LLM operates in a loop. In each iteration, it selects a tool to invoke, provides input, receives the result (an observation), and uses that observation to inform the next action. The loop continues until a stopping condition is met — typically when the agent has gathered enough information to respond to the user.
|
||||
|
||||
<figure markdown="1">
|
||||
{: style="max-height:400px"}
|
||||
<figcaption>Agent loop: the LLM selects tools and uses their outputs to fulfill a user request.</figcaption>
|
||||
</figure>
|
||||
|
||||
## Basic configuration
|
||||
|
||||
Use [`create_react_agent`](https://python.langchain.com/docs/api_reference/langgraph.prebuilt.chat_agent_executor/#create-react-agent) to instantiate an agent:
|
||||
|
||||
```python
|
||||
from langgraph.prebuilt import create_react_agent
|
||||
|
||||
def get_weather(city: str) -> str: # (1)!
|
||||
"""Get weather for a given city."""
|
||||
return f"It's always sunny in {city}!"
|
||||
|
||||
agent = create_react_agent(
|
||||
model="anthropic:claude-3-7-sonnet-latest", # (2)!
|
||||
tools=[get_weather], # (3)!
|
||||
prompt="You are a helpful assistant" # (4)!
|
||||
)
|
||||
|
||||
# Run the agent
|
||||
agent.invoke(
|
||||
{"messages": [{"role": "user", "content": "what is the weather in sf"}]}
|
||||
)
|
||||
```
|
||||
|
||||
1. Define a tool for the agent to use. Tools can be defined as vanilla Python functions. For more advanced tool usage and customization, check the [tools](./tools.md) page.
|
||||
2. Provide a language model for the agent to use. To learn more about configuring language models for the agents, check the [models](./models.md) page.
|
||||
3. Provide a list of tools for the model to use.
|
||||
4. Provide a system prompt (instructions) to the language model used by the agent.
|
||||
|
||||
## LLM configuration
|
||||
|
||||
Use [init_chat_model](https://python.langchain.com/api_reference/langchain/chat_models/langchain.chat_models.base.init_chat_model.html) to configure an LLM with specific parameters,
|
||||
such as temperature:
|
||||
|
||||
```python
|
||||
from langchain.chat_models import init_chat_model
|
||||
from langgraph.prebuilt import create_react_agent
|
||||
|
||||
# highlight-next-line
|
||||
model = init_chat_model(
|
||||
"anthropic:claude-3-7-sonnet-latest",
|
||||
# highlight-next-line
|
||||
temperature=0
|
||||
)
|
||||
|
||||
agent = create_react_agent(
|
||||
# highlight-next-line
|
||||
model=model,
|
||||
tools=[get_weather],
|
||||
)
|
||||
```
|
||||
|
||||
See the [models](./models.md) page for more information on how to configure LLMs.
|
||||
|
||||
## Custom Prompts
|
||||
|
||||
Prompts instruct the LLM how to behave. They can be:
|
||||
|
||||
* **Static**: A string is interpreted as a **system message**
|
||||
* **Dynamic**: a list of messages generated at **runtime** based on input or configuration
|
||||
|
||||
### Static prompts
|
||||
|
||||
Define a fixed prompt string or list of messages.
|
||||
|
||||
```python
|
||||
from langgraph.prebuilt import create_react_agent
|
||||
|
||||
agent = create_react_agent(
|
||||
model="anthropic:claude-3-7-sonnet-latest",
|
||||
tools=[get_weather],
|
||||
# A static prompt that never changes
|
||||
# highlight-next-line
|
||||
prompt="Never answer questions about the weather."
|
||||
)
|
||||
|
||||
agent.invoke(
|
||||
{"messages": [{"role": "user", "content": "what is the weather in sf"}]}
|
||||
)
|
||||
```
|
||||
|
||||
### Dynamic prompts
|
||||
|
||||
Define a function that returns a message list based on the agent's state and configuration:
|
||||
|
||||
```python
|
||||
from langchain_core.messages import AnyMessage
|
||||
from langchain_core.runnables import RunnableConfig
|
||||
from langgraph.prebuilt.chat_agent_executor import AgentState
|
||||
from langgraph.prebuilt import create_react_agent
|
||||
|
||||
# highlight-next-line
|
||||
def prompt(state: AgentState, config: RunnableConfig) -> list[AnyMessage]: # (1)!
|
||||
user_name = config.get("configurable", {}).get("user_name")
|
||||
system_msg = f"You are a helpful assistant. Address the user as {user_name}."
|
||||
return [{"role": "system", "content": system_msg}] + state["messages"]
|
||||
|
||||
agent = create_react_agent(
|
||||
model="anthropic:claude-3-7-sonnet-latest",
|
||||
tools=[get_weather],
|
||||
# highlight-next-line
|
||||
prompt=prompt
|
||||
)
|
||||
|
||||
agent.invoke(
|
||||
{"messages": [{"role": "user", "content": "what is the weather in sf"}]},
|
||||
# highlight-next-line
|
||||
config={"configurable": {"user_name": "John Smith"}}
|
||||
)
|
||||
```
|
||||
|
||||
1. Dynamic prompts allow including non-message [context](./context.md) when constructing an input to the LLM, such as:
|
||||
|
||||
- Information passed at runtime, like a `user_id` or API credentials (using `config`).
|
||||
- Internal agent state updated during a multi-step reasoning process (using `state`).
|
||||
|
||||
Dynamic prompts can be defined as functions that take `state` and `config` and return a list of messages to send to the LLM.
|
||||
|
||||
See the [context](./context.md) page for more information.
|
||||
|
||||
## Memory
|
||||
|
||||
To allow multi-turn conversations with an agent, you need to enable [persistence](../concepts/persistence.md) by providing a `checkpointer` when creating an agent. At runtime you need to provide a config containing `thread_id` — a unique identifier for the conversation (session):
|
||||
|
||||
```python
|
||||
from langgraph.prebuilt import create_react_agent
|
||||
from langgraph.checkpoint.memory import InMemorySaver
|
||||
|
||||
# highlight-next-line
|
||||
checkpointer = InMemorySaver()
|
||||
|
||||
agent = create_react_agent(
|
||||
model="anthropic:claude-3-7-sonnet-latest",
|
||||
tools=[get_weather],
|
||||
# highlight-next-line
|
||||
checkpointer=checkpointer # (1)!
|
||||
)
|
||||
|
||||
# Run the agent
|
||||
# highlight-next-line
|
||||
config = {"configurable": {"thread_id": "1"}}
|
||||
sf_response = agent.invoke(
|
||||
{"messages": [{"role": "user", "content": "what is the weather in sf"}]},
|
||||
# highlight-next-line
|
||||
config # (2)!
|
||||
)
|
||||
ny_response = agent.invoke(
|
||||
{"messages": [{"role": "user", "content": "what about new york?"}]},
|
||||
# highlight-next-line
|
||||
config
|
||||
)
|
||||
```
|
||||
|
||||
1. `checkpointer` allows the agent to store its state at every step in the tool calling loop. This enables [short-term memory](./memory.md#short-term-memory) and [human-in-the-loop](./human-in-the-loop.md) capabilities.
|
||||
2. Pass configuration with `thread_id` to be able to resume the same conversation on future agent invocations.
|
||||
|
||||
When you enable the checkpointer, it stores agent state at every step in the provided checkpointer database (or in memory, if using `InMemorySaver`).
|
||||
|
||||
Note that in the above example, when the agent is invoked the second time with the same `thread_id`, the original message history from the first conversation is automatically included, together with the new user input.
|
||||
|
||||
Please see the [memory guide](./memory.md) for more details on how to work with memory.
|
||||
|
||||
|
||||
## Structured output
|
||||
|
||||
To produce structured responses conforming to a schema, use the `response_format` parameter. The schema can be defined with a `Pydantic` model or `TypedDict`. The result will be accessible via the `structured_response` field.
|
||||
|
||||
```python
|
||||
from pydantic import BaseModel
|
||||
from langgraph.prebuilt import create_react_agent
|
||||
|
||||
class WeatherResponse(BaseModel):
|
||||
conditions: str
|
||||
|
||||
agent = create_react_agent(
|
||||
model="anthropic:claude-3-7-sonnet-latest",
|
||||
tools=[get_weather],
|
||||
# highlight-next-line
|
||||
response_format=WeatherResponse # (1)!
|
||||
)
|
||||
|
||||
response = agent.invoke(
|
||||
{"messages": [{"role": "user", "content": "what is the weather in sf"}]}
|
||||
)
|
||||
|
||||
# highlight-next-line
|
||||
response["structured_response"]
|
||||
```
|
||||
|
||||
1. When `response_format` is provided, a separate step is added at the end of the agent loop: agent message history is passed to an LLM with structured output to generate a structured response.
|
||||
|
||||
To provide a system prompt to this LLM, use a tuple `(prompt, schema)`, e.g., `response_format=(prompt, WeatherResponse)`.
|
||||
|
||||
!!! Note "LLM post-processing"
|
||||
|
||||
Structured output requires an additional call to the LLM to format the response according to the schema.
|
||||
|
||||
|
After Width: | Height: | Size: 141 KiB |
|
After Width: | Height: | Size: 3.2 MiB |
|
After Width: | Height: | Size: 129 KiB |
|
After Width: | Height: | Size: 40 KiB |
|
After Width: | Height: | Size: 28 KiB |
|
After Width: | Height: | Size: 88 KiB |
|
After Width: | Height: | Size: 65 KiB |
@@ -0,0 +1,287 @@
|
||||
# Context
|
||||
|
||||
Agents often require more than a list of messages to function effectively. They need **context**.
|
||||
|
||||
Context includes *any* data outside the message list that can shape agent behavior or tool execution. This can be:
|
||||
|
||||
- Information passed at runtime, like a `user_id` or API credentials.
|
||||
- Internal state updated during a multi-step reasoning process.
|
||||
- Persistent memory or facts from previous interactions.
|
||||
|
||||
LangGraph provides **three** primary ways to supply context:
|
||||
|
||||
| Type | Description | Mutable? | Lifetime |
|
||||
|------------------------------------------------------------------------------|-----------------------------------------------|----------|-------------------------|
|
||||
| [**Config**](#config-static-context) | data passed at the start of a run | ❌ | per run |
|
||||
| [**State**](#state-mutable-context) | dynamic data that can change during execution | ✅ | per run or conversation |
|
||||
| [**Long-term Memory (Store)**](#long-term-memory-cross-conversation-context) | data that can be shared between conversations | ✅ | across conversations |
|
||||
|
||||
You can use context to:
|
||||
|
||||
- Adjust the system prompt the model sees
|
||||
- Feed tools with necessary inputs
|
||||
- Track facts during an ongoing conversation
|
||||
|
||||
## Providing Runtime Context
|
||||
|
||||
Use this when you need to inject data into an agent at runtime.
|
||||
|
||||
### Config (static context)
|
||||
|
||||
Config is for immutable data like user metadata or API keys. Use
|
||||
when you have values that don't change mid-run.
|
||||
|
||||
Specify configuration using a key called **"configurable"** which is reserved
|
||||
for this purpose:
|
||||
|
||||
```python
|
||||
agent.invoke(
|
||||
{"messages": [{"role": "user", "content": "hi!"}]},
|
||||
# highlight-next-line
|
||||
config={"configurable": {"user_id": "user_123"}}
|
||||
)
|
||||
```
|
||||
|
||||
### State (mutable context)
|
||||
|
||||
State acts as short-term memory during a run. It holds dynamic data that can evolve during execution, such as values derived from tools or LLM outputs.
|
||||
|
||||
```python
|
||||
class CustomState(AgentState):
|
||||
# highlight-next-line
|
||||
user_name: str
|
||||
|
||||
agent = create_react_agent(
|
||||
# Other agent parameters...
|
||||
# highlight-next-line
|
||||
state_schema=CustomState,
|
||||
)
|
||||
|
||||
agent.invoke({
|
||||
"messages": "hi!",
|
||||
"user_name": "Jane"
|
||||
})
|
||||
```
|
||||
|
||||
!!! tip "Turning on memory"
|
||||
|
||||
Please see the [memory guide](./memory.md) for more details on how to enable memory. This is a powerful feature that allows you to persist the agent's state across multiple invocations.
|
||||
Otherwise, the state is scoped only to a single agent run.
|
||||
|
||||
|
||||
|
||||
### Long-Term Memory (cross-conversation context)
|
||||
|
||||
For context that spans *across* conversations or sessions, LangGraph allows access to **long-term memory** via a `store`. This can be used to read or update persistent facts (e.g., user profiles, preferences, prior interactions). For more, see the [Memory guide](./memory.md).
|
||||
|
||||
## Customizing Prompts with Context
|
||||
|
||||
Prompts define how the agent behaves. To incorporate runtime context, you can dynamically generate prompts based on the agent's state or config.
|
||||
|
||||
Common use cases:
|
||||
|
||||
- Personalization
|
||||
- Role or goal customization
|
||||
- Conditional behavior (e.g., user is admin)
|
||||
|
||||
=== "Using config"
|
||||
|
||||
```python
|
||||
from langchain_core.messages import AnyMessage
|
||||
from langchain_core.runnables import RunnableConfig
|
||||
from langgraph.prebuilt import create_react_agent
|
||||
from langgraph.prebuilt.chat_agent_executor import AgentState
|
||||
|
||||
def prompt(
|
||||
state: AgentState,
|
||||
# highlight-next-line
|
||||
config: RunnableConfig,
|
||||
) -> list[AnyMessage]:
|
||||
# highlight-next-line
|
||||
user_name = config.get("configurable", {}).get("user_name")
|
||||
system_msg = f"You are a helpful assistant. User's name is {user_name}"
|
||||
return [{"role": "system", "content": system_msg}] + state["messages"]
|
||||
|
||||
agent = create_react_agent(
|
||||
model="anthropic:claude-3-7-sonnet-latest",
|
||||
tools=[get_weather],
|
||||
# highlight-next-line
|
||||
prompt=prompt
|
||||
)
|
||||
|
||||
agent.invoke(
|
||||
...,
|
||||
# highlight-next-line
|
||||
config={"configurable": {"user_name": "John Smith"}}
|
||||
)
|
||||
```
|
||||
|
||||
=== "Using state"
|
||||
|
||||
```python
|
||||
from langchain_core.messages import AnyMessage
|
||||
from langchain_core.runnables import RunnableConfig
|
||||
from langgraph.prebuilt import create_react_agent
|
||||
from langgraph.prebuilt.chat_agent_executor import AgentState
|
||||
|
||||
class CustomState(AgentState):
|
||||
# highlight-next-line
|
||||
user_name: str
|
||||
|
||||
def prompt(
|
||||
# highlight-next-line
|
||||
state: CustomState
|
||||
) -> list[AnyMessage]:
|
||||
# highlight-next-line
|
||||
user_name = state["user_name"]
|
||||
system_msg = f"You are a helpful assistant. User's name is {user_name}"
|
||||
return [{"role": "system", "content": system_msg}] + state["messages"]
|
||||
|
||||
agent = create_react_agent(
|
||||
model="anthropic:claude-3-7-sonnet-latest",
|
||||
tools=[...],
|
||||
# highlight-next-line
|
||||
state_schema=CustomState,
|
||||
# highlight-next-line
|
||||
prompt=prompt
|
||||
)
|
||||
|
||||
agent.invoke({
|
||||
"messages": "hi!",
|
||||
# highlight-next-line
|
||||
"user_name": "John Smith"
|
||||
})
|
||||
```
|
||||
|
||||
## Tools
|
||||
|
||||
Tools can access context through special parameter **annotations**.
|
||||
|
||||
* Use `RunnableConfig` for config access
|
||||
* Use `Annotated[StateSchema, InjectedState]` for agent state
|
||||
|
||||
|
||||
!!! tip
|
||||
|
||||
These annotations prevent LLMs from attempting to fill in the values. These parameters will be **hidden** from the LLM.
|
||||
|
||||
=== "Using config"
|
||||
|
||||
```python
|
||||
def get_user_info(
|
||||
# highlight-next-line
|
||||
config: RunnableConfig,
|
||||
) -> str:
|
||||
"""Look up user info."""
|
||||
# highlight-next-line
|
||||
user_id = config.get("configurable", {}).get("user_id")
|
||||
return "User is John Smith" if user_id == "user_123" else "Unknown user"
|
||||
|
||||
agent = create_react_agent(
|
||||
model="anthropic:claude-3-7-sonnet-latest",
|
||||
tools=[get_user_info],
|
||||
)
|
||||
|
||||
agent.invoke(
|
||||
{"messages": [{"role": "user", "content": "look up user information"}]},
|
||||
# highlight-next-line
|
||||
config={"configurable": {"user_id": "user_123"}}
|
||||
)
|
||||
```
|
||||
|
||||
=== "Using State"
|
||||
|
||||
```python
|
||||
from typing import Annotated
|
||||
from langgraph.prebuilt import InjectedState
|
||||
|
||||
class CustomState(AgentState):
|
||||
# highlight-next-line
|
||||
user_id: str
|
||||
|
||||
def get_user_info(
|
||||
# highlight-next-line
|
||||
state: Annotated[CustomState, InjectedState]
|
||||
) -> str:
|
||||
"""Look up user info."""
|
||||
# highlight-next-line
|
||||
user_id = state["user_id"]
|
||||
return "User is John Smith" if user_id == "user_123" else "Unknown user"
|
||||
|
||||
agent = create_react_agent(
|
||||
model="anthropic:claude-3-7-sonnet-latest",
|
||||
tools=[get_user_info],
|
||||
# highlight-next-line
|
||||
state_schema=CustomState,
|
||||
)
|
||||
|
||||
agent.invoke({
|
||||
"messages": "look up user information",
|
||||
# highlight-next-line
|
||||
"user_id": "user_123"
|
||||
})
|
||||
```
|
||||
|
||||
|
||||
## Update context from tools
|
||||
|
||||
Tools can modify the agent's state during execution. This is useful for persisting intermediate results or making information accessible to subsequent tools or prompts.
|
||||
|
||||
```python
|
||||
from typing import Annotated
|
||||
from langchain_core.tools import InjectedToolCallId
|
||||
from langchain_core.messages import ToolMessage
|
||||
from langgraph.prebuilt import InjectedState
|
||||
from langgraph.types import Command
|
||||
|
||||
class CustomState(AgentState):
|
||||
# highlight-next-line
|
||||
user_name: str
|
||||
|
||||
def get_user_info(
|
||||
# highlight-next-line
|
||||
tool_call_id: Annotated[str, InjectedToolCallId],
|
||||
# highlight-next-line
|
||||
config: RunnableConfig
|
||||
) -> Command:
|
||||
"""Look up user info."""
|
||||
# highlight-next-line
|
||||
user_id = config.get("configurable", {}).get("user_id")
|
||||
name = "John Smith" if user_id == "user_123" else "Unknown user"
|
||||
return Command(update={
|
||||
# highlight-next-line
|
||||
"user_name": name,
|
||||
# update the message history
|
||||
# highlight-next-line
|
||||
"messages": [
|
||||
ToolMessage(
|
||||
"Successfully looked up user information",
|
||||
# highlight-next-line
|
||||
tool_call_id=tool_call_id
|
||||
)
|
||||
]
|
||||
})
|
||||
|
||||
def greet(
|
||||
# highlight-next-line
|
||||
state: Annotated[CustomState, InjectedState]
|
||||
) -> str:
|
||||
"""Use this to greet the user once you found their info."""
|
||||
user_name = state["user_name"]
|
||||
return f"Hello {user_name}!"
|
||||
|
||||
agent = create_react_agent(
|
||||
model="anthropic:claude-3-7-sonnet-latest",
|
||||
tools=[get_user_info, greet],
|
||||
# highlight-next-line
|
||||
state_schema=CustomState
|
||||
)
|
||||
|
||||
agent.invoke(
|
||||
{"messages": [{"role": "user", "content": "greet the user"}]},
|
||||
# highlight-next-line
|
||||
config={"configurable": {"user_id": "user_123"}}
|
||||
)
|
||||
```
|
||||
|
||||
For more details, see [how to update state from tools](../how-tos/update-state-from-tools.ipynb).
|
||||
@@ -0,0 +1,83 @@
|
||||
# Deployment
|
||||
|
||||
To deploy your LangGraph agent, create and configure a LangGraph app. This setup supports both local development and production deployments.
|
||||
|
||||
Features:
|
||||
|
||||
* 🖥️ Local server for development
|
||||
* 🧩 Studio Web UI for visual debugging
|
||||
* ☁️ Cloud and 🔧 self-hosted deployment options
|
||||
* 📊 LangSmith integration for tracing and observability
|
||||
|
||||
!!! info "Requirements"
|
||||
|
||||
- ✅ You **must** have a [LangSmith account](https://www.langchain.com/langsmith). You can sign up for **free** and get started with the free tier.
|
||||
|
||||
## Create a LangGraph app
|
||||
|
||||
```bash
|
||||
pip install -U "langgraph-cli[inmem]"
|
||||
langgraph new path/to/your/app --template new-langgraph-project-python
|
||||
```
|
||||
|
||||
This will create an empty LangGraph project. You can modify it by replacing the code in `src/agent/graph.py` with your agent code. For example:
|
||||
|
||||
```python
|
||||
from langgraph.prebuilt import create_react_agent
|
||||
|
||||
def get_weather(city: str) -> str:
|
||||
"""Get weather for a given city."""
|
||||
return f"It's always sunny in {city}!"
|
||||
|
||||
graph = create_react_agent(
|
||||
model="anthropic:claude-3-7-sonnet-latest",
|
||||
tools=[get_weather],
|
||||
prompt="You are a helpful assistant"
|
||||
)
|
||||
```
|
||||
|
||||
### Install dependencies
|
||||
|
||||
In the root of your new LangGraph app, install the dependencies in `edit` mode so your local changes are used by the server:
|
||||
|
||||
```shell
|
||||
pip install -e .
|
||||
```
|
||||
|
||||
### Create an `.env` file
|
||||
|
||||
You will find a `.env.example` in the root of your new LangGraph app. Create
|
||||
a `.env` file in the root of your new LangGraph app and copy the contents of the `.env.example` file into it, filling in the necessary API keys:
|
||||
|
||||
```bash
|
||||
LANGSMITH_API_KEY=lsv2...
|
||||
ANTHROPIC_API_KEY=sk-
|
||||
```
|
||||
|
||||
## Launch LangGraph server locally
|
||||
|
||||
```shell
|
||||
langgraph dev
|
||||
```
|
||||
|
||||
This will start up the LangGraph API server locally. If this runs successfully, you should see something like:
|
||||
|
||||
> Ready!
|
||||
>
|
||||
> - API: [http://localhost:2024](http://localhost:2024/)
|
||||
>
|
||||
> - Docs: http://localhost:2024/docs
|
||||
>
|
||||
> - LangGraph Studio Web UI: https://smith.langchain.com/studio/?baseUrl=http://127.0.0.1:2024
|
||||
|
||||
See this [tutorial](https://langchain-ai.github.io/langgraph/tutorials/langgraph-platform/local-server/) to learn more about running LangGraph app locally.
|
||||
|
||||
## LangGraph Studio Web UI
|
||||
|
||||
LangGraph Studio Web is a specialized UI that you can connect to LangGraph API server to enable visualization, interaction, and debugging of your application locally. Test your graph in the LangGraph Studio Web UI by visiting the URL provided in the output of the `langgraph dev` command.
|
||||
|
||||
> - LangGraph Studio Web UI: https://smith.langchain.com/studio/?baseUrl=http://127.0.0.1:2024
|
||||
|
||||
## Deployment
|
||||
|
||||
Once your LangGraph app is running locally, you can deploy it using LangGraph Cloud or self-hosted options. Refer to the [deployment options guide](../tutorials/deployment.md) for detailed instructions on all supported deployment models.
|
||||
@@ -0,0 +1,119 @@
|
||||
# Evals
|
||||
|
||||
To evaluate your agent's performance you can use `LangSmith` [evaluations](https://docs.smith.langchain.com/evaluation). You would need to first define an evaluator function to judge the results from an agent, such as final outputs or trajectory. Depending on your evaluation technique, this may or may not involve a reference output:
|
||||
|
||||
```python
|
||||
def evaluator(*, outputs: dict, reference_outputs: dict):
|
||||
# compare agent outputs against reference outputs
|
||||
output_messages = outputs["messages"]
|
||||
reference_messages = reference["messages"]
|
||||
score = compare_messages(output_messages, reference_messages)
|
||||
return {"key": "evaluator_score", "score": score}
|
||||
```
|
||||
|
||||
To get started, you can use prebuilt evaluators from `AgentEvals` package:
|
||||
|
||||
```bash
|
||||
pip install -U agentevals
|
||||
```
|
||||
|
||||
## Create evaluator
|
||||
|
||||
A common way to evaluate agent performance is by comparing its trajectory (the order in which it calls its tools) against a reference trajectory:
|
||||
|
||||
```python
|
||||
import json
|
||||
# highlight-next-line
|
||||
from agentevals.trajectory.match import create_trajectory_match_evaluator
|
||||
|
||||
outputs = [
|
||||
{
|
||||
"role": "assistant",
|
||||
"tool_calls": [
|
||||
{
|
||||
"function": {
|
||||
"name": "get_weather",
|
||||
"arguments": json.dumps({"city": "san francisco"}),
|
||||
}
|
||||
},
|
||||
{
|
||||
"function": {
|
||||
"name": "get_directions",
|
||||
"arguments": json.dumps({"destination": "presidio"}),
|
||||
}
|
||||
}
|
||||
],
|
||||
}
|
||||
]
|
||||
reference_outputs = [
|
||||
{
|
||||
"role": "assistant",
|
||||
"tool_calls": [
|
||||
{
|
||||
"function": {
|
||||
"name": "get_weather",
|
||||
"arguments": json.dumps({"city": "san francisco"}),
|
||||
}
|
||||
},
|
||||
],
|
||||
}
|
||||
]
|
||||
|
||||
# Create the evaluator
|
||||
evaluator = create_trajectory_match_evaluator(
|
||||
# highlight-next-line
|
||||
trajectory_match_mode="superset", # (1)!
|
||||
)
|
||||
|
||||
# Run the evaluator
|
||||
result = evaluator(
|
||||
outputs=outputs, reference_outputs=reference_outputs
|
||||
)
|
||||
```
|
||||
|
||||
1. Specify how the trajectories will be compared. `superset` will accept output trajectory as valid if it's a superset of the reference one. Other options include: [strict](https://github.com/langchain-ai/agentevals?tab=readme-ov-file#strict-match), [unordered](https://github.com/langchain-ai/agentevals?tab=readme-ov-file#unordered-match) and [subset](https://github.com/langchain-ai/agentevals?tab=readme-ov-file#subset-and-superset-match)
|
||||
|
||||
|
||||
As a next step, learn more about how to [customize trajectory match evaluator](https://github.com/langchain-ai/agentevals?tab=readme-ov-file#agent-trajectory-match).
|
||||
|
||||
### LLM-as-a-judge
|
||||
|
||||
You can use LLM-as-a-judge evaluator that uses an LLM to compare the trajectory against the reference outputs and output a score:
|
||||
|
||||
```python
|
||||
import json
|
||||
from agentevals.trajectory.llm import (
|
||||
# highlight-next-line
|
||||
create_trajectory_llm_as_judge,
|
||||
TRAJECTORY_ACCURACY_PROMPT_WITH_REFERENCE
|
||||
)
|
||||
|
||||
evaluator = create_trajectory_llm_as_judge(
|
||||
prompt=TRAJECTORY_ACCURACY_PROMPT_WITH_REFERENCE,
|
||||
model="openai:o3-mini"
|
||||
)
|
||||
```
|
||||
|
||||
## Run evaluator
|
||||
|
||||
To run an evaluator, you will first need to create a [LangSmith dataset](https://docs.smith.langchain.com/evaluation/concepts#datasets). To use the prebuilt AgentEvals evaluators, you will need a dataset with the following schema:
|
||||
|
||||
- **input**: `{"messages": [...]}` input messages to call the agent with.
|
||||
- **output**: `{"messages": [...]}` expected message history in the agent output. For trajectory evaluation, you can choose to keep only assistant messages.
|
||||
|
||||
```python
|
||||
from langsmith import Client
|
||||
from langgraph.prebuilt import create_react_agent
|
||||
from agentevals.trajectory.match import create_trajectory_match_evaluator
|
||||
|
||||
client = Client()
|
||||
agent = create_react_agent(...)
|
||||
evaluator = create_trajectory_match_evaluator(...)
|
||||
|
||||
experiment_results = client.evaluate(
|
||||
lambda inputs: agent.invoke(inputs),
|
||||
# replace with your dataset name
|
||||
data="<Name of your dataset>",
|
||||
evaluators=[evaluator]
|
||||
)
|
||||
```
|
||||
@@ -0,0 +1,227 @@
|
||||
# Human-in-the-loop
|
||||
|
||||
To review, edit and approve tool calls in an agent you can use LangGraph's built-in [human-in-the-loop](../concepts/human_in_the_loop.md) features, specifically the [`interrupt()`][langgraph.types.interrupt] primitive.
|
||||
|
||||
LangGraph allows you to pause execution **indefinitely** — for minutes, hours, or even days—until human input is received.
|
||||
|
||||
This is possible because the agent state is **checkpointed into a database**, which allows the system to persist execution context and later resume the workflow, continuing from where it left off.
|
||||
|
||||
For a deeper dive into the **human-in-the-loop** concept, see the [concept guide](../concepts/human_in_the_loop.md).
|
||||
|
||||
<figure markdown="1">
|
||||
{: style="max-height:400px"}
|
||||
<figcaption>
|
||||
A human can review and edit the output from the agent before proceeding. This is particularly critical in applications where the tool calls requested may be sensitive or require human oversight.
|
||||
</figcaption>
|
||||
</figure>
|
||||
|
||||
|
||||
## Review tool calls
|
||||
|
||||
To add a human approval step to a tool:
|
||||
|
||||
1. Use `interrupt()` in the tool to pause execution.
|
||||
2. Resume with a `Command(resume=...)` to continue based on human input.
|
||||
|
||||
```python
|
||||
from langgraph.checkpoint.memory import InMemorySaver
|
||||
from langgraph.types import interrupt
|
||||
from langgraph.prebuilt import create_react_agent
|
||||
|
||||
# An example of a sensitive tool that requires human review / approval
|
||||
def book_hotel(hotel_name: str):
|
||||
"""Book a hotel"""
|
||||
# highlight-next-line
|
||||
response = interrupt( # (1)!
|
||||
f"Trying to call `book_hotel` with args {{'hotel_name': {hotel_name}}}. "
|
||||
"Please approve or suggest edits."
|
||||
)
|
||||
if response["type"] == "accept":
|
||||
pass
|
||||
elif response["type"] == "edit":
|
||||
hotel_name = response["args"]["hotel_name"]
|
||||
else:
|
||||
raise ValueError(f"Unknown response type: {response['type']}")
|
||||
return f"Successfully booked a stay at {hotel_name}."
|
||||
|
||||
# highlight-next-line
|
||||
checkpointer = InMemorySaver() # (2)!
|
||||
|
||||
agent = create_react_agent(
|
||||
model="anthropic:claude-3-5-sonnet-latest",
|
||||
tools=[book_hotel],
|
||||
# highlight-next-line
|
||||
checkpointer=checkpointer, # (3)!
|
||||
)
|
||||
```
|
||||
|
||||
1. The [`interrupt` function][langgraph.types.interrupt] pauses the agent graph at a specific node. In this case, we call `interrupt()` at the beginning of the tool function, which pauses the graph at the node that executes the tool. The information inside `interrupt()` (e.g., tool calls) can be presented to a human, and the graph can be resumed with the user input (tool call approval, edit or feedback).
|
||||
2. The `InMemorySaver` is used to store the agent state at every step in the tool calling loop. This enables [short-term memory](./memory.md#short-term-memory) and [human-in-the-loop](./human-in-the-loop.md) capabilities. In this example, we use `InMemorySaver` to store the agent state in memory. In a production application, the agent state will be stored in a database.
|
||||
3. Initialize the agent with the `checkpointer`.
|
||||
|
||||
Run the agent with the `stream()` method, passing the `config` object to specify the thread ID. This allows the agent to resume the same conversation on future invocations.
|
||||
|
||||
```python
|
||||
config = {
|
||||
"configurable": {
|
||||
# highlight-next-line
|
||||
"thread_id": "1"
|
||||
}
|
||||
}
|
||||
|
||||
for chunk in agent.stream(
|
||||
{"messages": [{"role": "user", "content": "book a stay at McKittrick hotel"}]},
|
||||
# highlight-next-line
|
||||
config
|
||||
):
|
||||
print(chunk)
|
||||
print("\n")
|
||||
```
|
||||
|
||||
> You should see that the agent runs until it reaches the `interrupt()` call, at which point it pauses and waits for human input.
|
||||
|
||||
Resume the agent with a `Command(resume=...)` to continue based on human input.
|
||||
|
||||
```python
|
||||
from langgraph.types import Command
|
||||
|
||||
for chunk in agent.stream(
|
||||
# highlight-next-line
|
||||
Command(resume={"type": "accept"}), # (1)!
|
||||
# Command(resume={"type": "edit", "args": {"hotel_name": "McKittrick Hotel"}}),
|
||||
config
|
||||
):
|
||||
print(chunk)
|
||||
print("\n")
|
||||
```
|
||||
|
||||
1. The [`interrupt` function][langgraph.types.interrupt] is used in conjunction with the [`Command`](../reference/types.md#langgraph.types.Command) object to resume the graph with a value provided by the human.
|
||||
|
||||
## Using with Agent Inbox
|
||||
|
||||
You can create a wrapper to add interrupts to *any* tool.
|
||||
|
||||
The example below provides a reference implementation compatible with [Agent Inbox UI](https://github.com/langchain-ai/agent-inbox) and [Agent Chat UI](https://github.com/langchain-ai/agent-chat-ui).
|
||||
|
||||
```python title="Wrapper that adds human-in-the-loop to any tool"
|
||||
from typing import Callable
|
||||
from langchain_core.tools import BaseTool, tool as create_tool
|
||||
from langchain_core.runnables import RunnableConfig
|
||||
from langgraph.types import interrupt
|
||||
from langgraph.prebuilt.interrupt import HumanInterruptConfig, HumanInterrupt
|
||||
|
||||
def add_human_in_the_loop(
|
||||
tool: Callable | BaseTool,
|
||||
*,
|
||||
interrupt_config: HumanInterruptConfig = None,
|
||||
) -> BaseTool:
|
||||
"""Wrap a tool to support human-in-the-loop review."""
|
||||
if not isinstance(tool, BaseTool):
|
||||
tool = create_tool(tool)
|
||||
|
||||
if interrupt_config is None:
|
||||
interrupt_config = {
|
||||
"allow_accept": True,
|
||||
"allow_edit": True,
|
||||
"allow_respond": True,
|
||||
}
|
||||
|
||||
@create_tool( # (1)!
|
||||
tool.name,
|
||||
description=tool.description,
|
||||
args_schema=tool.args_schema
|
||||
)
|
||||
def call_tool_with_interrupt(config: RunnableConfig, **tool_input):
|
||||
request: HumanInterrupt = {
|
||||
"action_request": {
|
||||
"action": tool.name,
|
||||
"args": tool_input
|
||||
},
|
||||
"config": interrupt_config,
|
||||
"description": "Please review the tool call"
|
||||
}
|
||||
# highlight-next-line
|
||||
response = interrupt([request])[0] # (2)!
|
||||
# approve the tool call
|
||||
if response["type"] == "accept":
|
||||
tool_response = tool.invoke(tool_input, config)
|
||||
# update tool call args
|
||||
elif response["type"] == "edit":
|
||||
tool_input = response["args"]["args"]
|
||||
tool_response = tool.invoke(tool_input, config)
|
||||
# respond to the LLM with user feedback
|
||||
elif response["type"] == "response":
|
||||
user_feedback = response["args"]
|
||||
tool_response = user_feedback
|
||||
else:
|
||||
raise ValueError(f"Unsupported interrupt response type: {response['type']}")
|
||||
|
||||
return tool_response
|
||||
|
||||
return call_tool_with_interrupt
|
||||
```
|
||||
|
||||
1. This wrapper creates a new tool that calls `interrupt()` **before** executing the wrapped tool.
|
||||
2. `interrupt()` is using special input and output format that's expected by [Agent Inbox UI](https://github.com/langchain-ai/agent-inbox):
|
||||
- a list of [`HumanInterrupt`][langgraph.prebuilt.interrupt.HumanInterrupt] objects is sent to `AgentInbox` render interrupt information to the end user
|
||||
- resume value is provided by `AgentInbox` as a list (i.e., `Command(resume=[...])`)
|
||||
|
||||
You can use the `add_human_in_the_loop` wrapper to add `interrupt()` to any tool without having to add it *inside* the tool:
|
||||
|
||||
```python
|
||||
from langgraph.checkpoint.memory import InMemorySaver
|
||||
from langgraph.prebuilt import create_react_agent
|
||||
|
||||
# highlight-next-line
|
||||
checkpointer = InMemorySaver()
|
||||
|
||||
def book_hotel(hotel_name: str):
|
||||
"""Book a hotel"""
|
||||
return f"Successfully booked a stay at {hotel_name}."
|
||||
|
||||
|
||||
agent = create_react_agent(
|
||||
model="anthropic:claude-3-5-sonnet-latest",
|
||||
tools=[
|
||||
# highlight-next-line
|
||||
add_human_in_the_loop(book_hotel), # (1)!
|
||||
],
|
||||
# highlight-next-line
|
||||
checkpointer=checkpointer,
|
||||
)
|
||||
|
||||
config = {"configurable": {"thread_id": "1"}}
|
||||
|
||||
# Run the agent
|
||||
for chunk in agent.stream(
|
||||
{"messages": [{"role": "user", "content": "book a stay at McKittrick hotel"}]},
|
||||
# highlight-next-line
|
||||
config
|
||||
):
|
||||
print(chunk)
|
||||
print("\n")
|
||||
```
|
||||
|
||||
1. The `add_human_in_the_loop` wrapper is used to add `interrupt()` to the tool. This allows the agent to pause execution and wait for human input before proceeding with the tool call.
|
||||
|
||||
> You should see that the agent runs until it reaches the `interrupt()` call,
|
||||
> at which point it pauses and waits for human input.
|
||||
|
||||
Resume the agent with a `Command(resume=...)` to continue based on human input.
|
||||
|
||||
```python
|
||||
from langgraph.types import Command
|
||||
|
||||
for chunk in agent.stream(
|
||||
# highlight-next-line
|
||||
Command(resume=[{"type": "accept"}]),
|
||||
# Command(resume=[{"type": "edit", "args": {"args": {"hotel_name": "McKittrick Hotel"}}}]),
|
||||
config
|
||||
):
|
||||
print(chunk)
|
||||
print("\n")
|
||||
```
|
||||
|
||||
## Additional resources
|
||||
|
||||
* [Human-in-the-loop in LangGraph](../concepts/human_in_the_loop.md)
|
||||
@@ -0,0 +1,98 @@
|
||||
# MCP Integration
|
||||
|
||||
[Model Context Protocol (MCP)](https://modelcontextprotocol.io/introduction) is an open protocol that standardizes how applications provide tools and context to language models. LangGraph agents can use tools defined on MCP servers through the `langchain-mcp-adapters` library.
|
||||
|
||||

|
||||
|
||||
Install the `langchain-mcp-adapters` library to use MCP tools in LangGraph:
|
||||
|
||||
```bash
|
||||
pip install langchain-mcp-adapters
|
||||
```
|
||||
|
||||
## Use MCP tools
|
||||
|
||||
The `langchain-mcp-adapters` package enables agents to use tools defined across one or more MCP servers.
|
||||
|
||||
```python title="Agent using tools defined on MCP servers"
|
||||
# highlight-next-line
|
||||
from langchain_mcp_adapters.client import MultiServerMCPClient
|
||||
from langgraph.prebuilt import create_react_agent
|
||||
|
||||
# highlight-next-line
|
||||
async with MultiServerMCPClient(
|
||||
{
|
||||
"math": {
|
||||
"command": "python",
|
||||
# Replace with absolute path to your math_server.py file
|
||||
"args": ["/path/to/math_server.py"],
|
||||
"transport": "stdio",
|
||||
},
|
||||
"weather": {
|
||||
# Ensure your start your weather server on port 8000
|
||||
"url": "http://localhost:8000/sse",
|
||||
"transport": "sse",
|
||||
}
|
||||
}
|
||||
) as client:
|
||||
agent = create_react_agent(
|
||||
"anthropic:claude-3-7-sonnet-latest",
|
||||
# highlight-next-line
|
||||
client.get_tools()
|
||||
)
|
||||
math_response = await agent.ainvoke(
|
||||
{"messages": [{"role": "user", "content": "what's (3 + 5) x 12?"}]}
|
||||
)
|
||||
weather_response = await agent.ainvoke(
|
||||
{"messages": [{"role": "user", "content": "what is the weather in nyc?"}]}
|
||||
)
|
||||
```
|
||||
|
||||
## Custom MCP servers
|
||||
|
||||
To create your own MCP servers, you can use the `mcp` library. This library provides a simple way to define tools and run them as servers.
|
||||
|
||||
Install the MCP library:
|
||||
|
||||
```bash
|
||||
pip install mcp
|
||||
```
|
||||
Use the following reference implementations to test your agent with MCP tool servers.
|
||||
|
||||
```python title="Example Math Server (stdio transport)"
|
||||
from mcp.server.fastmcp import FastMCP
|
||||
|
||||
mcp = FastMCP("Math")
|
||||
|
||||
@mcp.tool()
|
||||
def add(a: int, b: int) -> int:
|
||||
"""Add two numbers"""
|
||||
return a + b
|
||||
|
||||
@mcp.tool()
|
||||
def multiply(a: int, b: int) -> int:
|
||||
"""Multiply two numbers"""
|
||||
return a * b
|
||||
|
||||
if __name__ == "__main__":
|
||||
mcp.run(transport="stdio")
|
||||
```
|
||||
|
||||
```python title="Example Weather Server (SSE transport)"
|
||||
from mcp.server.fastmcp import FastMCP
|
||||
|
||||
mcp = FastMCP("Weather")
|
||||
|
||||
@mcp.tool()
|
||||
async def get_weather(location: str) -> str:
|
||||
"""Get weather for location."""
|
||||
return "It's always sunny in New York"
|
||||
|
||||
if __name__ == "__main__":
|
||||
mcp.run(transport="sse")
|
||||
```
|
||||
|
||||
## Additional resources
|
||||
|
||||
- [MCP documentation](https://modelcontextprotocol.io/introduction)
|
||||
- [MCP Transport documentation](https://modelcontextprotocol.io/docs/concepts/transports)
|
||||
@@ -0,0 +1,262 @@
|
||||
# Memory
|
||||
|
||||
LangGraph supports two types of memory essential for building conversational agents:
|
||||
|
||||
- **[Short-term memory](#short-term-memory)**: Tracks the ongoing conversation by maintaining message history within a session.
|
||||
- **[Long-term memory](#long-term-memory)**: Stores user-specific or application-level data across sessions.
|
||||
|
||||
This guide demonstrates how to use both memory types with agents in LangGraph. For a deeper
|
||||
understanding of memory concepts, refer to the [LangGraph memory documentation](../concepts/memory.md).
|
||||
|
||||
<figure markdown="1">
|
||||
{: style="max-height:400px"}
|
||||
<figcaption>Both <strong>short-term</strong> and <strong>long-term</strong> memory require persistent storage to maintain continuity across LLM interactions. In production environments, this data is typically stored in a database.</figcaption>
|
||||
</figure>
|
||||
|
||||
!!! note "Terminology"
|
||||
|
||||
In LangGraph:
|
||||
|
||||
- *Short-term memory* is also referred to as **thread-level memory**.
|
||||
- *Long-term memory* is also called **cross-thread memory**.
|
||||
|
||||
A [thread](../concepts/persistence.md#threads) represents a sequence of related runs
|
||||
grouped by the same `thread_id`.
|
||||
|
||||
## Short-term memory
|
||||
|
||||
Short-term memory enables agents to track multi-turn conversations. To use it, you must:
|
||||
|
||||
1. Provide a `checkpointer` when creating the agent. The `checkpointer` enables [persistence](../concepts/persistence.md) of the agent's state.
|
||||
2. Supply a `thread_id` in the config when running the agent. The `thread_id` is a unique identifier for the conversation session.
|
||||
|
||||
```python
|
||||
from langgraph.prebuilt import create_react_agent
|
||||
from langgraph.checkpoint.memory import InMemorySaver
|
||||
|
||||
# highlight-next-line
|
||||
checkpointer = InMemorySaver() # (1)!
|
||||
|
||||
|
||||
def get_weather(city: str) -> str:
|
||||
"""Get weather for a given city."""
|
||||
return f"It's always sunny in {city}!"
|
||||
|
||||
|
||||
agent = create_react_agent(
|
||||
model="anthropic:claude-3-7-sonnet-latest",
|
||||
tools=[get_weather],
|
||||
# highlight-next-line
|
||||
checkpointer=checkpointer # (2)!
|
||||
)
|
||||
|
||||
# Run the agent
|
||||
config = {
|
||||
"configurable": {
|
||||
# highlight-next-line
|
||||
"thread_id": "1" # (3)!
|
||||
}
|
||||
}
|
||||
|
||||
sf_response = agent.invoke(
|
||||
{"messages": [{"role": "user", "content": "what is the weather in sf"}]},
|
||||
# highlight-next-line
|
||||
config
|
||||
)
|
||||
|
||||
# Continue the conversation using the same thread_id
|
||||
ny_response = agent.invoke(
|
||||
{"messages": [{"role": "user", "content": "what about new york?"}]},
|
||||
# highlight-next-line
|
||||
config # (4)!
|
||||
)
|
||||
```
|
||||
|
||||
1. The `InMemorySaver` is a checkpointer that stores the agent's state in memory. In a production setting, you would typically use a database or other persistent storage. Please review the [checkpointer documentation](../reference/checkpoints.md) for more options. If you're deploying with **LangGraph Platform**, the platform will provide a production-ready checkpointer for you.
|
||||
2. The `checkpointer` is passed to the agent. This enables the agent to persist its state across invocations. Please note that
|
||||
3. A unique `thread_id` is provided in the config. This ID is used to identify the conversation session. The value is controlled by the user and can be any string.
|
||||
4. The agent will continue the conversation using the same `thread_id`. This will allow the agent to infer that the user is asking specifically about the **weather** in New York.
|
||||
|
||||
When the agent is invoked the second time with the same `thread_id`, the original message history from the first conversation is automatically included, allowing the agent to infer that the user is asking specifically about the **weather** in New York.
|
||||
|
||||
!!! Note "LangGraph Platform providers a production-ready checkpointer"
|
||||
|
||||
If you're using [LangGraph Platform](./deployment.md), during deployment your checkpointer will be automatically configured to use a production-ready database.
|
||||
|
||||
### Message history summarization
|
||||
|
||||
<figure markdown="1">
|
||||
{: style="max-height:400px"}
|
||||
<figcaption>Message history can grow quickly and exceed the LLM's context window. A common solution is to maintain a running summary of the conversation. This allows the agent to keep track of the conversation without exceeding the LLM's context window.
|
||||
</figcaption>
|
||||
</figure>
|
||||
|
||||
Long conversations can exceed the LLM's context window. To handle this, you can summarize older messages by specifying a [`pre_model_hook`][langgraph.prebuilt.chat_agent_executor.create_react_agent], such as the prebuilt [`SummarizationNode`](https://langchain-ai.github.io/langmem/reference/short_term/#langmem.short_term.SummarizationNode):
|
||||
|
||||
```python
|
||||
from langchain_anthropic import ChatAnthropic
|
||||
from langmem.short_term import SummarizationNode
|
||||
from langchain_core.messages.utils import count_tokens_approximately
|
||||
from langgraph.prebuilt import create_react_agent
|
||||
from langgraph.prebuilt.chat_agent_executor import AgentState
|
||||
from langgraph.checkpoint.memory import InMemorySaver
|
||||
from typing import Any
|
||||
|
||||
model = ChatAnthropic(model="claude-3-7-sonnet-latest")
|
||||
|
||||
summarization_node = SummarizationNode( # (1)!
|
||||
token_counter=count_tokens_approximately,
|
||||
model=model,
|
||||
max_tokens=384,
|
||||
max_summary_tokens=128,
|
||||
output_messages_key="llm_input_messages",
|
||||
)
|
||||
|
||||
class State(AgentState):
|
||||
# NOTE: we're adding this key to keep track of previous summary information
|
||||
# to make sure we're not summarizing on every LLM call
|
||||
# highlight-next-line
|
||||
context: dict[str, Any] # (2)!
|
||||
|
||||
|
||||
checkpointer = InMemorySaver() # (3)!
|
||||
|
||||
agent = create_react_agent(
|
||||
model=model,
|
||||
tools=tools,
|
||||
# highlight-next-line
|
||||
pre_model_hook=summarization_node, # (4)!
|
||||
# highlight-next-line
|
||||
state_schema=State, # (5)!
|
||||
checkpointer=checkpointer,
|
||||
)
|
||||
```
|
||||
|
||||
1. The `InMemorySaver` is a checkpointer that stores the agent's state in memory. In a production setting, you would typically use a database or other persistent storage. Please review the [checkpointer documentation](../reference/checkpoints.md) for more options. If you're deploying with **LangGraph Platform**, the platform will provide a production-ready checkpointer for you.
|
||||
2. The `context` key is added to the agent's state. The key contains book-keeping information for the summarization node. It is used to keep track of the last summary information and ensure that the agent doesn't summarize on every LLM call, which can be inefficient.
|
||||
3. The `checkpointer` is passed to the agent. This enables the agent to persist its state across invocations.
|
||||
4. The `pre_model_hook` is set to the `SummarizationNode`. This node will summarize the message history before sending it to the LLM. The summarization node will automatically handle the summarization process and update the agent's state with the new summary. You can replace this with a custom implementation if you prefer. Please see the [create_react_agent][langgraph.prebuilt.chat_agent_executor.create_react_agent] API reference for more details.
|
||||
5. The `state_schema` is set to the `State` class, which is the custom state that contains an extra `context` key.
|
||||
|
||||
To learn more about using `pre_model_hook` for managing message history, see this [how-to guide](../how-tos/create-react-agent-manage-message-history.ipynb)
|
||||
|
||||
## Long-term memory
|
||||
|
||||
Use long-term memory to store user-specific or application-specific data across conversations. This is useful for applications like chatbots, where you want to remember user preferences or other information.
|
||||
|
||||
To use long-term memory, you need to:
|
||||
|
||||
1. [Configure a store](../how-tos/cross-thread-persistence.ipynb) to persist data across invocations.
|
||||
2. Use the [`get_store`][langgraph.config.get_store] function to access the store from within tools or prompts.
|
||||
|
||||
### Reading
|
||||
|
||||
```python title="A tool the agent can use to look up user information"
|
||||
from langgraph.config import get_store
|
||||
from langgraph.prebuilt import create_react_agent
|
||||
from langgraph.store.memory import InMemoryStore
|
||||
|
||||
# highlight-next-line
|
||||
store = InMemoryStore() # (1)!
|
||||
|
||||
# highlight-next-line
|
||||
store.put( # (2)!
|
||||
("users",), # (3)!
|
||||
"user_123", # (4)!
|
||||
{
|
||||
"name": "John Smith",
|
||||
"language": "English",
|
||||
} # (5)!
|
||||
)
|
||||
|
||||
def get_user_info(config: RunnableConfig) -> str:
|
||||
"""Look up user info."""
|
||||
# Same as that provided to `create_react_agent`
|
||||
# highlight-next-line
|
||||
store = get_store() # (6)!
|
||||
user_id = config.get("configurable", {}).get("user_id")
|
||||
# highlight-next-line
|
||||
user_info = store.get(("users",), user_id) # (7)!
|
||||
return str(user_info.value) if user_info else "Unknown user"
|
||||
|
||||
agent = create_react_agent(
|
||||
model="anthropic:claude-3-7-sonnet-latest",
|
||||
tools=[get_user_info],
|
||||
# highlight-next-line
|
||||
store=store # (8)!
|
||||
)
|
||||
|
||||
# Run the agent
|
||||
agent.invoke(
|
||||
{"messages": [{"role": "user", "content": "look up user information"}]},
|
||||
# highlight-next-line
|
||||
config={"configurable": {"user_id": "user_123"}}
|
||||
)
|
||||
```
|
||||
|
||||
1. The `InMemoryStore` is a store that stores data in memory. In a production setting, you would typically use a database or other persistent storage. Please review the [store documentation](../reference/stores.md) for more options. If you're deploying with **LangGraph Platform**, the platform will provide a production-ready store for you.
|
||||
2. For this example, we write some sample data to the store using the `put` method. Please see the [BaseStore.put][langgraph.store.base.BaseStore.put] API reference for more details.
|
||||
3. The first argument is the namespace. This is used to group related data together. In this case, we are using the `users` namespace to group user data.
|
||||
4. A key within the namespace. This example uses a user ID for the key.
|
||||
5. The data that we want to store for the given user.
|
||||
6. The `get_store` function is used to access the store. You can call it from anywhere in your code, including tools and prompts. This function returns the store that was passed to the agent when it was created.
|
||||
7. The `get` method is used to retrieve data from the store. The first argument is the namespace, and the second argument is the key. This will return a `StoreValue` object, which contains the value and metadata about the value.
|
||||
8. The `store` is passed to the agent. This enables the agent to access the store when running tools. You can also use the `get_store` function to access the store from anywhere in your code.
|
||||
|
||||
### Writing
|
||||
|
||||
```python title="Example of a tool that updates user information"
|
||||
from typing_extensions import TypedDict
|
||||
|
||||
from langgraph.config import get_store
|
||||
from langgraph.prebuilt import create_react_agent
|
||||
from langgraph.store.memory import InMemoryStore
|
||||
|
||||
store = InMemoryStore() # (1)!
|
||||
|
||||
class UserInfo(TypedDict): # (2)!
|
||||
name: str
|
||||
|
||||
def save_user_info(user_info: UserInfo, config: RunnableConfig) -> str: # (3)!
|
||||
"""Save user info."""
|
||||
# Same as that provided to `create_react_agent`
|
||||
# highlight-next-line
|
||||
store = get_store() # (4)!
|
||||
user_id = config.get("configurable", {}).get("user_id")
|
||||
# highlight-next-line
|
||||
store.put(("users",), user_id, user_info) # (5)!
|
||||
return "Successfully saved user info."
|
||||
|
||||
agent = create_react_agent(
|
||||
model="anthropic:claude-3-7-sonnet-latest",
|
||||
tools=[save_user_info],
|
||||
# highlight-next-line
|
||||
store=store
|
||||
)
|
||||
|
||||
# Run the agent
|
||||
agent.invoke(
|
||||
{"messages": [{"role": "user", "content": "My name is John Smith"}]},
|
||||
# highlight-next-line
|
||||
config={"configurable": {"user_id": "user_123"}} # (6)!
|
||||
)
|
||||
|
||||
# You can access the store directly to get the value
|
||||
store.get(("users",), "user_123").value
|
||||
```
|
||||
|
||||
1. The `InMemoryStore` is a store that stores data in memory. In a production setting, you would typically use a database or other persistent storage. Please review the [store documentation](../reference/stores.md) for more options. If you're deploying with **LangGraph Platform**, the platform will provide a production-ready store for you.
|
||||
2. The `UserInfo` class is a `TypedDict` that defines the structure of the user information. The LLM will use this to format the response according to the schema.
|
||||
3. The `save_user_info` function is a tool that allows an agent to update user information. This could be useful for a chat application where the user wants to update their profile information.
|
||||
4. The `get_store` function is used to access the store. You can call it from anywhere in your code, including tools and prompts. This function returns the store that was passed to the agent when it was created.
|
||||
5. The `put` method is used to store data in the store. The first argument is the namespace, and the second argument is the key. This will store the user information in the store.
|
||||
6. The `user_id` is passed in the config. This is used to identify the user whose information is being updated.
|
||||
|
||||
### Prebuilt memory tools
|
||||
|
||||
**LangMem** is a LangChain-maintained library that offers tools for managing long-term memories in your agent. See the [LangMem documentation](https://langchain-ai.github.io/langmem/) for usage examples.
|
||||
|
||||
|
||||
## Additional resources
|
||||
|
||||
* [Memory in LangGraph](../concepts/memory.md)
|
||||
@@ -0,0 +1,69 @@
|
||||
# Models
|
||||
|
||||
This page describes how to configure the chat model used by an agent.
|
||||
|
||||
## Tool calling support
|
||||
|
||||
To enable tool-calling agents, the underlying LLM must support [tool calling](https://python.langchain.com/docs/concepts/tool_calling/).
|
||||
|
||||
Compatible models can be found in the [LangChain integrations directory](https://python.langchain.com/docs/integrations/chat/).
|
||||
|
||||
## Specifying a model by name
|
||||
|
||||
You can configure an agent with a model name string:
|
||||
|
||||
```python
|
||||
from langgraph.prebuilt import create_react_agent
|
||||
|
||||
agent = create_react_agent(
|
||||
# highlight-next-line
|
||||
model="anthropic:claude-3-7-sonnet-latest",
|
||||
# other parameters
|
||||
)
|
||||
```
|
||||
|
||||
## Using `init_chat_model`
|
||||
|
||||
The [`init_chat_model`](https://python.langchain.com/docs/how_to/chat_models_universal_init/) utility simplifies model initialization with configurable parameters:
|
||||
|
||||
```python
|
||||
from langchain.chat_models import init_chat_model
|
||||
|
||||
model = init_chat_model(
|
||||
"anthropic:claude-3-7-sonnet-latest",
|
||||
temperature=0,
|
||||
max_tokens=2048
|
||||
)
|
||||
```
|
||||
|
||||
Refer to the [API reference](https://python.langchain.com/api_reference/langchain/chat_models/langchain.chat_models.base.init_chat_model.html) for advanced options.
|
||||
|
||||
## Using provider-specific LLMs
|
||||
|
||||
If a model provider is not available via `init_chat_model`, you can instantiate the provider's model class directly. The model must implement the [BaseChatModel interface](https://python.langchain.com/api_reference/core/language_models/langchain_core.language_models.chat_models.BaseChatModel.html) and support tool calling:
|
||||
|
||||
```python
|
||||
from langchain_anthropic import ChatAnthropic
|
||||
from langgraph.prebuilt import create_react_agent
|
||||
|
||||
model = ChatAnthropic(
|
||||
model="claude-3-7-sonnet-latest",
|
||||
temperature=0,
|
||||
max_tokens=2048
|
||||
)
|
||||
|
||||
agent = create_react_agent(
|
||||
# highlight-next-line
|
||||
model=model,
|
||||
# other parameters
|
||||
)
|
||||
```
|
||||
|
||||
!!! note "Illustrative example"
|
||||
|
||||
The example above uses `ChatAnthropic`, which is already supported by `init_chat_model`. This pattern is shown to illustrate how to manually instantiate a model not available through init_chat_model.
|
||||
|
||||
## Additional resources
|
||||
|
||||
- [Model integration directory](https://python.langchain.com/docs/integrations/chat/)
|
||||
- [Universal initialization with `init_chat_model`](https://python.langchain.com/docs/how_to/chat_models_universal_init/)
|
||||
@@ -0,0 +1,299 @@
|
||||
# Multi-agent
|
||||
|
||||
A single agent might struggle if it needs to specialize in multiple domains or manage many tools. To tackle this, you can break your agent into smaller, independent agents and composing them into a [multi-agent system](../concepts/multi_agent.md).
|
||||
|
||||
In multi-agent systems, agents need to communicate between each other. They do so via [handoffs](#handoffs) — a primitive that describes which agent to hand control to and the payload to send to that agent.
|
||||
|
||||
Two of the most popular multi-agent architectures are:
|
||||
|
||||
- [supervisor](#supervisor) — individual agents are coordinated by a central supervisor agent. The supervisor controls all communication flow and task delegation, making decisions about which agent to invoke based on the current context and task requirements.
|
||||
- [swarm](#swarm) — agents dynamically hand off control to one another based on their specializations. The system remembers which agent was last active, ensuring that on subsequent interactions, the conversation resumes with that agent.
|
||||
|
||||
## Supervisor
|
||||
|
||||

|
||||
|
||||
Use [`langgraph-supervisor`](https://github.com/langchain-ai/langgraph-supervisor-py) library to create a supervisor multi-agent system:
|
||||
|
||||
```bash
|
||||
pip install langgraph-supervisor
|
||||
```
|
||||
|
||||
```python
|
||||
from langchain_openai import ChatOpenAI
|
||||
from langgraph.prebuilt import create_react_agent
|
||||
# highlight-next-line
|
||||
from langgraph_supervisor import create_supervisor
|
||||
|
||||
def book_hotel(hotel_name: str):
|
||||
"""Book a hotel"""
|
||||
return f"Successfully booked a stay at {hotel_name}."
|
||||
|
||||
def book_flight(from_airport: str, to_airport: str):
|
||||
"""Book a flight"""
|
||||
return f"Successfully booked a flight from {from_airport} to {to_airport}."
|
||||
|
||||
flight_assistant = create_react_agent(
|
||||
model="openai:gpt-4o",
|
||||
tools=[book_flight],
|
||||
prompt="You are a flight booking assistant",
|
||||
# highlight-next-line
|
||||
name="flight_assistant"
|
||||
)
|
||||
|
||||
hotel_assistant = create_react_agent(
|
||||
model="openai:gpt-4o",
|
||||
tools=[book_hotel],
|
||||
prompt="You are a hotel booking assistant",
|
||||
# highlight-next-line
|
||||
name="hotel_assistant"
|
||||
)
|
||||
|
||||
# highlight-next-line
|
||||
supervisor = create_supervisor(
|
||||
agents=[flight_assistant, hotel_assistant],
|
||||
model=ChatOpenAI(model="gpt-4o"),
|
||||
prompt=(
|
||||
"You manage a hotel booking assistant and a"
|
||||
"flight booking assistant. Assign work to them."
|
||||
)
|
||||
).compile()
|
||||
|
||||
for chunk in supervisor.stream(
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "book a flight from BOS to JFK and a stay at McKittrick Hotel"
|
||||
}
|
||||
]
|
||||
}
|
||||
):
|
||||
print(chunk)
|
||||
print("\n")
|
||||
```
|
||||
|
||||
## Swarm
|
||||
|
||||

|
||||
|
||||
Use [`langgraph-swarm`](https://github.com/langchain-ai/langgraph-swarm-py) library to create a swarm multi-agent system:
|
||||
|
||||
```bash
|
||||
pip install langgraph-swarm
|
||||
```
|
||||
|
||||
```python
|
||||
from langgraph.prebuilt import create_react_agent
|
||||
# highlight-next-line
|
||||
from langgraph_swarm import create_swarm, create_handoff_tool
|
||||
|
||||
transfer_to_hotel_assistant = create_handoff_tool(
|
||||
agent_name="hotel_assistant",
|
||||
description="Transfer user to the hotel-booking assistant.",
|
||||
)
|
||||
transfer_to_flight_assistant = create_handoff_tool(
|
||||
agent_name="flight_assistant",
|
||||
description="Transfer user to the flight-booking assistant.",
|
||||
)
|
||||
|
||||
flight_assistant = create_react_agent(
|
||||
model="anthropic:claude-3-5-sonnet-latest",
|
||||
# highlight-next-line
|
||||
tools=[book_flight, transfer_to_hotel_assistant],
|
||||
prompt="You are a flight booking assistant",
|
||||
# highlight-next-line
|
||||
name="flight_assistant"
|
||||
)
|
||||
hotel_assistant = create_react_agent(
|
||||
model="anthropic:claude-3-5-sonnet-latest",
|
||||
# highlight-next-line
|
||||
tools=[book_hotel, transfer_to_flight_assistant],
|
||||
prompt="You are a hotel booking assistant",
|
||||
# highlight-next-line
|
||||
name="hotel_assistant"
|
||||
)
|
||||
|
||||
# highlight-next-line
|
||||
swarm = create_swarm(
|
||||
agents=[flight_assistant, hotel_assistant],
|
||||
default_active_agent="flight_assistant"
|
||||
).compile()
|
||||
|
||||
for chunk in swarm.stream(
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "book a flight from BOS to JFK and a stay at McKittrick Hotel"
|
||||
}
|
||||
]
|
||||
}
|
||||
):
|
||||
print(chunk)
|
||||
print("\n")
|
||||
```
|
||||
|
||||
## Handoffs
|
||||
|
||||
A common pattern in multi-agent interactions is **handoffs**, where one agent *hands off* control to another. Handoffs allow you to specify:
|
||||
|
||||
- **destination**: target agent to navigate to
|
||||
- **payload**: information to pass to that agent
|
||||
|
||||
This is used both by `langgraph-supervisor` (supervisor hands off to individual agents) and `langgraph-swarm` (an individual agent can hand off to other agents).
|
||||
|
||||
To implement handoffs with `create_react_agent`, you need to:
|
||||
|
||||
1. Create a special tool that can transfer control to a different agent
|
||||
|
||||
```python
|
||||
def transfer_to_bob():
|
||||
"""Transfer to bob."""
|
||||
return Command(
|
||||
# name of the agent (node) to go to
|
||||
# highlight-next-line
|
||||
goto="bob",
|
||||
# data to send to the agent
|
||||
# highlight-next-line
|
||||
update={"messages": [...]},
|
||||
# indicate to LangGraph that we need to navigate to
|
||||
# agent node in a parent graph
|
||||
# highlight-next-line
|
||||
graph=Command.PARENT,
|
||||
)
|
||||
```
|
||||
|
||||
1. Create individual agents that have access to handoff tools:
|
||||
|
||||
```python
|
||||
flight_assistant = create_react_agent(
|
||||
..., tools=[book_flight, transfer_to_hotel_assistant]
|
||||
)
|
||||
hotel_assistant = create_react_agent(
|
||||
..., tools=[book_hotel, transfer_to_flight_assistant]
|
||||
)
|
||||
```
|
||||
|
||||
1. Define a parent graph that contains individual agents as nodes:
|
||||
|
||||
```python
|
||||
from langgraph.graph import StateGraph, MessagesState
|
||||
multi_agent_graph = (
|
||||
StateGraph(MessagesState)
|
||||
.add_node(flight_assistant)
|
||||
.add_node(hotel_assistant)
|
||||
...
|
||||
)
|
||||
```
|
||||
|
||||
Putting this together, here is how you can implement a simple multi-agent system with two agents — a flight booking assistant and a hotel booking assistant:
|
||||
|
||||
```python
|
||||
from typing import Annotated
|
||||
from langchain_core.tools import tool, InjectedToolCallId
|
||||
from langgraph.prebuilt import create_react_agent, InjectedState
|
||||
from langgraph.graph import StateGraph, START, MessagesState
|
||||
from langgraph.types import Command
|
||||
|
||||
def create_handoff_tool(*, agent_name: str, description: str | None = None):
|
||||
name = f"transfer_to_{agent_name}"
|
||||
description = description or f"Transfer to {agent_name}"
|
||||
|
||||
@tool(name, description=description)
|
||||
def handoff_tool(
|
||||
# highlight-next-line
|
||||
state: Annotated[MessagesState, InjectedState], # (1)!
|
||||
# highlight-next-line
|
||||
tool_call_id: Annotated[str, InjectedToolCallId],
|
||||
) -> Command:
|
||||
tool_message = {
|
||||
"role": "tool",
|
||||
"content": f"Successfully transferred to {agent_name}",
|
||||
"name": name,
|
||||
"tool_call_id": tool_call_id,
|
||||
}
|
||||
return Command( # (2)!
|
||||
# highlight-next-line
|
||||
goto=agent_name, # (3)!
|
||||
# highlight-next-line
|
||||
update={"messages": state["messages"] + [tool_message]}, # (4)!
|
||||
# highlight-next-line
|
||||
graph=Command.PARENT, # (5)!
|
||||
)
|
||||
return handoff_tool
|
||||
|
||||
# Handoffs
|
||||
transfer_to_hotel_assistant = create_handoff_tool(
|
||||
agent_name="hotel_assistant",
|
||||
description="Transfer user to the hotel-booking assistant.",
|
||||
)
|
||||
transfer_to_flight_assistant = create_handoff_tool(
|
||||
agent_name="flight_assistant",
|
||||
description="Transfer user to the flight-booking assistant.",
|
||||
)
|
||||
|
||||
# Simple agent tools
|
||||
def book_hotel(hotel_name: str):
|
||||
"""Book a hotel"""
|
||||
return f"Successfully booked a stay at {hotel_name}."
|
||||
|
||||
def book_flight(from_airport: str, to_airport: str):
|
||||
"""Book a flight"""
|
||||
return f"Successfully booked a flight from {from_airport} to {to_airport}."
|
||||
|
||||
# Define agents
|
||||
flight_assistant = create_react_agent(
|
||||
model="anthropic:claude-3-5-sonnet-latest",
|
||||
# highlight-next-line
|
||||
tools=[book_flight, transfer_to_hotel_assistant],
|
||||
prompt="You are a flight booking assistant",
|
||||
# highlight-next-line
|
||||
name="flight_assistant"
|
||||
)
|
||||
hotel_assistant = create_react_agent(
|
||||
model="anthropic:claude-3-5-sonnet-latest",
|
||||
# highlight-next-line
|
||||
tools=[book_hotel, transfer_to_flight_assistant],
|
||||
prompt="You are a hotel booking assistant",
|
||||
# highlight-next-line
|
||||
name="hotel_assistant"
|
||||
)
|
||||
|
||||
# Define multi-agent graph
|
||||
multi_agent_graph = (
|
||||
StateGraph(MessagesState)
|
||||
.add_node(flight_assistant)
|
||||
.add_node(hotel_assistant)
|
||||
.add_edge(START, "flight_assistant")
|
||||
.compile()
|
||||
)
|
||||
|
||||
# Run the multi-agent graph
|
||||
for chunk in multi_agent_graph.stream(
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "book a flight from BOS to JFK and a stay at McKittrick Hotel"
|
||||
}
|
||||
]
|
||||
}
|
||||
):
|
||||
print(chunk)
|
||||
print("\n")
|
||||
```
|
||||
|
||||
1. Access agent's state
|
||||
2. The `Command` primitive allows specifying a state update and a node transition as a single operation, making it useful for implementing handoffs.
|
||||
3. Name of the agent or node to hand off to.
|
||||
4. Take the agent's messages and **add** them to the parent's **state** as part of the handoff. The next agent will see the parent state.
|
||||
5. Indicate to LangGraph that we need to navigate to agent node in a **parent** multi-agent graph.
|
||||
|
||||
!!! Note
|
||||
This handoff implementation assumes that:
|
||||
|
||||
- each agent receives overall message history (across all agents) in the multi-agent system as its input
|
||||
- each agent outputs its internal messages history to the overall message history of the multi-agent system
|
||||
|
||||
Check out LangGraph [supervisor](https://github.com/langchain-ai/langgraph-supervisor-py#customizing-handoff-tools) and [swarm](https://github.com/langchain-ai/langgraph-swarm-py#customizing-handoff-tools) documentation to learn how to customize handoffs.
|
||||
@@ -0,0 +1,38 @@
|
||||
---
|
||||
title: Overview
|
||||
---
|
||||
|
||||
# Agent development with LangGraph
|
||||
|
||||
**LangGraph** provides both low-level primitives and high-level prebuilt components for building agent-based applications. This section focuses on the **prebuilt**, **reusable** components designed to help you construct agentic systems quickly and reliably—without the need to implement orchestration, memory, or human feedback handling from scratch.
|
||||
|
||||
## Key features
|
||||
|
||||
LangGraph includes several capabilities essential for building robust, production-ready agentic systems:
|
||||
|
||||
- [**Memory integration**](./memory.md): Native support for *short-term* (session-based) and *long-term* (persistent across sessions) memory, enabling stateful behaviors in chatbots and assistants.
|
||||
- [**Human-in-the-loop control**](./human-in-the-loop.md): Execution can pause *indefinitely* to await human feedback—unlike websocket-based solutions limited to real-time interaction. This enables asynchronous approval, correction, or intervention at any point in the workflow.
|
||||
- [**Streaming support**](./streaming.md): Real-time streaming of agent state, model tokens, tool outputs, or combined streams.
|
||||
- [**Deployment tooling**](./deployment.md): Includes infrastructure-free deployment tools. [**LangGraph Platform**](https://langchain-ai.github.io/langgraph/concepts/langgraph_platform/) supports testing, debugging, and deployment.
|
||||
- **[Studio](https://langchain-ai.github.io/langgraph/concepts/langgraph_studio/)**: A visual IDE for inspecting and debugging workflows.
|
||||
- Supports multiple [**deployment options**](https://langchain-ai.github.io/langgraph/tutorials/deployment/) for production.
|
||||
|
||||
## High-level building blocks
|
||||
|
||||
LangGraph comes with a set of prebuilt components that implement common agent behaviors and workflows. These abstractions are built on top of the LangGraph framework, offering a faster path to production while remaining flexible for advanced customization.
|
||||
|
||||
Using LangGraph for agent development allows you to focus on your application's logic and behavior, instead of building and maintaining the supporting infrastructure for state, memory, and human feedback.
|
||||
|
||||
## Package ecosystem
|
||||
|
||||
The high-level components are organized into several packages, each with a specific focus.
|
||||
|
||||
| Package | Description | Installation |
|
||||
|--------------------------------------------|-----------------------------------------------------------------------------|-----------------------------------------|
|
||||
| `langgraph-prebuilt` (part of `langgraph`) | Prebuilt components to [**create agents**](./agents.md) | `pip install -U langgraph langchain` |
|
||||
| `langgraph-supervisor` | Tools for building [**supervisor**](./multi-agent.md#supervisor) agents | `pip install -U langgraph-supervisor` |
|
||||
| `langgraph-swarm` | Tools for building a [**swarm**](./multi-agent.md#swarm) multi-agent system | `pip install -U langgraph-swarm` |
|
||||
| `langchain-mcp-adapters` | Interfaces to [**MCP servers**](./mcp.md) for tool and resource integration | `pip install -U langchain-mcp-adapters` |
|
||||
| `langmem` | Agent memory management: [**short-term and long-term**](./memory.md) | `pip install -U langmem` |
|
||||
| `agentevals` | Utilities to [**evaluate agent performance**](./evals.md) | `pip install -U agentevals` |
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# 🚀 Prebuilt Agents
|
||||
# Community Agents
|
||||
|
||||
To share your project, simply open a Pull Request adding an entry for your package in our [packages.yml](https://github.com/langchain-ai/langgraph/blob/main/docs/_scripts/third_party_page/packages.yml) file.
|
||||
|
||||
@@ -0,0 +1,159 @@
|
||||
# Running agents
|
||||
|
||||
|
||||
Agents support both synchronous and asynchronous execution using either `.invoke()` / `await .invoke()` for full responses, or `.stream()` / `.astream()` for **incremental** [streaming](#streaming) output. This section explains how to provide input, interpret output, enable streaming, and control execution limits.
|
||||
|
||||
|
||||
## Basic usage
|
||||
|
||||
Agents can be executed in two primary modes:
|
||||
|
||||
- **Synchronous** using `.invoke()` or `.stream()`
|
||||
- **Asynchronous** using `await .invoke()` or `async for` with `.astream()`
|
||||
|
||||
=== "Sync invocation"
|
||||
```python
|
||||
from langgraph.prebuilt import create_react_agent
|
||||
|
||||
agent = create_react_agent(...)
|
||||
|
||||
# highlight-next-line
|
||||
response = agent.invoke({"messages": [{"role": "user", "content": "what is the weather in sf"}]})
|
||||
```
|
||||
|
||||
=== "Async invocation"
|
||||
```python
|
||||
from langgraph.prebuilt import create_react_agent
|
||||
|
||||
agent = create_react_agent(...)
|
||||
# highlight-next-line
|
||||
response = await agent.ainvoke({"messages": [{"role": "user", "content": "what is the weather in sf"}]})
|
||||
```
|
||||
|
||||
## Inputs and outputs
|
||||
|
||||
Agents use a language model that expects a list of `messages` as an input. Therefore, agent inputs and outputs are stored as a list of `messages` under the `messages` key in the agent [state](../concepts/low_level.md#working-with-messages-in-graph-state).
|
||||
|
||||
## Input format
|
||||
|
||||
Agent input must be a dictionary with a `messages` key. Supported formats are:
|
||||
|
||||
| Format | Example |
|
||||
|--------------------|-------------------------------------------------------------------------------------------------------------------------------|
|
||||
| String | `{"messages": "Hello"}` — Interpreted as a [HumanMessage](https://python.langchain.com/docs/concepts/messages/#humanmessage) |
|
||||
| Message dictionary | `{"messages": {"role": "user", "content": "Hello"}}` |
|
||||
| List of messages | `{"messages": [{"role": "user", "content": "Hello"}]}` |
|
||||
| With custom state | `{"messages": [{"role": "user", "content": "Hello"}], "user_name": "Alice"}` — If using a custom `state_schema` |
|
||||
|
||||
Messages are automatically converted into LangChain's internal message format. You can read
|
||||
more about [LangChain messages](https://python.langchain.com/docs/concepts/messages/#langchain-messages) in the LangChain documentation.
|
||||
|
||||
!!! tip "Using custom agent state"
|
||||
|
||||
You can provide additional fields defined in your agent’s state schema directly in the input dictionary. This allows dynamic behavior based on runtime data or prior tool outputs.
|
||||
See the [context guide](./context.md) for full details.
|
||||
|
||||
!!! note
|
||||
|
||||
A string input for `messages` is converted to a [HumanMessage](https://python.langchain.com/docs/concepts/messages/#humanmessage). This behavior differs from the `prompt` parameter in `create_react_agent`, which is interpreted as a [SystemMessage](https://python.langchain.com/docs/concepts/messages/#systemmessage) when passed as a string.
|
||||
|
||||
|
||||
## Output format
|
||||
|
||||
Agent output is a dictionary containing:
|
||||
|
||||
- `messages`: A list of all messages exchanged during execution (user input, assistant replies, tool invocations).
|
||||
- Optionally, `structured_response` if [structured output](./agents.md#structured-output) is configured.
|
||||
- If using a custom `state_schema`, additional keys corresponding to your defined fields may also be present in the output. These can hold updated state values from tool execution or prompt logic.
|
||||
|
||||
See the [context guide](./context.md) for more details on working with custom state schemas and accessing context.
|
||||
|
||||
## Streaming output
|
||||
|
||||
Agents support streaming responses for more responsive applications. This includes:
|
||||
|
||||
- **Progress updates** after each step
|
||||
- **LLM tokens** as they're generated
|
||||
- **Custom tool messages** during execution
|
||||
|
||||
Streaming is available in both sync and async modes:
|
||||
|
||||
=== "Sync streaming"
|
||||
|
||||
```python
|
||||
for chunk in agent.stream(
|
||||
{"messages": [{"role": "user", "content": "what is the weather in sf"}]},
|
||||
stream_mode="updates"
|
||||
):
|
||||
print(chunk)
|
||||
```
|
||||
|
||||
=== "Async streaming"
|
||||
|
||||
```python
|
||||
async for chunk in agent.astream(
|
||||
{"messages": [{"role": "user", "content": "what is the weather in sf"}]},
|
||||
stream_mode="updates"
|
||||
):
|
||||
print(chunk)
|
||||
```
|
||||
|
||||
!!! tip
|
||||
|
||||
For full details, see the [streaming guide](./streaming.md).
|
||||
|
||||
## Max iterations
|
||||
|
||||
To control agent execution and avoid infinite loops, set a recursion limit. This defines the maximum number of steps the agent can take before raising a `GraphRecursionError`. You can configure `recursion_limit` at runtime or when defining agent via `.with_config()`:
|
||||
|
||||
=== "Runtime"
|
||||
|
||||
```python
|
||||
from langgraph.errors import GraphRecursionError
|
||||
from langgraph.prebuilt import create_react_agent
|
||||
|
||||
max_iterations = 3
|
||||
# highlight-next-line
|
||||
recursion_limit = 2 * max_iterations + 1
|
||||
agent = create_react_agent(
|
||||
model="anthropic:claude-3-5-haiku-latest",
|
||||
tools=[get_weather]
|
||||
)
|
||||
|
||||
try:
|
||||
response = agent.invoke(
|
||||
{"messages": [{"role": "user", "content": "what's the weather in sf"}]},
|
||||
# highlight-next-line
|
||||
{"recursion_limit": recursion_limit},
|
||||
)
|
||||
except GraphRecursionError:
|
||||
print("Agent stopped due to max iterations.")
|
||||
```
|
||||
|
||||
=== "`.with_config()`"
|
||||
|
||||
```python
|
||||
from langgraph.errors import GraphRecursionError
|
||||
from langgraph.prebuilt import create_react_agent
|
||||
|
||||
max_iterations = 3
|
||||
# highlight-next-line
|
||||
recursion_limit = 2 * max_iterations + 1
|
||||
agent = create_react_agent(
|
||||
model="anthropic:claude-3-5-haiku-latest",
|
||||
tools=[get_weather]
|
||||
)
|
||||
# highlight-next-line
|
||||
agent_with_recursion_limit = agent.with_config(recursion_limit=recursion_limit)
|
||||
|
||||
try:
|
||||
response = agent_with_recursion_limit.invoke(
|
||||
{"messages": [{"role": "user", "content": "what's the weather in sf"}]},
|
||||
)
|
||||
except GraphRecursionError:
|
||||
print("Agent stopped due to max iterations.")
|
||||
```
|
||||
|
||||
## Additional Resources
|
||||
|
||||
* [Async programming in LangChain](https://python.langchain.com/docs/concepts/async)
|
||||
@@ -0,0 +1,208 @@
|
||||
# Streaming
|
||||
|
||||
Streaming is key to building responsive applications. There are a few types of data you’ll want to stream:
|
||||
|
||||
1. [**Agent progress**](#agent-progress) — get updates after each node in the agent graph is executed.
|
||||
2. [**LLM tokens**](#llm-tokens) — stream tokens as they are generated by the language model.
|
||||
3. [**Custom updates**](#tool-updates) — emit custom data from tools during execution (e.g., "Fetched 10/100 records")
|
||||
|
||||
You can stream [more than one type of data](#stream-multiple-modes) at a time.
|
||||
|
||||
|
||||
<figure markdown="1">
|
||||
{: style="max-height:300px"}
|
||||
<figcaption>
|
||||
Waiting is for pigeons.
|
||||
</figcaption>
|
||||
</figure>
|
||||
|
||||
## Agent progress
|
||||
|
||||
To stream agent progress, use the [`stream()`][langgraph.graph.state.CompiledStateGraph.stream] or [`astream()`][langgraph.graph.state.CompiledStateGraph.astream] methods with [`stream_mode="updates"`](https://langchain-ai.github.io/langgraph/how-tos/streaming/#updates). This emits an event after every agent step.
|
||||
|
||||
For example, if you have an agent that calls a tool once, you should see the following updates:
|
||||
|
||||
* **LLM node**: AI message with tool call requests
|
||||
* **Tool node**: Tool message with execution result
|
||||
* **LLM node**: Final AI response
|
||||
|
||||
=== "Sync"
|
||||
|
||||
```python
|
||||
agent = create_react_agent(
|
||||
model="anthropic:claude-3-7-sonnet-latest",
|
||||
tools=[get_weather],
|
||||
)
|
||||
# highlight-next-line
|
||||
for chunk in agent.stream(
|
||||
{"messages": [{"role": "user", "content": "what is the weather in sf"}]},
|
||||
# highlight-next-line
|
||||
stream_mode="updates"
|
||||
):
|
||||
print(chunk)
|
||||
print("\n")
|
||||
```
|
||||
|
||||
=== "Async"
|
||||
|
||||
```python
|
||||
agent = create_react_agent(
|
||||
model="anthropic:claude-3-7-sonnet-latest",
|
||||
tools=[get_weather],
|
||||
)
|
||||
# highlight-next-line
|
||||
async for chunk in agent.astream(
|
||||
{"messages": [{"role": "user", "content": "what is the weather in sf"}]},
|
||||
# highlight-next-line
|
||||
stream_mode="updates"
|
||||
):
|
||||
print(chunk)
|
||||
print("\n")
|
||||
```
|
||||
|
||||
## LLM tokens
|
||||
|
||||
To stream tokens as they are produced by the LLM, use `stream_mode="messages"`:
|
||||
|
||||
=== "Sync"
|
||||
|
||||
```python
|
||||
agent = create_react_agent(
|
||||
model="anthropic:claude-3-7-sonnet-latest",
|
||||
tools=[get_weather],
|
||||
)
|
||||
# highlight-next-line
|
||||
for token, metadata in agent.stream(
|
||||
{"messages": [{"role": "user", "content": "what is the weather in sf"}]},
|
||||
# highlight-next-line
|
||||
stream_mode="messages"
|
||||
):
|
||||
print("Token", token)
|
||||
print("Metadata", metadata)
|
||||
print("\n")
|
||||
```
|
||||
|
||||
=== "Async"
|
||||
|
||||
```python
|
||||
agent = create_react_agent(
|
||||
model="anthropic:claude-3-7-sonnet-latest",
|
||||
tools=[get_weather],
|
||||
)
|
||||
# highlight-next-line
|
||||
async for token, metadata in agent.astream(
|
||||
{"messages": [{"role": "user", "content": "what is the weather in sf"}]},
|
||||
# highlight-next-line
|
||||
stream_mode="messages"
|
||||
):
|
||||
print("Token", token)
|
||||
print("Metadata", metadata)
|
||||
print("\n")
|
||||
```
|
||||
|
||||
## Tool updates
|
||||
|
||||
To stream updates from tools as they are executed, you can use [get_stream_writer][langgraph.config.get_stream_writer].
|
||||
|
||||
=== "Sync"
|
||||
|
||||
```python
|
||||
# highlight-next-line
|
||||
from langgraph.config import get_stream_writer
|
||||
|
||||
def get_weather(city: str) -> str:
|
||||
"""Get weather for a given city."""
|
||||
# highlight-next-line
|
||||
writer = get_stream_writer()
|
||||
# stream any arbitrary data
|
||||
# highlight-next-line
|
||||
writer(f"Looking up data for city: {city}")
|
||||
return f"It's always sunny in {city}!"
|
||||
|
||||
agent = create_react_agent(
|
||||
model="anthropic:claude-3-7-sonnet-latest",
|
||||
tools=[get_weather],
|
||||
)
|
||||
|
||||
for chunk in agent.stream(
|
||||
{"messages": [{"role": "user", "content": "what is the weather in sf"}]},
|
||||
# highlight-next-line
|
||||
stream_mode="custom"
|
||||
):
|
||||
print(chunk)
|
||||
print("\n")
|
||||
```
|
||||
|
||||
=== "Async"
|
||||
|
||||
```python
|
||||
# highlight-next-line
|
||||
from langgraph.config import get_stream_writer
|
||||
|
||||
def get_weather(city: str) -> str:
|
||||
"""Get weather for a given city."""
|
||||
# highlight-next-line
|
||||
writer = get_stream_writer()
|
||||
# stream any arbitrary data
|
||||
# highlight-next-line
|
||||
writer(f"Looking up data for city: {city}")
|
||||
return f"It's always sunny in {city}!"
|
||||
|
||||
agent = create_react_agent(
|
||||
model="anthropic:claude-3-7-sonnet-latest",
|
||||
tools=[get_weather],
|
||||
)
|
||||
|
||||
async for chunk in agent.astream(
|
||||
{"messages": [{"role": "user", "content": "what is the weather in sf"}]},
|
||||
# highlight-next-line
|
||||
stream_mode="custom"
|
||||
):
|
||||
print(chunk)
|
||||
print("\n")
|
||||
```
|
||||
|
||||
!!! Note
|
||||
If you add `get_stream_writer` inside your tool, you won't be able to invoke the tool outside of a LangGraph execution context.
|
||||
|
||||
## Stream multiple modes
|
||||
|
||||
You can specify multiple streaming modes by passing stream mode as a list: `stream_mode=["updates", "messages", "custom"]`:
|
||||
|
||||
=== "Sync"
|
||||
|
||||
```python
|
||||
agent = create_react_agent(
|
||||
model="anthropic:claude-3-7-sonnet-latest",
|
||||
tools=[get_weather],
|
||||
)
|
||||
|
||||
for stream_mode, chunk in agent.stream(
|
||||
{"messages": [{"role": "user", "content": "what is the weather in sf"}]},
|
||||
# highlight-next-line
|
||||
stream_mode=["updates", "messages", "custom"]
|
||||
):
|
||||
print(chunk)
|
||||
print("\n")
|
||||
```
|
||||
|
||||
=== "Async"
|
||||
|
||||
```python
|
||||
agent = create_react_agent(
|
||||
model="anthropic:claude-3-7-sonnet-latest",
|
||||
tools=[get_weather],
|
||||
)
|
||||
|
||||
async for stream_mode, chunk in agent.astream(
|
||||
{"messages": [{"role": "user", "content": "what is the weather in sf"}]},
|
||||
# highlight-next-line
|
||||
stream_mode=["updates", "messages", "custom"]
|
||||
):
|
||||
print(chunk)
|
||||
print("\n")
|
||||
```
|
||||
|
||||
## Additional resources
|
||||
|
||||
* [Streaming in LangGraph](https://langchain-ai.github.io/langgraph/how-tos/streaming)
|
||||
@@ -0,0 +1,280 @@
|
||||
# Tools
|
||||
|
||||
[Tools](https://python.langchain.com/docs/concepts/tools/) are a way to encapsulate a function and its input schema in a way that can be passed to a chat model that supports tool calling. This allows the model to request the execution of this function with specific inputs.
|
||||
|
||||
You can either [define your own tools](#define-simple-tools) or use [prebuilt integrations](#prebuilt-tools) that LangChain provides.
|
||||
|
||||
## Define simple tools
|
||||
|
||||
You can pass a vanilla function to `create_react_agent` to use as a tool:
|
||||
|
||||
```python
|
||||
from langgraph.prebuilt import create_react_agent
|
||||
|
||||
def multiply(a: int, b: int) -> int:
|
||||
"""Multiply two numbers."""
|
||||
return a * b
|
||||
|
||||
create_react_agent(
|
||||
model="anthropic:claude-3-7-sonnet",
|
||||
tools=[multiply]
|
||||
)
|
||||
```
|
||||
|
||||
`create_react_agent` automatically converts vanilla functions to [LangChain tools](https://python.langchain.com/docs/concepts/tools/#tool-interface).
|
||||
|
||||
## Customize tools
|
||||
|
||||
For more control over tool behavior, use the `@tool` decorator:
|
||||
|
||||
```python
|
||||
# highlight-next-line
|
||||
from langchain_core.tools import tool
|
||||
|
||||
# highlight-next-line
|
||||
@tool("multiply_tool", parse_docstring=True)
|
||||
def multiply(a: int, b: int) -> int:
|
||||
"""Multiply two numbers.
|
||||
|
||||
Args:
|
||||
a: First operand
|
||||
b: Second operand
|
||||
"""
|
||||
return a * b
|
||||
```
|
||||
|
||||
You can also define a custom input schema using Pydantic:
|
||||
|
||||
```python
|
||||
from pydantic import BaseModel, Field
|
||||
|
||||
class MultiplyInputSchema(BaseModel):
|
||||
"""Multiply two numbers"""
|
||||
a: int = Field(description="First operand")
|
||||
b: int = Field(description="Second operand")
|
||||
|
||||
# highlight-next-line
|
||||
@tool("multiply_tool", args_schema=MultiplyInputSchema)
|
||||
def multiply(a: int, b: int) -> int:
|
||||
return a * b
|
||||
```
|
||||
|
||||
For additional customization, refer to the [custom tools guide](https://python.langchain.com/docs/how_to/custom_tools/).
|
||||
|
||||
## Hide arguments from the model
|
||||
|
||||
Some tools require runtime-only arguments (e.g., user ID or session context) that should not be controllable by the model.
|
||||
|
||||
You can put these arguments in the `state` or `config` of the agent, and access
|
||||
this information inside the tool:
|
||||
|
||||
```python
|
||||
from langgraph.prebuilt import InjectedState
|
||||
from langgraph.prebuilt.chat_agent_executor import AgentState
|
||||
from langchain_core.runnables import RunnableConfig
|
||||
|
||||
def my_tool(
|
||||
# This will be populated by an LLM
|
||||
tool_arg: str,
|
||||
# access information that's dynamically updated inside the agent
|
||||
# highlight-next-line
|
||||
state: Annotated[AgentState, InjectedState],
|
||||
# access static data that is passed at agent invocation
|
||||
# highlight-next-line
|
||||
config: RunnableConfig,
|
||||
) -> str:
|
||||
"""My tool."""
|
||||
do_something_with_state(state["messages"])
|
||||
do_something_with_config(config)
|
||||
...
|
||||
```
|
||||
|
||||
## Disable parallel tool calling
|
||||
|
||||
Some model providers support executing multiple tools in parallel, but
|
||||
allow users to disable this feature.
|
||||
|
||||
For supported providers, you can disable parallel tool calling by setting `parallel_tool_calls=False` via the `model.bind_tools()` method:
|
||||
|
||||
```python
|
||||
from langchain.chat_models import init_chat_model
|
||||
|
||||
def add(a: int, b: int) -> int:
|
||||
"""Add two numbers"""
|
||||
return a + b
|
||||
|
||||
def multiply(a: int, b: int) -> int:
|
||||
"""Multiply two numbers."""
|
||||
return a * b
|
||||
|
||||
model = init_chat_model("anthropic:claude-3-5-sonnet-latest", temperature=0)
|
||||
tools = [add, multiply]
|
||||
agent = create_react_agent(
|
||||
# disable parallel tool calls
|
||||
# highlight-next-line
|
||||
model=model.bind_tools(tools, parallel_tool_calls=False),
|
||||
tools=tools
|
||||
)
|
||||
|
||||
agent.invoke(
|
||||
{"messages": [{"role": "user", "content": "what's 3 + 5 and 4 * 7?"}]}
|
||||
)
|
||||
```
|
||||
|
||||
## Return tool results directly
|
||||
|
||||
Use `return_direct=True` to return tool results immediately and stop the agent loop:
|
||||
|
||||
```python
|
||||
from langchain_core.tools import tool
|
||||
|
||||
# highlight-next-line
|
||||
@tool(return_direct=True)
|
||||
def add(a: int, b: int) -> int:
|
||||
"""Add two numbers"""
|
||||
return a + b
|
||||
|
||||
agent = create_react_agent(
|
||||
model="anthropic:claude-3-7-sonnet-latest",
|
||||
tools=[add]
|
||||
)
|
||||
|
||||
agent.invoke(
|
||||
{"messages": [{"role": "user", "content": "what's 3 + 5?"}]}
|
||||
)
|
||||
```
|
||||
|
||||
## Force tool use
|
||||
|
||||
To force the agent to use specific tools, you can set the `tool_choice` option in `model.bind_tools()`:
|
||||
|
||||
```python
|
||||
from langchain_core.tools import tool
|
||||
|
||||
# highlight-next-line
|
||||
@tool(return_direct=True)
|
||||
def greet(user_name: str) -> int:
|
||||
"""Greet user."""
|
||||
return f"Hello {user_name}!"
|
||||
|
||||
tools = [greet]
|
||||
|
||||
agent = create_react_agent(
|
||||
# highlight-next-line
|
||||
model=model.bind_tools(tools, tool_choice={"type": "tool", "name": "greet"}),
|
||||
tools=tools
|
||||
)
|
||||
|
||||
agent.invoke(
|
||||
{"messages": [{"role": "user", "content": "Hi, I am Bob"}]}
|
||||
)
|
||||
```
|
||||
|
||||
!!! Warning "Avoid infinite loops"
|
||||
|
||||
Forcing tool usage without stopping conditions can create infinite loops. Use one of the following safeguards:
|
||||
|
||||
- Mark the tool with [`return_direct=True`](#return-tool-results-directly) to end the loop after execution.
|
||||
- Set [`recursion_limit`](../concepts/low_level.md#recursion-limit) to restrict the number of execution steps.
|
||||
|
||||
## Handle tool errors
|
||||
|
||||
By default, the agent will catch all exceptions raised during tool calls and will pass those as tool messages to the LLM. To control how the errors are handled, you can use the prebuilt [`ToolNode`][langgraph.prebuilt.tool_node.ToolNode] — the node that executes tools inside `create_react_agent` — via its `handle_tool_errors` parameter:
|
||||
|
||||
=== "Enable error handling (default)"
|
||||
|
||||
```python
|
||||
from langgraph.prebuilt import create_react_agent
|
||||
|
||||
def multiply(a: int, b: int) -> int:
|
||||
"""Multiply two numbers."""
|
||||
if a == 42:
|
||||
raise ValueError("The ultimate error")
|
||||
return a * b
|
||||
|
||||
# Run with error handling (default)
|
||||
agent = create_react_agent(
|
||||
model="anthropic:claude-3-7-sonnet-latest",
|
||||
tools=[multiply]
|
||||
)
|
||||
agent.invoke(
|
||||
{"messages": [{"role": "user", "content": "what's 42 x 7?"}]}
|
||||
)
|
||||
```
|
||||
|
||||
=== "Disable error handling"
|
||||
|
||||
```python
|
||||
from langgraph.prebuilt import create_react_agent, ToolNode
|
||||
|
||||
def multiply(a: int, b: int) -> int:
|
||||
"""Multiply two numbers."""
|
||||
if a == 42:
|
||||
raise ValueError("The ultimate error")
|
||||
return a * b
|
||||
|
||||
# highlight-next-line
|
||||
tool_node = ToolNode(
|
||||
[multiply],
|
||||
# highlight-next-line
|
||||
handle_tool_errors=False # (1)!
|
||||
)
|
||||
agent_no_error_handling = create_react_agent(
|
||||
model="anthropic:claude-3-7-sonnet-latest",
|
||||
tools=tool_node
|
||||
)
|
||||
agent_no_error_handling.invoke(
|
||||
{"messages": [{"role": "user", "content": "what's 42 x 7?"}]}
|
||||
)
|
||||
```
|
||||
|
||||
1. This disables error handling (enabled by default). See all available strategies in the [API reference][langgraph.prebuilt.tool_node.ToolNode].
|
||||
|
||||
=== "Custom error handling"
|
||||
|
||||
```python
|
||||
from langgraph.prebuilt import create_react_agent, ToolNode
|
||||
|
||||
def multiply(a: int, b: int) -> int:
|
||||
"""Multiply two numbers."""
|
||||
if a == 42:
|
||||
raise ValueError("The ultimate error")
|
||||
return a * b
|
||||
|
||||
# highlight-next-line
|
||||
tool_node = ToolNode(
|
||||
[multiply],
|
||||
# highlight-next-line
|
||||
handle_tool_errors=(
|
||||
"Can't use 42 as a first operand, you must switch operands!" # (1)!
|
||||
)
|
||||
)
|
||||
agent_custom_error_handling = create_react_agent(
|
||||
model="anthropic:claude-3-7-sonnet-latest",
|
||||
tools=tool_node
|
||||
)
|
||||
agent_custom_error_handling.invoke(
|
||||
{"messages": [{"role": "user", "content": "what's 42 x 7?"}]}
|
||||
)
|
||||
```
|
||||
|
||||
1. This provides a custom message to send to the LLM in case of an exception. See all available strategies in the [API reference][langgraph.prebuilt.tool_node.ToolNode].
|
||||
|
||||
See [API reference][langgraph.prebuilt.tool_node.ToolNode] for more information on different tool error handling options.
|
||||
|
||||
## Prebuilt tools
|
||||
|
||||
LangChain supports a wide range of prebuilt tool integrations for interacting with APIs, databases, file systems, web data, and more. These tools extend the functionality of agents and enable rapid development.
|
||||
|
||||
You can browse the full list of available integrations in the [LangChain integrations directory](https://python.langchain.com/docs/integrations/tools/).
|
||||
|
||||
Some commonly used tool categories include:
|
||||
|
||||
- **Search**: Bing, SerpAPI, Tavily
|
||||
- **Code interpreters**: Python REPL, Node.js REPL
|
||||
- **Databases**: SQL, MongoDB, Redis
|
||||
- **Web data**: Web scraping and browsing
|
||||
- **APIs**: OpenWeatherMap, NewsAPI, and others
|
||||
|
||||
These integrations can be configured and added to your agents using the same `tools` parameter shown in the examples above.
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
# UI
|
||||
|
||||
You can use a prebuilt chat UI for interacting with any LangGraph agent through the [Agent Chat UI](https://github.com/langchain-ai/agent-chat-ui). Using the [deployed version](https://agentchat.vercel.app) is the quickest way to get started, and allows you to interact with both local and deployed graphs.
|
||||
|
||||
## Run agent in UI
|
||||
|
||||
First, set up LangGraph API server [locally](./deployment.md#launch-langgraph-server-locally) or deploy your agent on [LangGraph Cloud](https://langchain-ai.github.io/langgraph/cloud/quick_start/).
|
||||
|
||||
Then, navigate to [Agent Chat UI](https://agentchat.vercel.app), or clone the repository and [run the dev server locally](https://github.com/langchain-ai/agent-chat-ui?tab=readme-ov-file#setup):
|
||||
|
||||
<video controls src="../assets/base-chat-ui.mp4" type="video/mp4"></video>
|
||||
|
||||
!!! Tip
|
||||
|
||||
UI has out-of-box support for rendering tool calls, and tool result messages. To customize what messages are shown, see the [Hiding Messages in the Chat](https://github.com/langchain-ai/agent-chat-ui?tab=readme-ov-file#hiding-messages-in-the-chat) section in the Agent Chat UI documentation.
|
||||
|
||||
## Add human-in-the-loop
|
||||
|
||||
Agent Chat UI has full support for [human-in-the-loop](../concepts/human_in_the_loop.md) workflows. To try it out, replace the agent code in `src/agent/graph.py` (from the [deployment](./deployment.md) guide) with this [agent implementation](./human-in-the-loop.md#using-with-agent-inbox):
|
||||
|
||||
<video controls src="../assets/interrupt-chat-ui.mp4" type="video/mp4"></video>
|
||||
|
||||
!!! Important
|
||||
|
||||
Agent Chat UI works best if your LangGraph agent interrupts using the [`HumanInterrupt` schema][langgraph.prebuilt.interrupt.HumanInterrupt]. If you do not use that schema, the Agent Chat UI will be able to render the input passed to the `interrupt` function, but it will not have full support for resuming your graph.
|
||||
|
||||
## Generative UI
|
||||
|
||||
You can also use generative UI in the Agent Chat UI.
|
||||
|
||||
Generative UI allows you to define [React](https://react.dev/) components, and push them to the UI from the LangGraph server. For more documentation on building generative UI LangGraph agents, read [these docs](https://langchain-ai.github.io/langgraph/cloud/how-tos/generative_ui_react/).
|
||||
@@ -1,6 +1,6 @@
|
||||
# How to Deploy to LangGraph Cloud
|
||||
# How to Deploy to Cloud SaaS (Beta)
|
||||
|
||||
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
|
||||
|
||||
|
||||
@@ -0,0 +1,56 @@
|
||||
# How to Deploy Self-Hosted Control Plane (Beta)
|
||||
|
||||
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 (Beta)
|
||||
|
||||
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!
|
||||
@@ -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".
|
||||
|
||||
{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.
|
||||
@@ -12,10 +12,6 @@ Generative user interfaces (Generative UI) allows agents to go beyond text and g
|
||||
|
||||
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.
|
||||
|
||||
!!! warning "LangGraph.js only"
|
||||
|
||||
Currently only LangGraph.js supports Generative UI. Support for Python is coming soon.
|
||||
|
||||
## Tutorial
|
||||
|
||||
### 1. Define and configure UI components
|
||||
@@ -74,58 +70,105 @@ CSS and Tailwind 4.x is also supported out of the box, so you can freely use Tai
|
||||
|
||||
### 2. Send the UI components in your graph
|
||||
|
||||
Use the `typedUi` utility to emit UI elements from your agent nodes:
|
||||
=== "Python"
|
||||
|
||||
```typescript title="src/agent/index.ts"
|
||||
import {
|
||||
typedUi,
|
||||
uiMessageReducer,
|
||||
} from "@langchain/langgraph-sdk/react-ui/server";
|
||||
```python title="src/agent.py"
|
||||
import uuid
|
||||
from typing import Annotated, Sequence, TypedDict
|
||||
|
||||
import { ChatOpenAI } from "@langchain/openai";
|
||||
import { v4 as uuidv4 } from "uuid";
|
||||
import { z } from "zod";
|
||||
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
|
||||
|
||||
import type ComponentMap from "./ui.js";
|
||||
|
||||
import {
|
||||
Annotation,
|
||||
MessagesAnnotation,
|
||||
StateGraph,
|
||||
type LangGraphRunnableConfig,
|
||||
} from "@langchain/langgraph";
|
||||
class AgentState(TypedDict): # noqa: D101
|
||||
messages: Annotated[Sequence[BaseMessage], add_messages]
|
||||
ui: Annotated[Sequence[AnyUIMessage], ui_message_reducer]
|
||||
|
||||
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);
|
||||
async def weather(state: AgentState):
|
||||
class WeatherOutput(TypedDict):
|
||||
city: str
|
||||
|
||||
const weather = await new ChatOpenAI({ model: "gpt-4o-mini" })
|
||||
.withStructuredOutput(z.object({ city: z.string() }))
|
||||
.withConfig({ tags: ["langsmith:nostream"] })
|
||||
.invoke(state.messages);
|
||||
weather: WeatherOutput = (
|
||||
await ChatOpenAI(model="gpt-4o-mini")
|
||||
.with_structured_output(WeatherOutput)
|
||||
.with_config({"tags": ["nostream"]})
|
||||
.ainvoke(state["messages"])
|
||||
)
|
||||
|
||||
const response = {
|
||||
id: uuidv4(),
|
||||
type: "ai",
|
||||
content: `Here's the weather for ${weather.city}`,
|
||||
};
|
||||
message = AIMessage(
|
||||
id=str(uuid.uuid4()),
|
||||
content=f"Here's the weather for {weather['city']}",
|
||||
)
|
||||
|
||||
// Emit UI elements with associated AI message
|
||||
ui.push({ name: "weather", props: weather }, { message: response });
|
||||
# Emit UI elements associated with the message
|
||||
push_ui_message("weather", weather, message=message)
|
||||
return {"messages": [message]}
|
||||
|
||||
return { messages: [response] };
|
||||
})
|
||||
.addEdge("__start__", "weather")
|
||||
.compile();
|
||||
```
|
||||
|
||||
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
|
||||
|
||||
@@ -294,18 +337,29 @@ const { thread, submit } = useStream({
|
||||
|
||||
### 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 `ui.delete` with the ID of the UI message.
|
||||
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.
|
||||
|
||||
```tsx
|
||||
// pushed message
|
||||
const message = ui.push({ name: "weather", props: { city: "London" } });
|
||||
=== "Python"
|
||||
|
||||
// remove said message
|
||||
ui.delete(message.id);
|
||||
```python
|
||||
from langgraph.graph.ui import push_ui_message, delete_ui_message
|
||||
|
||||
// return new state to persist changes
|
||||
return { ui: ui.items };
|
||||
```
|
||||
# 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
|
||||
|
||||
|
||||
|
After Width: | Height: | Size: 59 KiB |
@@ -1,7 +1,7 @@
|
||||
# LangGraph Studio With Local Deployment
|
||||
|
||||
!!! warning "Browser Compatibility"
|
||||
Viewing the studio page of a local LangGraph deployment does not work in Safari. Use Chrome instead.
|
||||
Safari blocks `localhost` connections to Studio. To work around this, start the server with `--tunnel` and you’ll be able to access Studio from Safari via a secure tunnel.
|
||||
|
||||
## Setup
|
||||
|
||||
|
||||
@@ -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.
|
||||
@@ -157,7 +158,7 @@ export default function HomePage() {
|
||||
}
|
||||
```
|
||||
|
||||
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.
|
||||
Under the hood, the `useStream()` hook will use the `streamMode: "messages-tuple"` 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.
|
||||
|
||||
### Interrupts
|
||||
|
||||
@@ -169,10 +170,7 @@ The `useStream()` hook exposes the `interrupt` property, which will be filled wi
|
||||
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 }
|
||||
>({
|
||||
const thread = useStream<{ messages: Message[] }, { InterruptType: string }>({
|
||||
apiUrl: "http://localhost:2024",
|
||||
assistantId: "agent",
|
||||
messagesKey: "messages",
|
||||
@@ -182,7 +180,6 @@ if (thread.interrupt) {
|
||||
return (
|
||||
<div>
|
||||
Interrupted! {thread.interrupt.value}
|
||||
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => {
|
||||
@@ -313,7 +310,7 @@ export default function App() {
|
||||
onEdit={(message) =>
|
||||
thread.submit(
|
||||
{ messages: [message] },
|
||||
{ checkpoint: parentCheckpoint },
|
||||
{ checkpoint: parentCheckpoint }
|
||||
)
|
||||
}
|
||||
/>
|
||||
@@ -370,6 +367,33 @@ 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 friendly for apps written in TypeScript and you can specify types for the state to get better type safety and IDE support.
|
||||
@@ -397,21 +421,23 @@ You can also optionally specify types for different scenarios, such as:
|
||||
- `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;
|
||||
};
|
||||
}>({
|
||||
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",
|
||||
|
||||
@@ -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": [
|
||||
|
||||
@@ -10,9 +10,6 @@ The LangGraph command line interface includes commands to build and run a LangGr
|
||||
=== "Python"
|
||||
```bash
|
||||
pip install langgraph-cli
|
||||
|
||||
# Install via Homebrew
|
||||
brew install langgraph-cli
|
||||
```
|
||||
|
||||
=== "JS"
|
||||
@@ -29,7 +26,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 +39,16 @@ 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"
|
||||
@@ -59,9 +57,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
|
||||
|
||||
@@ -82,7 +81,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"]`
|
||||
@@ -171,6 +170,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"
|
||||
|
||||
@@ -240,6 +295,11 @@ The LangGraph CLI requires a JSON configuration file with the following keys:
|
||||
| `--no-reload` | | Disable auto-reload |
|
||||
| `--n-jobs-per-worker INTEGER` | | Number of jobs per worker. Default is 10 |
|
||||
| `--debug-port INTEGER` | | Port for debugger to listen on |
|
||||
| `--wait-for-client` | `False` | Wait for a debugger client to connect to the debug port before starting the server |
|
||||
| `--no-browser` | | Skip automatically opening the browser when the server starts |
|
||||
| `--studio-url TEXT` | | URL of the LangGraph Studio instance to connect to. Defaults to https://smith.langchain.com |
|
||||
| `--allow-blocking` | `False` | Do not raise errors for synchronous I/O blocking operations in your code (added in `0.2.6`) |
|
||||
| `--tunnel` | `False` | Expose the local server via a public tunnel (Cloudflare) for remote frontend access. This avoids issues with browsers like Safari or networks blocking localhost connections |
|
||||
| `--help` | | Display command documentation |
|
||||
|
||||
|
||||
@@ -263,6 +323,11 @@ The LangGraph CLI requires a JSON configuration file with the following keys:
|
||||
| `--no-reload` | | Disable auto-reload |
|
||||
| `--n-jobs-per-worker INTEGER` | | Number of jobs per worker. Default is 10 |
|
||||
| `--debug-port INTEGER` | | Port for debugger to listen on |
|
||||
| `--wait-for-client` | `False` | Wait for a debugger client to connect to the debug port before starting the server |
|
||||
| `--no-browser` | | Skip automatically opening the browser when the server starts |
|
||||
| `--studio-url TEXT` | | URL of the LangGraph Studio instance to connect to. Defaults to https://smith.langchain.com |
|
||||
| `--allow-blocking` | `False` | Do not raise errors for synchronous I/O blocking operations in your code |
|
||||
| `--tunnel` | `False` | Expose the local server via a public tunnel (Cloudflare) for remote frontend access. This avoids issues with browsers or networks blocking localhost connections |
|
||||
| `--help` | | Display command documentation |
|
||||
|
||||
### `build`
|
||||
|
||||
@@ -1,6 +1,22 @@
|
||||
# Environment Variables
|
||||
|
||||
The LangGraph Cloud Server supports specific environment variables for configuring a deployment.
|
||||
The LangGraph 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`
|
||||
|
||||
@@ -16,7 +32,7 @@ See <a href="https://docs.smith.langchain.com/how_to_guides/tracing/sample_trace
|
||||
|
||||
## `LANGGRAPH_AUTH_TYPE`
|
||||
|
||||
Type of authentication for the LangGraph Cloud Server deployment. Valid values: `langsmith`, `noop`.
|
||||
Type of authentication for the LangGraph Server deployment. Valid values: `langsmith`, `noop`.
|
||||
|
||||
For deployments to LangGraph Cloud, this environment variable is set automatically. For local development or deployments where authentication is handled externally (e.g. self-hosted), set this environment variable to `noop`.
|
||||
|
||||
@@ -28,15 +44,35 @@ 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.
|
||||
|
||||
## `LANGSMITH_TRACING`
|
||||
|
||||
!!! info "Only for Self-Hosted Data Plane, Self-Hosted Control Plane, and Standalone Container"
|
||||
Disabling LangSmith tracing is only available for [Self-Hosted Data Plane](../../concepts/langgraph_self_hosted_data_plane.md), [Self-Hosted Control Plane](../../concepts/langgraph_self_hosted_control_plane.md), and [Standalone Container](../../concepts/langgraph_standalone_container.md) deployments.
|
||||
|
||||
Set `LANGSMITH_TRACING` to `false` to disable tracing to LangSmith.
|
||||
|
||||
## `LOG_LEVEL`
|
||||
|
||||
Configure [log level](https://docs.python.org/3/library/logging.html#logging-levels). Defaults to `INFO`.
|
||||
|
||||
## `LOG_JSON`
|
||||
|
||||
Set `LOG_JSON` to `true` to render all log messages as JSON objects using the configured `JSONRenderer`. This produces structured logs that can be easily parsed or ingested by log management systems. Defaults to `false`.
|
||||
|
||||
## `LOG_COLOR`
|
||||
|
||||
This is mainly relevant in the context of using the dev server via the `langgraph dev` command. Set `LOG_COLOR` to `true` to enable ANSI-colored console output when using the default console renderer. Disabling color output by setting this variable to `false` produces monochrome logs. Defaults to `true`.
|
||||
|
||||
## `N_JOBS_PER_WORKER`
|
||||
|
||||
Number of jobs per worker for the LangGraph Cloud task queue. Defaults to `10`.
|
||||
Number of jobs per worker for the LangGraph Server task queue. Defaults to `10`.
|
||||
|
||||
## `POSTGRES_URI_CUSTOM`
|
||||
|
||||
For [Bring Your Own Cloud (BYOC)](../../concepts/bring_your_own_cloud.md) deployments only.
|
||||
!!! info "Only for Self-Hosted Data Plane and Self-Hosted Control Plane"
|
||||
Custom Postgres instances are only available for [Self-Hosted Data Plane](../../concepts/langgraph_self_hosted_data_plane.md) and [Self-Hosted Control Plane](../../concepts/langgraph_self_hosted_control_plane.md) deployments.
|
||||
|
||||
Specify `POSTGRES_URI_CUSTOM` to use an externally managed Postgres instance. The value of `POSTGRES_URI_CUSTOM` must be a valid [Postgres connection URI](https://www.postgresql.org/docs/current/libpq-connect.html#LIBPQ-CONNSTRING-URIS).
|
||||
Specify `POSTGRES_URI_CUSTOM` to use a custom Postgres instance. The value of `POSTGRES_URI_CUSTOM` must be a valid [Postgres connection URI](https://www.postgresql.org/docs/current/libpq-connect.html#LIBPQ-CONNSTRING-URIS).
|
||||
|
||||
Postgres:
|
||||
|
||||
@@ -53,5 +89,11 @@ Control Plane Functionality:
|
||||
|
||||
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.
|
||||
- The custom Postgres instance must be accessible by the LangGraph Server. The user is responsible for ensuring connectivity.
|
||||
|
||||
## `REDIS_URI_CUSTOM`
|
||||
|
||||
!!! info "Only for Self-Hosted Data Plane and Self-Hosted Control Plane"
|
||||
Custom Redis instances are only available for [Self-Hosted Data Plane](../../concepts/langgraph_self_hosted_data_plane.md) and [Self-Hosted Control Plane](../../concepts/langgraph_self_hosted_control_plane.md) deployments.
|
||||
|
||||
Specify `REDIS_URI_CUSTOM` to use a custom 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).
|
||||
|
||||
@@ -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}
|
||||
|
||||
@@ -423,6 +419,7 @@ Here are all the supported action handlers:
|
||||
| | `@auth.on.crons.search` | Listing cron jobs | [`CronsSearch`](../cloud/reference/sdk/python_sdk_ref.md#langgraph_sdk.auth.types.CronsSearch) |
|
||||
|
||||
???+ note "About Runs"
|
||||
|
||||
Runs are scoped to their parent thread for access control. This means permissions are typically inherited from the thread, reflecting the conversational nature of the data model. All run operations (reading, listing) except creation are controlled by the thread's handlers.
|
||||
There is a specific `create_run` handler for creating new runs because it had more arguments that you can view in the handler.
|
||||
|
||||
|
||||
@@ -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. **<a href="#cloud-saas">Cloud SaaS<sup>(Beta)</sup></a>**: Available for **Plus** and **Enterprise** plans.
|
||||
|
||||
2. **[Self-Hosted Enterprise](#self-hosted-enterprise)**: Available for the **Enterprise** plan.
|
||||
1. **<a href="#self-hosted-data-plane">Self-Hosted Data Plane<sup>(Beta)</sup></a>**: Available for the **Enterprise** plan.
|
||||
|
||||
3. **[Cloud SaaS](#cloud-saas)**: Available for **Plus** and **Enterprise** plans.
|
||||
1. **<a href="#self-hosted-control-plane">Self-Hosted Control Plane<sup>(Beta)</sup></a>**: 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.
|
||||
|
||||
You’ll 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.
|
||||
|
||||
You’ll 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
|
||||
|
||||
|
||||
@@ -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."""
|
||||
|
||||
|
After Width: | Height: | Size: 437 KiB |
|
After Width: | Height: | Size: 668 KiB |
@@ -49,7 +49,7 @@ 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.
|
||||
- [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: [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.
|
||||
- [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.
|
||||
|
||||
@@ -62,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
|
||||
|
||||
@@ -74,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.
|
||||
- <a href="./langgraph_cloud/">Cloud SaaS<sup>(Beta)</sup></a>: Connect to your GitHub repositories and deploy LangGraph Servers to LangChain's cloud. We manage everything.
|
||||
- <a href="./langgraph_self_hosted_data_plane/">Self-Hosted Data Plane<sup>(Beta)</sup></a>: 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.
|
||||
- <a href="./langgraph_self_hosted_control_plane/">Self-Hosted Control Plane<sup>(Beta)</sup></a>: Create deployments from a self-hosted [Control Plane UI](../concepts/langgraph_control_plane.md#control-plane-ui) 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.
|
||||
|
||||
@@ -54,7 +54,7 @@ pip install -U "langgraph-cli[inmem]"
|
||||
|
||||
### `up`
|
||||
|
||||
The `langgraph up` command starts an instance of the [LangGraph API server](./langgraph_server.md) locally in a docker container. This requires thedocker server to be running locally. It also requires a LangSmith API key for local development or a license key for production use.
|
||||
The `langgraph up` command starts an instance of the [LangGraph API server](./langgraph_server.md) locally in a docker container. This requires the docker server to be running locally. It also requires a LangSmith API key for local development or a license key for production use.
|
||||
|
||||
The 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.
|
||||
|
||||
|
||||
@@ -1,101 +1,17 @@
|
||||
# Cloud SaaS
|
||||
# Cloud SaaS (Beta)
|
||||
|
||||
!!! 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.
|
||||
|
||||

|
||||
|
||||
## 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 |
|
||||
|
||||
## Related
|
||||
|
||||
- [Deployment Options](./deployment_options.md)
|
||||

|
||||
|
||||
@@ -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,120 @@
|
||||
# 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 3 metrics:
|
||||
|
||||
1. CPU utilization
|
||||
1. Memory utilization
|
||||
1. Number of pending (in progress) [runs](../concepts/langgraph_server.md#runs)
|
||||
|
||||
For CPU utilization, the autoscaler targets 75% utilization. This means the autoscaler will scale the number of containers up or down to ensure that CPU utilization is at or near 75%. For memory utilization, the autoscaler targets 75% utilization as well.
|
||||
|
||||
For number of pending runs, the autoscaler targets 10 pending runs. For example, if the current number of containers is 1, but the number of pending runs in 20, the autoscaler will scale up the deployment to 2 containers (20 pending runs / 2 containers = 10 pending runs per container).
|
||||
|
||||
Each metric is computed independently and the autoscaler will determine the scaling action based on the metric that results in the most number of containers.
|
||||
|
||||
Scale down actions are delayed for 30 minutes before any action is taken. In other words, if the autoscaler decides to scale down a deployment, it will first wait for 30 minutes before scaling down. After 30 minutes, the metrics are recomputed and the deployment will scale down if the recomputed metrics result in a lower number of containers than the current number. Otherwise, the deployment remains scaled up. This "cool down" period ensures that deployments do not scale up and down too frequently.
|
||||
|
||||
### Static IP Addresses
|
||||
|
||||
!!! info "Only for Cloud SaaS"
|
||||
Static IP addresses are only available for [Cloud SaaS](../concepts/langgraph_cloud.md) deployments.
|
||||
|
||||
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 |
|
||||
|
||||
### Custom Postgres
|
||||
|
||||
!!! info "Only for Self-Hosted Data Plane and Self-Hosted Control Plane"
|
||||
Custom Postgres instances are only available for [Self-Hosted Data Plane](../concepts/langgraph_self_hosted_data_plane.md) and [Self-Hosted Control Plane](../concepts/langgraph_self_hosted_control_plane.md) deployments.
|
||||
|
||||
A custom Postgres instance can be used instead of the [one automatically created by the control plane](./langgraph_control_plane.md#database-provisioning). Specify the [`POSTGRES_URI_CUSTOM`](../cloud/reference/env_var.md#postgres_uri_custom) environment variable to use a custom Postgres instance.
|
||||
|
||||
Multiple deployments can share the same Postgres instance. For example, for `Deployment A`, `POSTGRES_URI_CUSTOM` can be set to `postgres://<user>:<password>@/<database_name_1>?host=<hostname_1>` and for `Deployment B`, `POSTGRES_URI_CUSTOM` 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**.
|
||||
|
||||
### Custom Redis
|
||||
|
||||
!!! info "Only for Self-Hosted Data Plane and Self-Hosted Control Plane"
|
||||
Custom Redis instances are only available for [Self-Hosted Data Plane](../concepts/langgraph_self_hosted_data_plane.md) and [Self-Hosted Control Plane](../concepts/langgraph_self_hosted_control_plane.md) deployments.
|
||||
|
||||
A custom Redis instance can be used instead of the one automatically created by the control plane. Specify the [REDIS_URI_CUSTOM](../cloud/reference/env_var.md#redis_uri_custom) environment variable to use a custom Redis instance.
|
||||
|
||||
|
||||
Multiple deployments can share the same Redis instance. For example, for `Deployment A`, `REDIS_URI_CUSTOM` can be set to `redis://<hostname_1>:<port>/1` and for `Deployment B`, `REDIS_URI_CUSTOM` 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**.
|
||||
|
||||
### LangSmith Tracing
|
||||
|
||||
LangGraph Server is automatically configured to send traces to LangSmith. See the table below for details with respect to each deployment option.
|
||||
|
||||
| Cloud SaaS | Self-Hosted Data Plane | Self-Hosted Control Plane | Standalone Container |
|
||||
|------------|------------------------|---------------------------|----------------------|
|
||||
| Required<br><br>Trace to LangSmith SaaS. | Optional<br><br>Disable tracing or trace to LangSmith SaaS. | Optional<br><br>Disable tracing or trace to Self-Hosted LangSmith. | Optional<br><br>Disable tracing, trace to LangSmith SaaS, or trace to Self-Hosted LangSmith. |
|
||||
|
||||
### Telemetry
|
||||
|
||||
LangGraph Server is automatically configured to report telemetry metadata for billing purposes. See the table below for details with respect to each deployment option.
|
||||
|
||||
| Cloud SaaS | Self-Hosted Data Plane | Self-Hosted Control Plane | Standalone Container |
|
||||
|------------|------------------------|---------------------------|----------------------|
|
||||
| Telemetry sent to LangSmith SaaS. | Telemetry sent to LangSmith SaaS. | Self-reported usage (audit) for air-gapped license key.<br><br>Telemetry sent to LangSmith SaaS for LangGraph Platform License Key. | Self-reported usage (audit) for air-gapped license key.<br><br>Telemetry sent to LangSmith SaaS for LangGraph Platform License Key. |
|
||||
|
||||
### Licensing
|
||||
|
||||
LangGraph Server is automatically configured to perform license key validation. See the table below for details with respect to each deployment option.
|
||||
|
||||
| Cloud SaaS | Self-Hosted Data Plane | Self-Hosted Control Plane | Standalone Container |
|
||||
|------------|------------------------|---------------------------|----------------------|
|
||||
| LangSmith API Key validated against LangSmith SaaS. | LangSmith API Key validated against LangSmith SaaS. | Air-gapped license key or LangGraph Platform License Key validated against LangSmith SaaS. | Air-gapped license key or LangGraph Platform License Key validated against LangSmith SaaS. |
|
||||
@@ -5,6 +5,10 @@ search:
|
||||
|
||||
# LangGraph Platform
|
||||
|
||||
Watch this 4-minute overview of LangGraph Platform to see how it helps you build, deploy, and evaluate agentic applications.
|
||||
|
||||
<iframe width="560" height="315" src="https://www.youtube.com/embed/pfAQxBS5z88?si=XGS6Chydn6lhSO1S" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>
|
||||
|
||||
## Overview
|
||||
|
||||
LangGraph Platform is a commercial solution for deploying agentic applications to production, built on the open-source [LangGraph framework](./high_level.md).
|
||||
@@ -16,6 +20,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.
|
||||
|
||||

|
||||
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
# Self-Hosted Control Plane (Beta)
|
||||
|
||||
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
|
||||
|
||||

|
||||
|
||||
## 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 (Beta)
|
||||
|
||||
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
|
||||
|
||||

|
||||
|
||||
## 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
|
||||
|
||||

|
||||
|
||||
## 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.
|
||||
@@ -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"},
|
||||
|
||||
@@ -4,6 +4,10 @@ LangGraph has a built-in persistence layer, implemented through checkpointers. W
|
||||
|
||||

|
||||
|
||||
!!! 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,7 +30,7 @@ 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
|
||||
@@ -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.
|
||||
@@ -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 ...
|
||||
|
||||
@@ -440,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:
|
||||
@@ -452,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
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
## How we use Postgres
|
||||
|
||||
Postgres is the persistence layer for all user and run data in LGP. This stores both checkpoints (see more info [here](./persistence.md)) as well as the server resources (threads, runs, assistants and crons).
|
||||
Postgres is the persistence layer for all user, run, and long-term memory data in LGP. This stores both checkpoints (see more info [here](./persistence.md)), server resources (threads, runs, assistants and crons), as well as items saved in the long-term memory store (see more info [here](./persistence.md#memory-store)).
|
||||
|
||||
## How we use Redis
|
||||
|
||||
|
||||
@@ -284,7 +284,7 @@ LangGraph provides two high-level APIs for creating a Pregel application: the [S
|
||||
{'__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)
|
||||
@@ -344,4 +344,4 @@ LangGraph provides two high-level APIs for creating a Pregel application: the [S
|
||||
{'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>}
|
||||
```
|
||||
```
|
||||
|
||||
@@ -9,10 +9,6 @@
|
||||
|
||||
For a more guided walkthrough, see [**setting up custom authentication**](../../tutorials/auth/getting_started.md) tutorial.
|
||||
|
||||
???+ 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.
|
||||
|
||||
???+ note "Support by deployment type"
|
||||
|
||||
Custom auth is supported for all deployments in the **managed LangGraph Cloud**, as well as **Enterprise** self-hosted plans. It is not supported for **Lite** self-hosted plans.
|
||||
|
||||
@@ -8,10 +8,6 @@ Defining a custom app object lets you add any routes you'd like, so you can do a
|
||||
|
||||
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.
|
||||
|
||||
@@ -163,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:
|
||||
@@ -201,11 +202,14 @@ Learn how to set up your app for deployment to LangGraph Platform:
|
||||
|
||||
### 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
|
||||
|
||||
@@ -300,6 +304,7 @@ LangGraph Studio is a built-in UI for visualizing, testing, and debugging your a
|
||||
- [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
|
||||
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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."
|
||||
]
|
||||
|
||||
@@ -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
|
||||
}
|
||||
@@ -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.
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
---
|
||||
hide_comments: true
|
||||
title: Home
|
||||
title: LangGraph
|
||||
---
|
||||
|
||||
<script>
|
||||
@@ -23,6 +23,9 @@ title: Home
|
||||
.md-content h1 {
|
||||
display: none;
|
||||
}
|
||||
.md-header__topic {
|
||||
display: none;
|
||||
}
|
||||
</style>
|
||||
|
||||
{!../README.md!}
|
||||
|
||||
@@ -1,13 +1,20 @@
|
||||
# LLMs-txt for LangGraph
|
||||
# LLMs-txt Overview
|
||||
|
||||
## Overview
|
||||
|
||||
LangGraph provides documentation files in the [`llms.txt`](https://llmstxt.org/) format, specifically `llms.txt` and `llms-full.txt`. These files allow large language models (LLMs) and agents to access programming documentation and APIs, particularly useful within integrated development environments (IDEs).
|
||||
Below you can find a list of documentation files in the [`llms.txt`](https://llmstxt.org/) format, specifically `llms.txt` and `llms-full.txt`. These files allow large language models (LLMs) and agents to access programming documentation and APIs, particularly useful within integrated development environments (IDEs).
|
||||
|
||||
| Language Version | llms.txt | llms-full.txt |
|
||||
|------------------|------------------------------------------------------------------------------------------------------------|----------------------------------------------------------------------------------------------------------------------|
|
||||
| LangGraph Python | [https://langchain-ai.github.io/langgraph/llms.txt](https://langchain-ai.github.io/langgraph/llms.txt) | [https://langchain-ai.github.io/langgraph/llms-full.txt](https://langchain-ai.github.io/langgraph/llms-full.txt) |
|
||||
| LangGraph JS | [https://langchain-ai.github.io/langgraphjs/llms.txt](https://langchain-ai.github.io/langgraphjs/llms.txt) | [https://langchain-ai.github.io/langgraphjs/llms-full.txt](https://langchain-ai.github.io/langgraphjs/llms-full.txt) |
|
||||
| LangChain Python | [https://python.langchain.com/llms.txt](https://python.langchain.com/llms.txt) | N/A |
|
||||
| LangChain JS | [https://js.langchain.com/llms.txt](https://js.langchain.com/llms.txt) | N/A |
|
||||
|
||||
!!! info "Review the output"
|
||||
|
||||
Even with access to up-to-date documentation, current state-of-the-art models may not always generate correct code. Treat the generated code as a starting point, and always review it before shipping
|
||||
code to production.
|
||||
|
||||
## Differences Between `llms.txt` and `llms-full.txt`
|
||||
|
||||
@@ -19,9 +26,17 @@ A key consideration when using `llms-full.txt` is its size. For extensive docume
|
||||
|
||||
## Using `llms.txt` via an MCP Server
|
||||
|
||||
As of March 9, 2025, IDEs [do not yet have robust native support for `llms.txt`](https://x.com/jeremyphoward/status/1902109312216129905?t=1eHFv2vdNdAckajnug0_Vw&s=19). However, you can utilize `llms.txt` effectively through an MCP server.
|
||||
As of March 9, 2025, IDEs [do not yet have robust native support for `llms.txt`](https://x.com/jeremyphoward/status/1902109312216129905?t=1eHFv2vdNdAckajnug0_Vw&s=19). However, you can still use `llms.txt` effectively through an MCP server.
|
||||
|
||||
We provide an MCP server specifically designed to serve documentation, called [`mcpdoc`](https://github.com/langchain-ai/mcpdoc). This setup is compatible with IDEs and platforms such as Cursor, Windsurf, Claude, and Claude Code. Instructions for using `mcpdoc` with these tools are available in the repository.
|
||||
### 🚀 Use the `mcpdoc` Server
|
||||
|
||||
We provide an **MCP server** that was designed to serve documentation for LLMs and IDEs:
|
||||
|
||||
👉 **[langchain-ai/mcpdoc GitHub Repository](https://github.com/langchain-ai/mcpdoc)**
|
||||
|
||||
This MCP server allows integrating `llms.txt` into tools like **Cursor**, **Windsurf**, **Claude**, and **Claude Code**.
|
||||
|
||||
📘 **Setup instructions and usage examples** are available in the repository.
|
||||
|
||||
## Using `llms-full.txt`
|
||||
|
||||
|
||||
@@ -17,3 +17,12 @@
|
||||
options:
|
||||
members:
|
||||
- ValidationNode
|
||||
|
||||
|
||||
::: langgraph.prebuilt.interrupt
|
||||
options:
|
||||
members:
|
||||
- HumanInterruptConfig
|
||||
- ActionRequest
|
||||
- HumanInterrupt
|
||||
- HumanResponse
|
||||
@@ -0,0 +1,3 @@
|
||||
.safari {
|
||||
color: #0070C9;
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
:root {
|
||||
--md-admonition-icon--version-added: url('data:image/svg+xml;charset=utf-8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M19 2H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h4l3 3 3-3h4c1.1 0 2-.9 2-2V4c0-1.1-.9-2-2-2m0 16h-4.2l-.8.8-2 2-2-2-.8-.8H5V4h14z"/><path d="M11 15h2v2h-2v-2m0-10h2v8h-2V5"/></svg>');
|
||||
--md-admonition-icon--version-changed: url('data:image/svg+xml;charset=utf-8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M19 2H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h4l3 3 3-3h4c1.1 0 2-.9 2-2V4c0-1.1-.9-2-2-2m0 16h-4.2l-.8.8-2 2-2-2-.8-.8H5V4h14z"/><path d="M15 11h-2V9h-2v2H9v2h2v2h2v-2h2v-2Z"/></svg>');
|
||||
}
|
||||
|
||||
.md-typeset .admonition.version-added,
|
||||
.md-typeset details.version-added {
|
||||
border-color: rgb(0, 191, 165);
|
||||
}
|
||||
|
||||
.md-typeset .version-added > .admonition-title,
|
||||
.md-typeset .version-added > summary {
|
||||
background-color: rgba(0, 191, 165, 0.1);
|
||||
}
|
||||
|
||||
.md-typeset .version-added > .admonition-title::before,
|
||||
.md-typeset .version-added > summary::before {
|
||||
background-color: rgb(0, 191, 165);
|
||||
-webkit-mask-image: var(--md-admonition-icon--version-added);
|
||||
mask-image: var(--md-admonition-icon--version-added);
|
||||
}
|
||||
|
||||
.md-typeset .admonition.version-changed,
|
||||
.md-typeset details.version-changed {
|
||||
border-color: rgb(100, 221, 23);
|
||||
}
|
||||
|
||||
.md-typeset .version-changed > .admonition-title,
|
||||
.md-typeset .version-changed > summary {
|
||||
background-color: rgba(100, 221, 23, 0.1);
|
||||
}
|
||||
|
||||
.md-typeset .version-changed > .admonition-title::before,
|
||||
.md-typeset .version-changed > summary::before {
|
||||
background-color: rgb(100, 221, 23);
|
||||
-webkit-mask-image: var(--md-admonition-icon--version-changed);
|
||||
mask-image: var(--md-admonition-icon--version-changed);
|
||||
}
|
||||
@@ -14,3 +14,4 @@ Errors referenced below will have an `lc_error_code` property corresponding to o
|
||||
These guides provide troubleshooting information for errors that are specific to the LangGraph Platform.
|
||||
|
||||
- [INVALID_LICENSE](./INVALID_LICENSE.md)
|
||||
- [Studio Errors](../studio.md)
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
# Troubleshooting LangGraph Studio
|
||||
|
||||
## :fontawesome-brands-safari:{ .safari } Safari connection error with local dev server
|
||||
|
||||
Safari blocks plain‑HTTP traffic on localhost. If you start Studio with a vanilla
|
||||
`langgraph dev`, the page may report a "Failed to load assistants" error (or something similar) and the browser DevTools will show network errors.
|
||||
|
||||
#### Quick fix — run Studio through a secure Cloudflare tunnel
|
||||
|
||||
=== "Python"
|
||||
|
||||
```shell
|
||||
pip install -U langgraph-cli>=0.2.6 # Python
|
||||
langgraph dev --tunnel
|
||||
```
|
||||
=== "JS"
|
||||
|
||||
```shell
|
||||
# Requires @langchain/langgraph-cli>=0.0.26
|
||||
npx @langchain/langgraph-cli dev
|
||||
```
|
||||
|
||||
The command prints a URL like:
|
||||
|
||||
```shell
|
||||
https://smith.langchain.com/studio/?baseUrl=https://hamilton-praise-heart-costumes.trycloudflare.com
|
||||
```
|
||||
where
|
||||
```shell
|
||||
?baseUrl=https://hamilton-praise-heart-costumes.trycloudflare.com
|
||||
```
|
||||
indicates the endpoint where your agent server is exposed.
|
||||
|
||||
Open that URL in Safari and Studio should load immediately.
|
||||
|
||||
#### Alternative — use a Chromium‑based browser
|
||||
|
||||
Chrome, Edge, and Brave allow HTTP on localhost, so a plain `langgraph dev` should work without extra steps.
|
||||
|
||||
#### If it’s still not loading
|
||||
|
||||
1. Make sure the `baseUrl` query parameter in the studio URL points to the **tunnel URL** NOT to localhost.
|
||||
2. Confirm your CLI version with `langgraph --version`.
|
||||
|
||||
No other configuration, certificates, or CORS tweaks are required.
|
||||
@@ -17,7 +17,18 @@ Get started deploying your LangGraph applications locally or on the cloud with
|
||||
|
||||
## Deployment Options
|
||||
|
||||
- [Self-Hosted Lite](../concepts/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](../concepts/langgraph_cloud.md): Hosted as part of LangSmith.
|
||||
- [Bring Your Own Cloud](../concepts/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](../concepts/self_hosted.md): Completely managed by you.
|
||||
- <a href="../../concepts/langgraph_cloud/">Cloud SaaS<sup>(Beta)</sup></a>: Connect to your GitHub repositories and deploy LangGraph Servers to LangChain's cloud. We manage everything.
|
||||
- <a href="../../concepts/langgraph_self_hosted_data_plane/">Self-Hosted Data Plane<sup>(Beta)</sup></a>: 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.
|
||||
- <a href="../../concepts/langgraph_self_hosted_control_plane/">Self-Hosted Control Plane<sup>(Beta)</sup></a>: Create deployments from a self-hosted [Control Plane UI](../concepts/langgraph_control_plane.md#control-plane-ui) 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.
|
||||
|
||||
A quick comparison...
|
||||
|
||||
| | **Cloud SaaS** | **Self-Hosted [Data Plane](../concepts/langgraph_data_plane.md)** | **Self-Hosted [Control Plane](../concepts/langgraph_control_plane.md)** | **Standalone Container** |
|
||||
|----------------------|----------------|----------------------------|-------------------------------|--------------------------|
|
||||
| **[Control Plane UI/API](../concepts/langgraph_control_plane.md)** | Yes | Yes | Yes | No |
|
||||
| **CI/CD** | Managed internally by platform | Managed externally by you | Managed externally by you | Managed externally by you |
|
||||
| **Data/Compute Residency** | LangChain’s cloud | Your cloud | Your cloud | Your cloud |
|
||||
| **Required Permissions** | None | See details [here](). | See details [here](). | None |
|
||||
| **LangSmith Compatibility** | Trace to LangSmith SaaS | Trace to LangSmith SaaS | Trace to Self-Hosted LangSmith | Optional tracing |
|
||||
| **[Pricing](https://www.langchain.com/pricing-langgraph-platform)** | Plus | Enterprise | Enterprise | Developer |
|
||||
|
||||
@@ -279,7 +279,6 @@
|
||||
" if user_input.lower() in [\"quit\", \"exit\", \"q\"]:\n",
|
||||
" print(\"Goodbye!\")\n",
|
||||
" break\n",
|
||||
"\n",
|
||||
" stream_graph_updates(user_input)\n",
|
||||
" except:\n",
|
||||
" # fallback if input() is not available\n",
|
||||
|
||||
@@ -741,13 +741,7 @@
|
||||
"from IPython.display import Image, display\n",
|
||||
"from langchain_core.runnables.graph import MermaidDrawMethod\n",
|
||||
"\n",
|
||||
"display(\n",
|
||||
" Image(\n",
|
||||
" app.get_graph().draw_mermaid_png(\n",
|
||||
" draw_method=MermaidDrawMethod.API,\n",
|
||||
" )\n",
|
||||
" )\n",
|
||||
")"
|
||||
"display(Image(app.get_graph().draw_mermaid_png()))"
|
||||
]
|
||||
},
|
||||
{
|
||||
|
||||
@@ -222,7 +222,7 @@ As noted in the Anthropic blog on `Building Effective Agents`:
|
||||
|
||||
|
||||
@entrypoint()
|
||||
def parallel_workflow(topic: str):
|
||||
def prompt_chaining_workflow(topic: str):
|
||||
original_joke = generate_joke(topic).result()
|
||||
if check_punchline(original_joke) == "Pass":
|
||||
return original_joke
|
||||
@@ -231,7 +231,7 @@ As noted in the Anthropic blog on `Building Effective Agents`:
|
||||
return polish_joke(improved_joke).result()
|
||||
|
||||
# Invoke
|
||||
for step in parallel_workflow.stream("cats", stream_mode="updates"):
|
||||
for step in prompt_chaining_workflow.stream("cats", stream_mode="updates"):
|
||||
print(step)
|
||||
print("\n")
|
||||
```
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
site_name: ""
|
||||
site_description: Build language agents as graphs
|
||||
site_name: "LangGraph"
|
||||
site_description: Build reliable, stateful AI systems, without giving up control
|
||||
site_url: https://langchain-ai.github.io/langgraph/
|
||||
repo_url: https://github.com/langchain-ai/langgraph
|
||||
edit_uri: edit/main/docs/docs/
|
||||
@@ -57,12 +57,16 @@ plugins:
|
||||
separator: '[\s\u200b\-,:!=\[\]()"`/]+|\.(?!\d)|&[lg]t;'
|
||||
- autorefs
|
||||
- mkdocstrings:
|
||||
custom_templates: templates
|
||||
handlers:
|
||||
python:
|
||||
import:
|
||||
- https://docs.python.org/3/objects.inv
|
||||
- https://python.langchain.com/api_reference/objects.inv
|
||||
options:
|
||||
preload_modules:
|
||||
- langchain
|
||||
- langchain_core
|
||||
enable_inventory: true
|
||||
members_order: source
|
||||
allow_inspection: true
|
||||
@@ -75,7 +79,10 @@ plugins:
|
||||
docstring_style: google
|
||||
docstring_section_style: list
|
||||
show_root_toc_entry: false
|
||||
show_signature: true
|
||||
show_signature_annotations: true
|
||||
separate_signature: true
|
||||
line_length: 60
|
||||
show_symbol_type_heading: true
|
||||
show_symbol_type_toc: true
|
||||
signature_crossrefs: true
|
||||
@@ -84,7 +91,7 @@ plugins:
|
||||
- "!^_"
|
||||
|
||||
nav:
|
||||
- Home:
|
||||
- LangGraph:
|
||||
- index.md
|
||||
- Get started:
|
||||
- Learn the basics: tutorials/introduction.ipynb
|
||||
@@ -185,6 +192,7 @@ nav:
|
||||
- how-tos/create-react-agent-system-prompt.ipynb
|
||||
- how-tos/create-react-agent-hitl.ipynb
|
||||
- how-tos/create-react-agent-structured-output.ipynb
|
||||
- how-tos/create-react-agent-manage-message-history.ipynb
|
||||
- how-tos/react-agent-from-scratch.ipynb
|
||||
- how-tos/react-agent-from-scratch-functional.ipynb
|
||||
- LangGraph Platform:
|
||||
@@ -202,12 +210,18 @@ nav:
|
||||
- Deployment:
|
||||
- Deployment: how-tos#deployment
|
||||
- cloud/deployment/cloud.md
|
||||
- cloud/deployment/self_hosted_data_plane.md
|
||||
- cloud/deployment/self_hosted_control_plane.md
|
||||
- cloud/deployment/standalone_container.md
|
||||
- how-tos/deploy-self-hosted.md
|
||||
- how-tos/use-remote-graph.md
|
||||
- how-tos/ttl/configure_ttl.md
|
||||
- Data Management:
|
||||
- how-tos/ttl/configure_ttl.md
|
||||
- Authentication & Access Control:
|
||||
- Authentication & Access Control: how-tos#authentication-access-control
|
||||
- cloud/how-tos/auth/custom_auth_new.md
|
||||
- cloud/how-tos/auth/openapi_security_new.md
|
||||
- how-tos/auth/custom_auth.md
|
||||
- how-tos/auth/openapi_security.md
|
||||
- Assistants:
|
||||
- Assistants: how-tos#assistants
|
||||
- cloud/how-tos/configuration_cloud.md
|
||||
@@ -249,6 +263,11 @@ nav:
|
||||
- cloud/how-tos/webhooks.md
|
||||
- Cron Jobs:
|
||||
- cloud/how-tos/cron_jobs.md
|
||||
- Modifying the API:
|
||||
- Modifying the API: how-tos#modifying-the-api
|
||||
- how-tos/http/custom_lifespan.md
|
||||
- how-tos/http/custom_middleware.md
|
||||
- how-tos/http/custom_routes.md
|
||||
- LangGraph Studio:
|
||||
- LangGraph Studio: how-tos#langgraph-studio
|
||||
- cloud/how-tos/test_deployment.md
|
||||
@@ -256,6 +275,9 @@ nav:
|
||||
- cloud/how-tos/invoke_studio.md
|
||||
- cloud/how-tos/threads_studio.md
|
||||
- cloud/how-tos/datasets_studio.md
|
||||
- cloud/how-tos/iterate_graph_studio.md
|
||||
- cloud/how-tos/clone_traces_studio.md
|
||||
- how-tos/local-studio.md
|
||||
- Concepts:
|
||||
- concepts/index.md
|
||||
- LangGraph:
|
||||
@@ -264,8 +286,9 @@ nav:
|
||||
- concepts/low_level.md
|
||||
- concepts/agentic_concepts.md
|
||||
- concepts/multi_agent.md
|
||||
- concepts/breakpoints
|
||||
- concepts/breakpoints.md
|
||||
- concepts/human_in_the_loop.md
|
||||
- concepts/v0-human-in-the-loop.md
|
||||
- concepts/time-travel.md
|
||||
- concepts/persistence.md
|
||||
- concepts/memory.md
|
||||
@@ -278,11 +301,16 @@ nav:
|
||||
- High Level:
|
||||
- High Level: concepts#high-level
|
||||
- concepts/langgraph_platform.md
|
||||
- concepts/platform_architecture.md
|
||||
- concepts/scalability_and_resilience.md
|
||||
- concepts/deployment_options.md
|
||||
- concepts/bring_your_own_cloud.md
|
||||
- concepts/plans.md
|
||||
- concepts/template_applications.md
|
||||
- Components:
|
||||
- Components: concepts#components
|
||||
- concepts/langgraph_control_plane.md
|
||||
- concepts/langgraph_data_plane.md
|
||||
- concepts/langgraph_server.md
|
||||
- concepts/langgraph_studio.md
|
||||
- concepts/langgraph_cli.md
|
||||
@@ -296,9 +324,11 @@ nav:
|
||||
- concepts/auth.md
|
||||
- Deployment Options:
|
||||
- Deployment Options: concepts#deployment-options
|
||||
- concepts/self_hosted.md
|
||||
- concepts/langgraph_cloud.md
|
||||
- concepts/bring_your_own_cloud.md
|
||||
- concepts/langgraph_self_hosted_data_plane.md
|
||||
- concepts/langgraph_self_hosted_control_plane.md
|
||||
- concepts/langgraph_standalone_container.md
|
||||
- concepts/self_hosted.md
|
||||
- Tutorials:
|
||||
- tutorials/index.md
|
||||
- Quick Start:
|
||||
@@ -358,8 +388,6 @@ nav:
|
||||
- tutorials/auth/resource_auth.md
|
||||
- tutorials/auth/add_auth_server.md
|
||||
- Resources:
|
||||
# NOTE: prebuilt.md is auto-generated by `make build-prebuilt`
|
||||
- Prebuilt Agents: prebuilt.md
|
||||
- Companies using LangGraph: adopters.md
|
||||
- LLMS-txt: llms-txt-overview.md
|
||||
- FAQ: concepts/faq.md
|
||||
@@ -372,9 +400,31 @@ nav:
|
||||
- troubleshooting/errors/MULTIPLE_SUBGRAPHS.md
|
||||
- troubleshooting/errors/INVALID_CHAT_HISTORY.md
|
||||
- troubleshooting/errors/INVALID_LICENSE.md
|
||||
- troubleshooting/studio.md
|
||||
- LangGraph Academy Course: https://academy.langchain.com/courses/intro-to-langgraph
|
||||
|
||||
- Agents:
|
||||
- agents/overview.md
|
||||
- Get started:
|
||||
- agents/agents.md
|
||||
- Documentation:
|
||||
- agents/run_agents.md
|
||||
- agents/streaming.md
|
||||
- agents/models.md
|
||||
- agents/tools.md
|
||||
- agents/mcp.md
|
||||
- agents/context.md
|
||||
- agents/memory.md
|
||||
- agents/human-in-the-loop.md
|
||||
- agents/multi-agent.md
|
||||
- agents/evals.md
|
||||
- agents/deployment.md
|
||||
- agents/ui.md
|
||||
- Resources:
|
||||
# NOTE: prebuilt.md is auto-generated by `make build-prebuilt`
|
||||
- agents/prebuilt.md
|
||||
- API reference:
|
||||
- reference/index.md
|
||||
- Library:
|
||||
- Graphs: reference/graphs.md
|
||||
- Checkpointing: reference/checkpoints.md
|
||||
@@ -485,13 +535,8 @@ extra:
|
||||
Thanks for your feedback! Please help us improve this page by adding to the discussion below.
|
||||
validation:
|
||||
# https://www.mkdocs.org/user-guide/configuration/
|
||||
# We're `ignoring` nav.omitted_files because we are going to rely
|
||||
# on files being properly links to from the index pages of:
|
||||
# - tutorials
|
||||
# - concepts
|
||||
# - how-tos
|
||||
# - reference
|
||||
omitted_files: ignore
|
||||
# We are still raising for omitted files because they determine the breadcrumbs for pages.
|
||||
omitted_files: warn
|
||||
absolute_links: warn
|
||||
unrecognized_links: warn
|
||||
# TODO: figure out how to enable 'warn' for this
|
||||
@@ -503,3 +548,6 @@ validation:
|
||||
not_found: info
|
||||
copyright: >
|
||||
Copyright © 2025 LangChain, Inc | <a href="#__consent">Consent Preferences</a>
|
||||
extra_css:
|
||||
- stylesheets/version_admonitions.css
|
||||
- stylesheets/logos.css
|
||||
|
||||