mirror of
https://github.com/langchain-ai/langgraph.git
synced 2026-08-18 05:35:43 +02:00
Compare commits
721
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
cddcf35c09 | ||
|
|
5eefc1d55d | ||
|
|
c9d4f1d77d | ||
|
|
1e2888ce39 | ||
|
|
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 | ||
|
|
addb491cfd | ||
|
|
c84f35eff5 | ||
|
|
f178e4205f | ||
|
|
3f4d1c66c2 | ||
|
|
2ee5b8e9d1 | ||
|
|
aadbcb443a | ||
|
|
a88794b74e | ||
|
|
556733c77c | ||
|
|
3d16acf3f5 | ||
|
|
87cbc4942d | ||
|
|
6d63300c9a | ||
|
|
a5dd181138 | ||
|
|
ad63b730b3 | ||
|
|
528d3946c6 | ||
|
|
037d9d1402 | ||
|
|
6aee213f3c | ||
|
|
f690f4244e | ||
|
|
d6856131b6 | ||
|
|
7d90440035 | ||
|
|
fed785eabd | ||
|
|
765b04adfd | ||
|
|
7085b149e5 | ||
|
|
11c71fef89 | ||
|
|
8be0fb675a | ||
|
|
1b4f335ffe | ||
|
|
9c36a7de85 | ||
|
|
d166dea4f0 | ||
|
|
8e922b859c | ||
|
|
9a4c30135f | ||
|
|
bc6651f34c | ||
|
|
23bb5369b9 | ||
|
|
85b81371f7 | ||
|
|
54ab833b74 | ||
|
|
4ea936eaf4 | ||
|
|
9d81ec9ffd | ||
|
|
46b652a74c | ||
|
|
7013ca9a3f | ||
|
|
0c04aec664 | ||
|
|
1650c8508e | ||
|
|
e176b98fe7 | ||
|
|
eb1e1aa010 | ||
|
|
77c833e1e5 | ||
|
|
0ac29434a7 | ||
|
|
43f5a17416 | ||
|
|
7d0857f263 | ||
|
|
b82d70a66a | ||
|
|
5fb037171d | ||
|
|
d3bb2b9aa0 | ||
|
|
ea765b4134 | ||
|
|
66ff83dca9 | ||
|
|
254e398345 | ||
|
|
c7567ea219 | ||
|
|
8c0306c3f4 | ||
|
|
992b05a196 | ||
|
|
893a9646d3 | ||
|
|
eaa37a2ce9 | ||
|
|
daee8d88bb | ||
|
|
eaa18cc2dd | ||
|
|
b2d9a36308 | ||
|
|
dd733a3389 | ||
|
|
03fc695d60 | ||
|
|
9994b09304 | ||
|
|
53f8558914 | ||
|
|
4bfcd84cee | ||
|
|
cd1d7be05f | ||
|
|
939a426a2e | ||
|
|
94c815f226 | ||
|
|
ef345aac5f | ||
|
|
e306258525 | ||
|
|
05cd317486 | ||
|
|
6dfed31a5e | ||
|
|
ee8374c4c0 | ||
|
|
2066894b5f | ||
|
|
6a2d20fd5b | ||
|
|
5b8b9f1067 | ||
|
|
c9cb8165d4 | ||
|
|
1f0348a5ca | ||
|
|
442ef0788e | ||
|
|
73f9ef0ef8 | ||
|
|
1f7a380548 | ||
|
|
8959f2aec5 | ||
|
|
0e7869eba4 | ||
|
|
d3f8478054 | ||
|
|
0cb1893475 | ||
|
|
e779c8e0b1 | ||
|
|
18b82cb8e2 | ||
|
|
972ab1a935 | ||
|
|
9cc2f37cca | ||
|
|
a2d7631f47 | ||
|
|
1e767c0653 | ||
|
|
d4c569cb7c | ||
|
|
a146df7f6a | ||
|
|
c52cc03e4b | ||
|
|
f206cfad8f | ||
|
|
d4c8b219c4 | ||
|
|
00855999d2 | ||
|
|
24bd0e1c1f | ||
|
|
3b59055192 | ||
|
|
67a16bec53 | ||
|
|
f97802eed5 | ||
|
|
bccb796ccc | ||
|
|
4068e9d135 | ||
|
|
a951334f7f | ||
|
|
75a727877f | ||
|
|
1cece3228c | ||
|
|
7ba48d75c9 | ||
|
|
7fb0628957 | ||
|
|
6edf29f043 | ||
|
|
c8a605cbc8 | ||
|
|
fbec207446 | ||
|
|
2223c82606 | ||
|
|
06f2eef74c | ||
|
|
62aa66cd4b | ||
|
|
8ffe9634b7 | ||
|
|
4b1d6d2aeb | ||
|
|
199ab46429 | ||
|
|
c758954519 | ||
|
|
5bfb3bb882 | ||
|
|
68a5c3f4c7 | ||
|
|
b7fb8e6afb | ||
|
|
c34c798763 | ||
|
|
792cd805a7 | ||
|
|
764929afd9 | ||
|
|
1e751a2256 | ||
|
|
e6726802f7 | ||
|
|
a541376d10 | ||
|
|
f9780330a6 | ||
|
|
347ab0165e | ||
|
|
cb95821eb0 | ||
|
|
4b9cdb4107 | ||
|
|
b440b14fa7 | ||
|
|
24f7d7c439 | ||
|
|
9533d35a84 | ||
|
|
48de4a7234 | ||
|
|
67ac35c5bc | ||
|
|
12c7ddf3a3 | ||
|
|
d6caa3b00a | ||
|
|
3d48526c16 | ||
|
|
2f3bd69bf5 | ||
|
|
f10a0c6f32 | ||
|
|
2eba27b01f | ||
|
|
c0245a6ee9 | ||
|
|
9e82d23252 | ||
|
|
460c522902 | ||
|
|
298a19b573 | ||
|
|
d2ec46b927 | ||
|
|
22e4bf74fc | ||
|
|
96a0536ec4 | ||
|
|
8d33938173 | ||
|
|
1c73b1e45a | ||
|
|
465d5d648b | ||
|
|
b751e8bcee | ||
|
|
8ec3982056 | ||
|
|
f17f264a7a | ||
|
|
086443472f | ||
|
|
936e69404e | ||
|
|
b1a25abc73 | ||
|
|
0e70b8d94f | ||
|
|
e1aa1a4510 | ||
|
|
ae7dbd1fa5 | ||
|
|
3ec95153ce | ||
|
|
4836f8b18b | ||
|
|
e7fbdeeb13 | ||
|
|
ee650ab85f | ||
|
|
7a959f62cc | ||
|
|
82905297fd | ||
|
|
9b5549f759 | ||
|
|
fa96c0ac76 | ||
|
|
98b8ff904c | ||
|
|
951131c8ec | ||
|
|
8bcdba822e | ||
|
|
60fc49b448 | ||
|
|
1d21b4ba08 | ||
|
|
55ec0d3d2a | ||
|
|
c7dd7be030 | ||
|
|
47d38a3022 | ||
|
|
8e829f38af | ||
|
|
3f241d00a3 | ||
|
|
f0abf582dd | ||
|
|
2458f2d2e0 | ||
|
|
477a43dae0 | ||
|
|
fc8e6ec64f | ||
|
|
d6a457ef1d | ||
|
|
ce1077da40 | ||
|
|
969958695a | ||
|
|
dd16ae4ba5 | ||
|
|
e24e141253 | ||
|
|
eae1faa656 | ||
|
|
1976d6584c | ||
|
|
54e18445fc | ||
|
|
69dc29aaf9 | ||
|
|
aa5ff74845 | ||
|
|
6049aaa842 | ||
|
|
576aa1ca02 | ||
|
|
e28e97d5e0 | ||
|
|
59e7c63c93 | ||
|
|
be7dee1c3b | ||
|
|
0aafa04bac | ||
|
|
2e1adaa867 | ||
|
|
3f8b165592 | ||
|
|
9ed0fa196c | ||
|
|
0b9adc28c3 | ||
|
|
3b0255d1ef | ||
|
|
80c3ccba7b | ||
|
|
d4255a0645 | ||
|
|
80d61a2600 | ||
|
|
424f24720a | ||
|
|
2a71180c1d | ||
|
|
697f878e36 | ||
|
|
987b9da4ab | ||
|
|
4bff1df4b0 | ||
|
|
5104e31e35 | ||
|
|
7ae4739630 | ||
|
|
5db1949ae3 | ||
|
|
ddb29df667 | ||
|
|
fa467573d7 | ||
|
|
1a728a93c6 | ||
|
|
def69c59d2 | ||
|
|
aaa0cd6b51 | ||
|
|
a9c831c11b | ||
|
|
bad4d17c34 | ||
|
|
55219b23d8 | ||
|
|
8edbd39ad3 | ||
|
|
4b0fd834d8 | ||
|
|
0fd2748530 | ||
|
|
bc0a3419ed | ||
|
|
5cd47bac49 | ||
|
|
4c6d80a67f | ||
|
|
18ed044c27 | ||
|
|
394a9fa85f | ||
|
|
9741d9bdf0 | ||
|
|
06ca07432d | ||
|
|
e757a80001 | ||
|
|
a204444905 | ||
|
|
4cfdf8774a | ||
|
|
beb62fc053 | ||
|
|
857f3e4a38 | ||
|
|
6342cd1665 | ||
|
|
baedf91836 | ||
|
|
190b42850f | ||
|
|
678b512aed | ||
|
|
c85e246c32 | ||
|
|
98ebc45f31 | ||
|
|
5ca2f358f9 | ||
|
|
86169c1439 | ||
|
|
36d6eed468 | ||
|
|
ef50fed6fe | ||
|
|
c0abfc7df6 | ||
|
|
318889bc6c | ||
|
|
b9e3fd5f3e | ||
|
|
8729ebc40c | ||
|
|
919282fead | ||
|
|
cff4784ff8 | ||
|
|
9921e5210a | ||
|
|
048eff9f11 | ||
|
|
8a2765c8f2 | ||
|
|
ffbcdd1ecc | ||
|
|
108a041fa7 | ||
|
|
52e3c59f07 | ||
|
|
0e17988332 | ||
|
|
5f0d05099d | ||
|
|
a1739d3184 | ||
|
|
ab38cc2cc0 | ||
|
|
647833dcaa | ||
|
|
1f03735b7d | ||
|
|
d980cca59b | ||
|
|
944b93bf61 | ||
|
|
8aa59d002a | ||
|
|
ed533b32a8 | ||
|
|
d88f59eea4 | ||
|
|
fc5dde6c55 | ||
|
|
4c902d21a3 | ||
|
|
54804af06a | ||
|
|
312f026e9c | ||
|
|
6973b19cc7 | ||
|
|
45ed67856f | ||
|
|
74b2dbe1ea | ||
|
|
7f803df586 | ||
|
|
a5b43c933a | ||
|
|
aae2fb4b85 | ||
|
|
c20a50875d | ||
|
|
779553f4aa | ||
|
|
537e69608e | ||
|
|
208cd4d70e | ||
|
|
1352e58133 | ||
|
|
f1162ac898 | ||
|
|
4de8443c5c | ||
|
|
96dc39aeab | ||
|
|
316f8410fa | ||
|
|
1d3926af27 | ||
|
|
e566ed4b3f | ||
|
|
14c2241853 | ||
|
|
2c908f1557 | ||
|
|
5005d1c004 | ||
|
|
02a46c45c8 | ||
|
|
852a129881 | ||
|
|
78348d2d9f | ||
|
|
44af8d5257 | ||
|
|
84c956bc8c | ||
|
|
b86e6b82f2 | ||
|
|
b1de5be334 | ||
|
|
0751428422 | ||
|
|
b16f05405b | ||
|
|
ca8d92421a | ||
|
|
7aa9d3fd00 | ||
|
|
ed69f60f24 | ||
|
|
c55f1f12bf | ||
|
|
5d76b1d624 | ||
|
|
857fd3578f | ||
|
|
3a4af1e573 | ||
|
|
37344124e1 | ||
|
|
d0f4db6ddd | ||
|
|
a9800aab87 | ||
|
|
9bf3fc2d0f | ||
|
|
a6e4bd93ff | ||
|
|
0e9c41f480 | ||
|
|
d4368cfa97 | ||
|
|
3808302309 | ||
|
|
25019450e2 | ||
|
|
e4c7db180e | ||
|
|
3183146141 | ||
|
|
f070b1c805 | ||
|
|
141589a7e6 | ||
|
|
be37631181 | ||
|
|
51ddc792d6 | ||
|
|
52d4f73e39 | ||
|
|
4b25e28e3e | ||
|
|
263eab9f76 | ||
|
|
c3df8bd500 | ||
|
|
d86502421d | ||
|
|
cbf26a5d98 | ||
|
|
09bd5990d4 | ||
|
|
79595d43a5 | ||
|
|
49a6704bdc | ||
|
|
a430b7fcfb | ||
|
|
48c287d107 | ||
|
|
0fdc787597 | ||
|
|
3bd86fc6f5 | ||
|
|
f1024f7341 | ||
|
|
f9ac88012f | ||
|
|
9d0186b5bf | ||
|
|
40062c40df | ||
|
|
36bbe059df | ||
|
|
52627010cb | ||
|
|
f6781d19ab | ||
|
|
fcf134a452 | ||
|
|
80331b88e0 | ||
|
|
b37f894f38 | ||
|
|
79de3dbad3 | ||
|
|
677fd3ce28 | ||
|
|
4ee863f30d | ||
|
|
7e060f88a2 | ||
|
|
f49856af0b | ||
|
|
5a7d384e2f | ||
|
|
b73b34ddd5 | ||
|
|
c9ffd753f5 | ||
|
|
e85e157e8f | ||
|
|
88e7868885 | ||
|
|
e8dd682320 | ||
|
|
75143b966c | ||
|
|
490e1aab3b | ||
|
|
003226cef4 | ||
|
|
098a199cb9 | ||
|
|
97f6f45993 | ||
|
|
e8631c052a | ||
|
|
16a86c8b8e | ||
|
|
5fa6bb5f55 | ||
|
|
d29e9e22c7 | ||
|
|
6990e1fcf5 | ||
|
|
22e60c47cc | ||
|
|
d9396c38ea | ||
|
|
ff60ee8c9a | ||
|
|
8761721fb9 | ||
|
|
de85e7c246 | ||
|
|
d333f4438f | ||
|
|
af14a2abbc | ||
|
|
e466c2c90c | ||
|
|
815a67ef55 | ||
|
|
38f1b415a0 | ||
|
|
ed78174adf | ||
|
|
5da6971a95 | ||
|
|
256e92bfb3 | ||
|
|
3d4e5c0471 | ||
|
|
013a12334e | ||
|
|
c7211e03e9 | ||
|
|
ffc916e38c | ||
|
|
03bf149ebd | ||
|
|
137dcce5b5 | ||
|
|
48164a95da | ||
|
|
3926e83884 | ||
|
|
43709a16bf | ||
|
|
d98c7248dc | ||
|
|
ac2736f18e | ||
|
|
fc130a52ef | ||
|
|
7d025e42ef | ||
|
|
4e9ed36f76 | ||
|
|
5d73df6133 | ||
|
|
fcc1210945 | ||
|
|
da5ee30bef | ||
|
|
57ff761cff | ||
|
|
f0a46bc3e3 | ||
|
|
b1587d24ed | ||
|
|
a1c676707c | ||
|
|
38b19fa99c | ||
|
|
3c3428da78 | ||
|
|
bb0125b4bb | ||
|
|
7580ad6005 | ||
|
|
eb8aa6b761 | ||
|
|
fe0de3e07e | ||
|
|
f51831f48e | ||
|
|
745eb90a6d | ||
|
|
f136e40065 | ||
|
|
de888b4032 | ||
|
|
7cb0bd52e8 | ||
|
|
3778f6113c | ||
|
|
24c13c211e | ||
|
|
2e36189c16 | ||
|
|
302aa8b9cb | ||
|
|
dac11f875c | ||
|
|
264be423f9 | ||
|
|
9a05600ff9 | ||
|
|
56dd728975 | ||
|
|
c157c956f4 | ||
|
|
dd293dad30 | ||
|
|
30811d7841 | ||
|
|
28a705b71a | ||
|
|
3b8130b96f | ||
|
|
94fc0adb05 | ||
|
|
162e96262f | ||
|
|
1bb0037450 | ||
|
|
50c53d3120 | ||
|
|
0b7b849633 | ||
|
|
678eb5cdbe | ||
|
|
a0969b61a3 | ||
|
|
e679ab73c4 | ||
|
|
b5a981d82d | ||
|
|
bdf1215ced | ||
|
|
f679348327 | ||
|
|
cba1852720 | ||
|
|
edf707be51 | ||
|
|
d3b9a96504 | ||
|
|
3257e5ae76 | ||
|
|
bedd0eb286 | ||
|
|
42f0c351fd | ||
|
|
a290984362 | ||
|
|
f1d6fd184f | ||
|
|
503f716104 | ||
|
|
b8fafa2795 | ||
|
|
515c34d1ce | ||
|
|
5ea0d49d4d | ||
|
|
d9f71ef8b3 | ||
|
|
8658a5dc0b | ||
|
|
2afee13d9e | ||
|
|
f7d9daa4eb | ||
|
|
fb28aa6d4b | ||
|
|
3488945cdf | ||
|
|
e6681bc175 | ||
|
|
57e8081921 | ||
|
|
078b335448 | ||
|
|
6615c6bb0d | ||
|
|
32df0016ee | ||
|
|
39b2bb9c8f | ||
|
|
5eb793d7d8 | ||
|
|
a9cdb9c948 | ||
|
|
3dac1894cc | ||
|
|
1500764b46 | ||
|
|
fbb89325f9 | ||
|
|
187c71a812 | ||
|
|
b09b33070e | ||
|
|
31a7bcf750 | ||
|
|
1a12b0309c | ||
|
|
660c15d072 | ||
|
|
4a59da7cfd | ||
|
|
aacc079eed | ||
|
|
3d70a4ed65 | ||
|
|
caad15f7ae | ||
|
|
1f4d4e7bfd | ||
|
|
5b0bf861ac | ||
|
|
a69ea47ac2 | ||
|
|
f83d18188f | ||
|
|
688efdea3d | ||
|
|
6641dcd3c9 | ||
|
|
c63fbbfaa6 | ||
|
|
577b4413a9 | ||
|
|
4dc8f813e7 | ||
|
|
f613fdfcbc | ||
|
|
265466184c |
@@ -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 lock --check
|
||||
|
||||
- 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:
|
||||
|
||||
@@ -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:
|
||||
@@ -39,6 +39,7 @@ jobs:
|
||||
- 'libs/checkpoint-sqlite/**'
|
||||
- 'libs/checkpoint-postgres/**'
|
||||
- 'libs/scheduler-kafka/**'
|
||||
- 'libs/prebuilt/**'
|
||||
sdk-js:
|
||||
- 'libs/sdk-js/**'
|
||||
|
||||
@@ -56,6 +57,7 @@ jobs:
|
||||
"libs/checkpoint-sqlite",
|
||||
"libs/checkpoint-postgres",
|
||||
"libs/scheduler-kafka",
|
||||
"libs/prebuilt",
|
||||
]
|
||||
if: needs.changes.outputs.python == 'true'
|
||||
uses: ./.github/workflows/_lint.yml
|
||||
@@ -74,6 +76,7 @@ jobs:
|
||||
"libs/checkpoint",
|
||||
"libs/checkpoint-sqlite",
|
||||
"libs/checkpoint-postgres",
|
||||
"libs/prebuilt",
|
||||
]
|
||||
if: needs.changes.outputs.python == 'true'
|
||||
uses: ./.github/workflows/_test.yml
|
||||
@@ -111,6 +114,42 @@ jobs:
|
||||
- name: Run check_sdk_methods script
|
||||
run: python .github/scripts/check_sdk_methods.py
|
||||
|
||||
check-schema:
|
||||
needs: changes
|
||||
if: needs.changes.outputs.python == 'true'
|
||||
name: "Check CLI schema hasn't changed #${{ matrix.python-version }}"
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
matrix:
|
||||
python-version:
|
||||
- "3.11"
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Set up Python ${{ matrix.python-version }} + Poetry ${{ env.POETRY_VERSION }}
|
||||
uses: "./.github/actions/poetry_setup"
|
||||
with:
|
||||
python-version: "3.11"
|
||||
poetry-version: ${{ env.POETRY_VERSION }}
|
||||
cache-key: schema-check-cli
|
||||
- name: Install CLI dependencies
|
||||
run: |
|
||||
cd libs/cli
|
||||
poetry install
|
||||
- name: Generate schema and check for changes
|
||||
run: |
|
||||
cd libs/cli
|
||||
# Create a temporary copy of the current schema
|
||||
cp schemas/schema.json schemas/schema.current.json
|
||||
# Generate new schema
|
||||
poetry run python generate_schema.py
|
||||
# Compare the new schema with the original
|
||||
if ! diff -q schemas/schema.json schemas/schema.current.json > /dev/null; then
|
||||
echo "Error: Langgraph.json configuration schema has changed. Please run 'poetry run python generate_schema.py' in the libs/cli directory and commit the changes."
|
||||
diff schemas/schema.json schemas/schema.current.json
|
||||
exit 1
|
||||
fi
|
||||
echo "Schema check passed - no changes detected"
|
||||
|
||||
integration-test:
|
||||
needs: changes
|
||||
if: needs.changes.outputs.python == 'true'
|
||||
@@ -177,6 +216,8 @@ jobs:
|
||||
test,
|
||||
test-langgraph,
|
||||
test-scheduler-kafka,
|
||||
check-sdk-methods,
|
||||
check-schema,
|
||||
integration-test,
|
||||
test-js,
|
||||
]
|
||||
|
||||
@@ -10,7 +10,7 @@ on:
|
||||
workflow_dispatch:
|
||||
|
||||
env:
|
||||
POETRY_VERSION: "1.7.1"
|
||||
POETRY_VERSION: "2.1.2"
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
@@ -63,35 +63,16 @@ jobs:
|
||||
poetry-version: ${{ env.POETRY_VERSION }}
|
||||
cache-key: docs
|
||||
|
||||
- name: Use Node.js
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: "22"
|
||||
cache: "yarn"
|
||||
cache-dependency-path: docs/yarn.lock
|
||||
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
yarn
|
||||
poetry install --with test --with docs --no-root
|
||||
poetry run pip install -U \
|
||||
pytest \
|
||||
pytest-check-links \
|
||||
GitPython \
|
||||
"git+https://github.com/benjamincburns/markdown-exec.git@cc0d39d737e5ffd4b83d23cd8729d7ea16e363c8"
|
||||
|
||||
# we run this installation only for internal PRs
|
||||
# as GITHUB_TOKEN is not available for PRs from outside contributors
|
||||
if [ -n "${GITHUB_TOKEN}" ]; then
|
||||
poetry run pip install "git+https://${GITHUB_TOKEN}@github.com/langchain-ai/mkdocs-material-insiders.git"
|
||||
fi
|
||||
|
||||
poetry run jupyter kernelspec list
|
||||
poetry run python3 -m ipykernel install --user --name=python3
|
||||
npm install -g tslab
|
||||
poetry run tslab install --python=python3
|
||||
poetry run jupyter kernelspec list
|
||||
|
||||
- name: Run unit tests
|
||||
# Run unit tests on the docs build pipeline
|
||||
run: make tests
|
||||
@@ -102,7 +83,14 @@ jobs:
|
||||
- name: Build llms-text
|
||||
run: make llms-text
|
||||
- name: Build site
|
||||
run: make build-docs
|
||||
run: |
|
||||
# If this is main branch, then we want to download stats. we do this
|
||||
# with the env variable DOWNLOAD_STATS=true
|
||||
if [ "${{ github.ref }}" == "refs/heads/main" ]; then
|
||||
DOWNLOAD_STATS=true make build-docs
|
||||
else
|
||||
make build-docs
|
||||
fi
|
||||
env:
|
||||
MKDOCS_GIT_COMMITTERS_APIKEY: ${{ secrets.MKDOCS_GIT_COMMITTERS_APIKEY }}
|
||||
OPENAI_API_KEY: sf-proj-1234567890 # fake placeholder, shouldn't actually be used
|
||||
@@ -111,12 +99,13 @@ jobs:
|
||||
env:
|
||||
LANGCHAIN_API_KEY: test
|
||||
run: |
|
||||
if [ "${{ github.event_name }}" == "schedule" ] || [ "${{ github.event_name }}" == "workflow_dispatch" ] || ([ "${{ github.event_name }}" == "push" ] && [ "${{ github.ref }}" == "refs/heads/main" ]); then
|
||||
if [ "${{ github.event_name }}" == "schedule" ]; then
|
||||
echo "Running link check on all HTML files matching notebooks in docs directory..."
|
||||
poetry run pytest -v \
|
||||
--check-links-ignore "https://(api|web|docs)\.smith\.langchain\.com/.*" \
|
||||
--check-links-ignore "https://academy\.langchain\.com/.*" \
|
||||
--check-links-ignore "https://x.com/.*" \
|
||||
--check-links-ignore "https://twitter.com/.*" \
|
||||
--check-links-ignore "https://github\.com/.*" \
|
||||
--check-links-ignore "http://localhost:8123/.*" \
|
||||
--check-links-ignore "http://localhost:2024.*" \
|
||||
@@ -126,6 +115,7 @@ jobs:
|
||||
--check-links-ignore "https://openai\.com/.*" \
|
||||
--check-links-ignore "https://www\.uber\.com/.*" \
|
||||
--check-links-ignore "https://pepy\.tech/.*" \
|
||||
--check-links-ignore "docs/docs/static/wordmark_*" \
|
||||
--check-links $(find site -name "index.html" | grep -v 'storm/index.html')
|
||||
|
||||
else
|
||||
@@ -143,8 +133,10 @@ jobs:
|
||||
--check-links-ignore "http://localhost:2024.*" \
|
||||
--check-links-ignore "http://127.0.0.1:.*" \
|
||||
--check-links-ignore "https://x.com/.*" \
|
||||
--check-links-ignore "https://twitter.com/.*" \
|
||||
--check-links-ignore "https://github\.com/.*" \
|
||||
--check-links-ignore "/.*\.(ipynb|html)$" \
|
||||
--check-links-ignore "docs/docs/static/wordmark_*" \
|
||||
--check-links ${CHANGED_FILES} \
|
||||
|| ([ $? = 5 ] && exit 0 || exit $?)
|
||||
else
|
||||
|
||||
@@ -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:
|
||||
@@ -195,7 +195,11 @@ jobs:
|
||||
"$PKG_NAME==$VERSION" \
|
||||
)
|
||||
|
||||
if [[ "$PKG_NAME" == *checkpoint* ]]; then
|
||||
if [[ "$PKG_NAME" == *prebuilt* ]]; then
|
||||
poetry run pip install langgraph
|
||||
fi
|
||||
|
||||
if [[ "$PKG_NAME" == *checkpoint* || "$PKG_NAME" == *prebuilt* ]]; then
|
||||
# since checkpoint packages are namespace packages, import them with . convention
|
||||
# i.e. import langgraph.checkpoint or langgraph.checkpoint.sqlite
|
||||
IMPORT_NAME="$(echo "$PKG_NAME" | sed s/-/./g)"
|
||||
|
||||
@@ -9,7 +9,7 @@ on:
|
||||
type: string
|
||||
description: "JSON string of changed files"
|
||||
schedule:
|
||||
- cron: '0 13 * * *'
|
||||
- cron: "0 13 * * *"
|
||||
|
||||
defaults:
|
||||
run:
|
||||
@@ -30,12 +30,12 @@ jobs:
|
||||
uses: "./.github/actions/poetry_setup"
|
||||
with:
|
||||
python-version: 3.11
|
||||
poetry-version: 1.7.1
|
||||
poetry-version: 2.1.2
|
||||
cache-key: test-langgraph-notebooks
|
||||
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
poetry install --with test
|
||||
poetry install --with test --no-root
|
||||
poetry run pip install jupyter
|
||||
|
||||
- name: Start services
|
||||
@@ -57,13 +57,13 @@ jobs:
|
||||
env:
|
||||
# these won't actually be used because of the VCR cassettes
|
||||
# but need to set them to avoid triggering getpass()
|
||||
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
|
||||
ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
|
||||
TAVILY_API_KEY: ${{ secrets.TAVILY_API_KEY }}
|
||||
LANGSMITH_API_KEY: ${{ secrets.LANGSMITH_API_KEY }}
|
||||
NOMIC_API_KEY: ${{ secrets.NOMIC_API_KEY }}
|
||||
COHERE_API_KEY: ${{ secrets.COHERE_API_KEY }}
|
||||
FIREWORKS_API_KEY: ${{ secrets.FIREWORKS_API_KEY }}
|
||||
OPENAI_API_KEY: "very-secret-key"
|
||||
ANTHROPIC_API_KEY: "very-secret-key"
|
||||
TAVILY_API_KEY: "very-secret-key"
|
||||
LANGSMITH_API_KEY: "very-secret-key"
|
||||
NOMIC_API_KEY: "very-secret-key"
|
||||
COHERE_API_KEY: "very-secret-key"
|
||||
FIREWORKS_API_KEY: "very-secret-key"
|
||||
run: |
|
||||
if [ "${{ github.event_name }}" = "workflow_dispatch" ] || [ "${{ github.event_name }}" = "schedule" ]; then
|
||||
echo "Running all notebooks"
|
||||
|
||||
@@ -1,29 +0,0 @@
|
||||
name: Check File Size
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
pull_request:
|
||||
branches:
|
||||
- main
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
file-size-check:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Get changed files
|
||||
id: changed-files
|
||||
uses: tj-actions/changed-files@v44
|
||||
- name: Filter by size
|
||||
# TODO: roll back the web voyager hack
|
||||
run: |
|
||||
large_added_files=$(find ${{ steps.changed-files.outputs.added_files }} -maxdepth 0 -size +1M | grep -v "web_voyager" || true)
|
||||
if [ -n "$large_added_files" ]; then
|
||||
echo "Large files added: $large_added_files"
|
||||
echo "# Large files added:" >> $GITHUB_STEP_SUMMARY
|
||||
echo "$large_added_files" >> $GITHUB_STEP_SUMMARY
|
||||
exit 1
|
||||
fi
|
||||
@@ -1,339 +1,87 @@
|
||||
# 🦜🕸️LangGraph
|
||||
<picture class="github-only">
|
||||
<source media="(prefers-color-scheme: light)" srcset="https://langchain-ai.github.io/langgraph/static/wordmark_dark.svg">
|
||||
<source media="(prefers-color-scheme: dark)" srcset="https://langchain-ai.github.io/langgraph/static/wordmark_light.svg">
|
||||
<img alt="LangGraph Logo" src="https://langchain-ai.github.io/langgraph/static/wordmark_dark.svg" width="80%">
|
||||
</picture>
|
||||
|
||||

|
||||
<div>
|
||||
<br>
|
||||
</div>
|
||||
|
||||
[](https://pypi.org/project/langgraph/)
|
||||
[](https://pepy.tech/project/langgraph)
|
||||
[](https://github.com/langchain-ai/langgraph/issues)
|
||||
[](https://langchain-ai.github.io/langgraph/)
|
||||
|
||||
⚡ Building language agents as graphs ⚡
|
||||
|
||||
> [!NOTE]
|
||||
> Looking for the JS version? See the [JS repo](https://github.com/langchain-ai/langgraphjs) and the [JS docs](https://langchain-ai.github.io/langgraphjs/).
|
||||
|
||||
## Overview
|
||||
LangGraph — used by Replit, Uber, LinkedIn, GitLab and more — is a low-level orchestration framework for building controllable agents. While langchain provides integrations and composable components to streamline LLM application development, the LangGraph library enables agent orchestration — offering customizable architectures, long-term memory, and human-in-the-loop to reliably handle complex tasks.
|
||||
|
||||
[LangGraph](https://langchain-ai.github.io/langgraph/) is a library for building
|
||||
stateful, multi-actor applications with LLMs, used to create agent and multi-agent
|
||||
workflows. Check out an introductory tutorial [here](https://langchain-ai.github.io/langgraph/tutorials/introduction/).
|
||||
|
||||
|
||||
LangGraph is inspired by [Pregel](https://research.google/pubs/pub37252/) and [Apache Beam](https://beam.apache.org/). The public interface draws inspiration from [NetworkX](https://networkx.org/documentation/latest/). LangGraph is built by LangChain Inc, the creators of LangChain, but can be used without LangChain.
|
||||
|
||||
### Why use LangGraph?
|
||||
|
||||
LangGraph powers [production-grade agents](https://www.langchain.com/built-with-langgraph), trusted by Linkedin, Uber, Klarna, GitLab, and many more. LangGraph provides fine-grained control over both the flow and state of your agent applications. It implements a central [persistence layer](https://langchain-ai.github.io/langgraph/concepts/persistence/), enabling features that are common to most agent architectures:
|
||||
|
||||
- **Memory**: LangGraph persists arbitrary aspects of your application's state,
|
||||
supporting memory of conversations and other updates within and across user
|
||||
interactions;
|
||||
- **Human-in-the-loop**: Because state is checkpointed, execution can be interrupted
|
||||
and resumed, allowing for decisions, validation, and corrections at key stages via
|
||||
human input.
|
||||
|
||||
Standardizing these components allows individuals and teams to focus on the behavior
|
||||
of their agent, instead of its supporting infrastructure.
|
||||
|
||||
Through [LangGraph Platform](#langgraph-platform), LangGraph also provides tooling for
|
||||
the development, deployment, debugging, and monitoring of your applications.
|
||||
|
||||
LangGraph integrates seamlessly with
|
||||
[LangChain](https://python.langchain.com/docs/introduction/) and
|
||||
[LangSmith](https://docs.smith.langchain.com/) (but does not require them).
|
||||
|
||||
To learn more about LangGraph, check out our first LangChain Academy
|
||||
course, *Introduction to LangGraph*, available for free
|
||||
[here](https://academy.langchain.com/courses/intro-to-langgraph).
|
||||
|
||||
### LangGraph Platform
|
||||
|
||||
[LangGraph Platform](https://langchain-ai.github.io/langgraph/concepts/langgraph_platform) is infrastructure for deploying LangGraph agents. It is a commercial solution for deploying agentic applications to production, built on the open-source LangGraph framework. The LangGraph Platform consists of several components that work together to support the development, deployment, debugging, and monitoring of LangGraph applications: [LangGraph Server](https://langchain-ai.github.io/langgraph/concepts/langgraph_server) (APIs), [LangGraph SDKs](https://langchain-ai.github.io/langgraph/concepts/sdk) (clients for the APIs), [LangGraph CLI](https://langchain-ai.github.io/langgraph/concepts/langgraph_cli) (command line tool for building the server), and [LangGraph Studio](https://langchain-ai.github.io/langgraph/concepts/langgraph_studio) (UI/debugger).
|
||||
|
||||
See deployment options [here](https://langchain-ai.github.io/langgraph/concepts/deployment_options/)
|
||||
(includes a free tier).
|
||||
|
||||
Here are some common issues that arise in complex deployments, which LangGraph Platform addresses:
|
||||
|
||||
- **Streaming support**: LangGraph Server provides [multiple streaming modes](https://langchain-ai.github.io/langgraph/concepts/streaming) optimized for various application needs
|
||||
- **Background runs**: Runs agents asynchronously in the background
|
||||
- **Support for long running agents**: Infrastructure that can handle long running processes
|
||||
- **[Double texting](https://langchain-ai.github.io/langgraph/concepts/double_texting)**: Handle the case where you get two messages from the user before the agent can respond
|
||||
- **Handle burstiness**: Task queue for ensuring requests are handled consistently without loss, even under heavy loads
|
||||
|
||||
## Installation
|
||||
|
||||
```shell
|
||||
```bash
|
||||
pip install -U langgraph
|
||||
```
|
||||
|
||||
## Example
|
||||
|
||||
Let's build a tool-calling [ReAct-style](https://langchain-ai.github.io/langgraph/concepts/agentic_concepts/#react-implementation) agent that uses a search tool!
|
||||
|
||||
```shell
|
||||
pip install langchain-anthropic
|
||||
```
|
||||
|
||||
```shell
|
||||
export ANTHROPIC_API_KEY=sk-...
|
||||
```
|
||||
|
||||
Optionally, we can set up [LangSmith](https://docs.smith.langchain.com/) for best-in-class observability.
|
||||
|
||||
```shell
|
||||
export LANGSMITH_TRACING=true
|
||||
export LANGSMITH_API_KEY=lsv2_sk_...
|
||||
```
|
||||
|
||||
The simplest way to create a tool-calling agent in LangGraph is to use `create_react_agent`:
|
||||
|
||||
<details open>
|
||||
<summary>High-level implementation</summary>
|
||||
To learn more about how to use LangGraph, check out [the docs](https://langchain-ai.github.io/langgraph/). We show a simple example below of how to create a ReAct agent.
|
||||
|
||||
```python
|
||||
# This code depends on pip install langchain[anthropic]
|
||||
from langgraph.prebuilt import create_react_agent
|
||||
from langgraph.checkpoint.memory import MemorySaver
|
||||
from langchain_anthropic import ChatAnthropic
|
||||
from langchain_core.tools import tool
|
||||
|
||||
# Define the tools for the agent to use
|
||||
@tool
|
||||
def search(query: str):
|
||||
"""Call to surf the web."""
|
||||
# This is a placeholder, but don't tell the LLM that...
|
||||
if "sf" in query.lower() or "san francisco" in query.lower():
|
||||
return "It's 60 degrees and foggy."
|
||||
return "It's 90 degrees and sunny."
|
||||
|
||||
|
||||
tools = [search]
|
||||
model = ChatAnthropic(model="claude-3-5-sonnet-latest", temperature=0)
|
||||
|
||||
# Initialize memory to persist state between graph runs
|
||||
checkpointer = MemorySaver()
|
||||
|
||||
app = create_react_agent(model, tools, checkpointer=checkpointer)
|
||||
|
||||
# Use the agent
|
||||
final_state = app.invoke(
|
||||
{"messages": [{"role": "user", "content": "what is the weather in sf"}]},
|
||||
config={"configurable": {"thread_id": 42}}
|
||||
agent = create_react_agent("anthropic:claude-3-7-sonnet-latest", tools=[search])
|
||||
agent.invoke(
|
||||
{"messages": [{"role": "user", "content": "what is the weather in sf"}]}
|
||||
)
|
||||
final_state["messages"][-1].content
|
||||
```
|
||||
```
|
||||
"Based on the search results, I can tell you that the current weather in San Francisco is:\n\nTemperature: 60 degrees Fahrenheit\nConditions: Foggy\n\nSan Francisco is known for its microclimates and frequent fog, especially during the summer months. The temperature of 60°F (about 15.5°C) is quite typical for the city, which tends to have mild temperatures year-round. The fog, often referred to as "Karl the Fog" by locals, is a characteristic feature of San Francisco\'s weather, particularly in the mornings and evenings.\n\nIs there anything else you\'d like to know about the weather in San Francisco or any other location?"
|
||||
```
|
||||
|
||||
Now when we pass the same <code>"thread_id"</code>, the conversation context is retained via the saved state (i.e. stored list of messages)
|
||||
## Why use LangGraph?
|
||||
|
||||
```python
|
||||
final_state = app.invoke(
|
||||
{"messages": [{"role": "user", "content": "what about ny"}]},
|
||||
config={"configurable": {"thread_id": 42}}
|
||||
)
|
||||
final_state["messages"][-1].content
|
||||
```
|
||||
LangGraph is built for developers who want to build powerful, adaptable AI agents. Developers choose LangGraph for:
|
||||
|
||||
```
|
||||
"Based on the search results, I can tell you that the current weather in New York City is:\n\nTemperature: 90 degrees Fahrenheit (approximately 32.2 degrees Celsius)\nConditions: Sunny\n\nThis weather is quite different from what we just saw in San Francisco. New York is experiencing much warmer temperatures right now. Here are a few points to note:\n\n1. The temperature of 90°F is quite hot, typical of summer weather in New York City.\n2. The sunny conditions suggest clear skies, which is great for outdoor activities but also means it might feel even hotter due to direct sunlight.\n3. This kind of weather in New York often comes with high humidity, which can make it feel even warmer than the actual temperature suggests.\n\nIt's interesting to see the stark contrast between San Francisco's mild, foggy weather and New York's hot, sunny conditions. This difference illustrates how varied weather can be across different parts of the United States, even on the same day.\n\nIs there anything else you'd like to know about the weather in New York or any other location?"
|
||||
```
|
||||
</details>
|
||||
- **Reliability and controllability.** Steer agent actions with moderation checks and human-in-the-loop approvals. LangGraph persists context for long-running workflows, keeping your agents on course.
|
||||
- **Low-level and extensible.** Build custom agents with fully descriptive, low-level primitives – free from rigid abstractions that limit customization. Design scalable multi-agent systems, with each agent serving a specific role tailored to your use case.
|
||||
- **First-class streaming support.** With token-by-token streaming and streaming of intermediate steps, LangGraph gives users clear visibility into agent reasoning and actions as they unfold in real time.
|
||||
|
||||
> [!TIP]
|
||||
> LangGraph is a **low-level** framework that allows you to implement any custom agent
|
||||
architectures. Click on the low-level implementation below to see how to implement a
|
||||
tool-calling agent from scratch.
|
||||
LangGraph is trusted in production and powering agents for companies like:
|
||||
|
||||
<details>
|
||||
<summary>Low-level implementation</summary>
|
||||
- [Klarna](https://blog.langchain.dev/customers-klarna/): Customer support bot for 85 million active users
|
||||
- [Elastic](https://www.elastic.co/blog/elastic-security-generative-ai-features): Security AI assistant for threat detection
|
||||
- [Uber](https://dpe.org/sessions/ty-smith-adam-huda/this-year-in-ubers-ai-driven-developer-productivity-revolution/): Automated unit test generation
|
||||
- [Replit](https://www.langchain.com/breakoutagents/replit): Code generation
|
||||
- And many more ([see list here](https://www.langchain.com/built-with-langgraph))
|
||||
|
||||
```python
|
||||
from typing import Literal
|
||||
## LangGraph’s ecosystem
|
||||
|
||||
from langchain_anthropic import ChatAnthropic
|
||||
from langchain_core.tools import tool
|
||||
from langgraph.checkpoint.memory import MemorySaver
|
||||
from langgraph.graph import END, START, StateGraph, MessagesState
|
||||
from langgraph.prebuilt import ToolNode
|
||||
While LangGraph can be used standalone, it also integrates seamlessly with any LangChain product, giving developers a full suite of tools for building agents. To improve your LLM application development, pair LangGraph with:
|
||||
|
||||
- [LangSmith](http://www.langchain.com/langsmith) — Helpful for agent evals and observability. Debug poor-performing LLM app runs, evaluate agent trajectories, gain visibility in production, and improve performance over time.
|
||||
- [LangGraph Platform](https://langchain-ai.github.io/langgraph/concepts/#langgraph-platform) — Deploy and scale agents effortlessly with a purpose-built deployment platform for long running, stateful workflows. Discover, reuse, configure, and share agents across teams — and iterate quickly with visual prototyping in [LangGraph Studio](https://langchain-ai.github.io/langgraph/concepts/langgraph_studio/).
|
||||
|
||||
# Define the tools for the agent to use
|
||||
@tool
|
||||
def search(query: str):
|
||||
"""Call to surf the web."""
|
||||
# This is a placeholder, but don't tell the LLM that...
|
||||
if "sf" in query.lower() or "san francisco" in query.lower():
|
||||
return "It's 60 degrees and foggy."
|
||||
return "It's 90 degrees and sunny."
|
||||
## Pairing with LangGraph Platform
|
||||
|
||||
While LangGraph is our open-source agent orchestration framework, enterprises that need scalable agent deployment can benefit from [LangGraph Platform](https://langchain-ai.github.io/langgraph/concepts/langgraph_platform/).
|
||||
|
||||
tools = [search]
|
||||
LangGraph Platform can help engineering teams:
|
||||
|
||||
tool_node = ToolNode(tools)
|
||||
- **Accelerate agent development**: Quickly create agent UXs with configurable templates and [LangGraph Studio](https://langchain-ai.github.io/langgraph/concepts/langgraph_studio/) for visualizing and debugging agent interactions.
|
||||
- **Deploy seamlessly**: We handle the complexity of deploying your agent. LangGraph Platform includes robust APIs for memory, threads, and cron jobs plus auto-scaling task queues & servers.
|
||||
- **Centralize agent management & reusability**: Discover, reuse, and manage agents across the organization. Business users can also modify agents without coding.
|
||||
|
||||
model = ChatAnthropic(model="claude-3-5-sonnet-latest", temperature=0).bind_tools(tools)
|
||||
## Additional resources
|
||||
|
||||
# Define the function that determines whether to continue or not
|
||||
def should_continue(state: MessagesState) -> Literal["tools", END]:
|
||||
messages = state['messages']
|
||||
last_message = messages[-1]
|
||||
# If the LLM makes a tool call, then we route to the "tools" node
|
||||
if last_message.tool_calls:
|
||||
return "tools"
|
||||
# Otherwise, we stop (reply to the user)
|
||||
return END
|
||||
- [LangChain Academy](https://academy.langchain.com/courses/intro-to-langgraph): Learn the basics of LangGraph in our free, structured course.
|
||||
- [Tutorials](https://langchain-ai.github.io/langgraph/tutorials/): Simple walkthroughs with guided examples on getting started with LangGraph.
|
||||
- [Templates](https://langchain-ai.github.io/langgraph/concepts/template_applications/): Pre-built reference apps for common agentic workflows (e.g. ReAct agent, memory, retrieval etc.) that can be cloned and adapted.
|
||||
- [How-to Guides](https://langchain-ai.github.io/langgraph/how-tos/): Quick, actionable code snippets for topics such as streaming, adding memory & persistence, and design patterns (e.g. branching, subgraphs, etc.).
|
||||
- [API Reference](https://langchain-ai.github.io/langgraph/reference/graphs/): Detailed reference on core classes, methods, how to use the graph and checkpointing APIs, and higher-level prebuilt components.
|
||||
- [Built with LangGraph](https://www.langchain.com/built-with-langgraph): Hear how industry leaders use LangGraph to ship powerful, production-ready AI applications.
|
||||
|
||||
## Acknowledgements
|
||||
|
||||
# Define the function that calls the model
|
||||
def call_model(state: MessagesState):
|
||||
messages = state['messages']
|
||||
response = model.invoke(messages)
|
||||
# We return a list, because this will get added to the existing list
|
||||
return {"messages": [response]}
|
||||
|
||||
|
||||
# Define a new graph
|
||||
workflow = StateGraph(MessagesState)
|
||||
|
||||
# Define the two nodes we will cycle between
|
||||
workflow.add_node("agent", call_model)
|
||||
workflow.add_node("tools", tool_node)
|
||||
|
||||
# Set the entrypoint as `agent`
|
||||
# This means that this node is the first one called
|
||||
workflow.add_edge(START, "agent")
|
||||
|
||||
# We now add a conditional edge
|
||||
workflow.add_conditional_edges(
|
||||
# First, we define the start node. We use `agent`.
|
||||
# This means these are the edges taken after the `agent` node is called.
|
||||
"agent",
|
||||
# Next, we pass in the function that will determine which node is called next.
|
||||
should_continue,
|
||||
)
|
||||
|
||||
# We now add a normal edge from `tools` to `agent`.
|
||||
# This means that after `tools` is called, `agent` node is called next.
|
||||
workflow.add_edge("tools", 'agent')
|
||||
|
||||
# Initialize memory to persist state between graph runs
|
||||
checkpointer = MemorySaver()
|
||||
|
||||
# Finally, we compile it!
|
||||
# This compiles it into a LangChain Runnable,
|
||||
# meaning you can use it as you would any other runnable.
|
||||
# Note that we're (optionally) passing the memory when compiling the graph
|
||||
app = workflow.compile(checkpointer=checkpointer)
|
||||
|
||||
# Use the agent
|
||||
final_state = app.invoke(
|
||||
{"messages": [{"role": "user", "content": "what is the weather in sf"}]},
|
||||
config={"configurable": {"thread_id": 42}}
|
||||
)
|
||||
final_state["messages"][-1].content
|
||||
```
|
||||
|
||||
<b>Step-by-step Breakdown</b>:
|
||||
|
||||
<details>
|
||||
<summary>Initialize the model and tools.</summary>
|
||||
<ul>
|
||||
<li>
|
||||
We use <code>ChatAnthropic</code> as our LLM. <strong>NOTE:</strong> we need to make sure the model knows that it has these tools available to call. We can do this by converting the LangChain tools into the format for OpenAI tool calling using the <code>.bind_tools()</code> method.
|
||||
</li>
|
||||
<li>
|
||||
We define the tools we want to use - a search tool in our case. It is really easy to create your own tools - see documentation here on how to do that <a href="https://python.langchain.com/docs/how_to/custom_tools/">here</a>.
|
||||
</li>
|
||||
</ul>
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary>Initialize graph with state.</summary>
|
||||
|
||||
<ul>
|
||||
<li>We initialize graph (<code>StateGraph</code>) by passing state schema (in our case <code>MessagesState</code>)</li>
|
||||
<li><code>MessagesState</code> is a prebuilt state schema that has one attribute -- a list of LangChain <code>Message</code> objects, as well as logic for merging the updates from each node into the state.</li>
|
||||
</ul>
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary>Define graph nodes.</summary>
|
||||
|
||||
There are two main nodes we need:
|
||||
|
||||
<ul>
|
||||
<li>The <code>agent</code> node: responsible for deciding what (if any) actions to take.</li>
|
||||
<li>The <code>tools</code> node that invokes tools: if the agent decides to take an action, this node will then execute that action.</li>
|
||||
</ul>
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary>Define entry point and graph edges.</summary>
|
||||
|
||||
First, we need to set the entry point for graph execution - <code>agent</code> node.
|
||||
|
||||
Then we define one normal and one conditional edge. Conditional edge means that the destination depends on the contents of the graph's state (<code>MessagesState</code>). In our case, the destination is not known until the agent (LLM) decides.
|
||||
|
||||
<ul>
|
||||
<li>Conditional edge: after the agent is called, we should either:
|
||||
<ul>
|
||||
<li>a. Run tools if the agent said to take an action, OR</li>
|
||||
<li>b. Finish (respond to the user) if the agent did not ask to run tools</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li>Normal edge: after the tools are invoked, the graph should always return to the agent to decide what to do next</li>
|
||||
</ul>
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary>Compile the graph.</summary>
|
||||
|
||||
<ul>
|
||||
<li>
|
||||
When we compile the graph, we turn it into a LangChain
|
||||
<a href="https://python.langchain.com/docs/concepts/runnables/">Runnable</a>,
|
||||
which automatically enables calling <code>.invoke()</code>, <code>.stream()</code> and <code>.batch()</code>
|
||||
with your inputs
|
||||
</li>
|
||||
<li>
|
||||
We can also optionally pass checkpointer object for persisting state between graph runs, and enabling memory,
|
||||
human-in-the-loop workflows, time travel and more. In our case we use <code>MemorySaver</code> -
|
||||
a simple in-memory checkpointer
|
||||
</li>
|
||||
</ul>
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary>Execute the graph.</summary>
|
||||
|
||||
<ol>
|
||||
<li>LangGraph adds the input message to the internal state, then passes the state to the entrypoint node, <code>"agent"</code>.</li>
|
||||
<li>The <code>"agent"</code> node executes, invoking the chat model.</li>
|
||||
<li>The chat model returns an <code>AIMessage</code>. LangGraph adds this to the state.</li>
|
||||
<li>Graph cycles the following steps until there are no more <code>tool_calls</code> on <code>AIMessage</code>:
|
||||
<ul>
|
||||
<li>If <code>AIMessage</code> has <code>tool_calls</code>, <code>"tools"</code> node executes</li>
|
||||
<li>The <code>"agent"</code> node executes again and returns <code>AIMessage</code></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li>Execution progresses to the special <code>END</code> value and outputs the final state. And as a result, we get a list of all our chat messages as output.</li>
|
||||
</ol>
|
||||
</details>
|
||||
|
||||
</details>
|
||||
|
||||
## Documentation
|
||||
|
||||
* [Tutorials](https://langchain-ai.github.io/langgraph/tutorials/): Learn to build with LangGraph through guided examples.
|
||||
* [How-to Guides](https://langchain-ai.github.io/langgraph/how-tos/): Accomplish specific things within LangGraph, from streaming, to adding memory & persistence, to common design patterns (branching, subgraphs, etc.), these are the place to go if you want to copy and run a specific code snippet.
|
||||
* [Conceptual Guides](https://langchain-ai.github.io/langgraph/concepts/high_level/): In-depth explanations of the key concepts and principles behind LangGraph, such as nodes, edges, state and more.
|
||||
* [API Reference](https://langchain-ai.github.io/langgraph/reference/graphs/): Review important classes and methods, simple examples of how to use the graph and checkpointing APIs, higher-level prebuilt components and more.
|
||||
* [LangGraph Platform](https://langchain-ai.github.io/langgraph/concepts/#langgraph-platform): LangGraph Platform is a commercial solution for deploying agentic applications in production, built on the open-source LangGraph framework.
|
||||
|
||||
## Resources
|
||||
|
||||
* [Built with LangGraph](https://www.langchain.com/built-with-langgraph): Hear how industry leaders use LangGraph to ship powerful, production-ready AI applications.
|
||||
|
||||
## Contributing
|
||||
|
||||
For more information on how to contribute, see [here](https://github.com/langchain-ai/langgraph/blob/main/CONTRIBUTING.md).
|
||||
LangGraph is inspired by [Pregel](https://research.google/pubs/pub37252/) and [Apache Beam](https://beam.apache.org/). The public interface draws inspiration from [NetworkX](https://networkx.org/documentation/latest/). LangGraph is built by LangChain Inc, the creators of LangChain, but can be used without LangChain.
|
||||
+9
-1
@@ -10,7 +10,15 @@ build-prebuilt:
|
||||
# Use to create an update to date prebuilt page.
|
||||
# Looks up download stats for each of the prebuilt packages and
|
||||
# generates the final prebuilt page.
|
||||
poetry run python -m _scripts.third_party_page.get_download_stats stats.yml
|
||||
@if [ "$(DOWNLOAD_STATS)" = "true" ]; then \
|
||||
set -x; \
|
||||
poetry run python -m _scripts.third_party_page.get_download_stats stats.yml; \
|
||||
set +x; \
|
||||
else \
|
||||
set -x; \
|
||||
poetry run python -m _scripts.third_party_page.get_download_stats --fake stats.yml; \
|
||||
set +x; \
|
||||
fi
|
||||
poetry run python -m _scripts.third_party_page.create_third_party_page stats.yml docs/prebuilt.md --language python
|
||||
|
||||
build-docs: build-typedoc build-prebuilt
|
||||
|
||||
@@ -14,6 +14,8 @@ To run the documentation server locally you can run:
|
||||
make serve-docs
|
||||
```
|
||||
|
||||
This will start the documentation server on [http://127.0.0.1:8000/langgraph/](http://127.0.0.1:8000/langgraph/).
|
||||
|
||||
## Execute notebooks
|
||||
|
||||
If you would like to automatically execute all of the notebooks, to mimic the "Run notebooks" GHA, you can run:
|
||||
|
||||
@@ -186,7 +186,7 @@ def _on_page_markdown_with_config(
|
||||
|
||||
if remove_base64_images:
|
||||
# Remove base64 encoded images from markdown
|
||||
markdown = re.sub(r"!\[.*?\]\(data:image/+;base64,[^\)]+\)", "", markdown)
|
||||
markdown = re.sub(r"!\[.*?\]\(data:image/[^;]+;base64,[^)]+\)", "", markdown)
|
||||
|
||||
return markdown
|
||||
|
||||
|
||||
@@ -83,14 +83,18 @@ def generate_markdown(resolved_packages: List[ResolvedPackage], language: str) -
|
||||
resolved_packages, key=lambda p: p["weekly_downloads"] or 0, reverse=True
|
||||
)
|
||||
rows = [
|
||||
"| Name | GitHub URL | Description | Weekly Downloads |",
|
||||
"| --- | --- | --- | --- |",
|
||||
"| Name | GitHub URL | Description | Weekly Downloads | Stars |",
|
||||
"| --- | --- | --- | --- | --- |",
|
||||
]
|
||||
for package in sorted_packages:
|
||||
name = f"**{package['name']}**"
|
||||
repo_url = f"[{package['repo']}](https://github.com/{package['repo']})"
|
||||
stars_badge = (
|
||||
f"https://img.shields.io/github/stars/{package['repo']}?style=social"
|
||||
)
|
||||
stars = f""
|
||||
downloads = package["weekly_downloads"] or "-"
|
||||
row = f"| {name} | {repo_url} | {package['description']} | {downloads} |"
|
||||
row = f"| {name} | {repo_url} | {package['description']} | {downloads} | {stars}"
|
||||
rows.append(row)
|
||||
markdown_content = MARKDOWN.format(
|
||||
library_list="\n".join(rows), langgraph_url=langgraph_url
|
||||
|
||||
@@ -30,10 +30,23 @@ PACKAGES_FILE = HERE / "packages.yml"
|
||||
PACKAGES = yaml.safe_load(PACKAGES_FILE.read_text())['packages']
|
||||
|
||||
|
||||
def _get_weekly_downloads(packages: list[Package]) -> list[ResolvedPackage]:
|
||||
def _get_weekly_downloads(packages: list[Package], fake: bool) -> list[ResolvedPackage]:
|
||||
"""Retrieve the monthly download count for a list of packages from PyPIStats."""
|
||||
resolved_packages: list[ResolvedPackage] = []
|
||||
|
||||
if fake:
|
||||
# To avoid making network requests during testing, return fake download counts
|
||||
for package in packages:
|
||||
resolved_packages.append(
|
||||
{
|
||||
"name": package["name"],
|
||||
"repo": package["repo"],
|
||||
"weekly_downloads": -12345,
|
||||
"description": package["description"],
|
||||
}
|
||||
)
|
||||
return resolved_packages
|
||||
|
||||
for package in packages:
|
||||
# First check if package exists on PyPI
|
||||
pypi_url = f"https://pypi.org/pypi/{package['name']}/json"
|
||||
@@ -88,13 +101,13 @@ def _get_weekly_downloads(packages: list[Package]) -> list[ResolvedPackage]:
|
||||
|
||||
|
||||
|
||||
def main(output_file: str) -> None:
|
||||
def main(output_file: str, fake: bool) -> None:
|
||||
"""Main function to generate package download information.
|
||||
|
||||
Args:
|
||||
output_file: Path to the output YAML file.
|
||||
"""
|
||||
resolved_packages: list[ResolvedPackage] = _get_weekly_downloads(PACKAGES)
|
||||
resolved_packages: list[ResolvedPackage] = _get_weekly_downloads(PACKAGES, fake)
|
||||
|
||||
if not output_file.endswith(".yml"):
|
||||
raise ValueError("Output file must have a .yml extension")
|
||||
@@ -115,6 +128,15 @@ if __name__ == "__main__":
|
||||
"downloads.yml"
|
||||
),
|
||||
)
|
||||
parser.add_argument(
|
||||
"--fake",
|
||||
default=False,
|
||||
action="store_true",
|
||||
help=(
|
||||
"Generate fake download counts for testing purposes. "
|
||||
"This option will not make any network requests."
|
||||
),
|
||||
)
|
||||
args = parser.parse_args()
|
||||
|
||||
main(args.output_file)
|
||||
main(args.output_file, args.fake)
|
||||
|
||||
@@ -2,16 +2,40 @@
|
||||
packages:
|
||||
- name: "trustcall"
|
||||
repo: "hinthornw/trustcall"
|
||||
description: "Tenacious tool calling built on LangGraph"
|
||||
description: "Tenacious tool calling built on LangGraph."
|
||||
- name: "breeze-agent"
|
||||
repo: "andrestorres123/breeze-agent"
|
||||
description: "A streamlined research system built inspired on STORM and built on LangGraph"
|
||||
description: "A streamlined research system built inspired on STORM and built on LangGraph."
|
||||
- name: "langgraph-supervisor"
|
||||
repo: "langchain-ai/langgraph-supervisor"
|
||||
description: "Build supervisor multi-agent systems with LangGraph"
|
||||
repo: "langchain-ai/langgraph-supervisor-py"
|
||||
description: "Build supervisor multi-agent systems with LangGraph."
|
||||
- name: "langmem"
|
||||
repo: "langchain-ai/langmem"
|
||||
description: "Build agents that learn and adapt from interactions over time."
|
||||
- name: "langchain-mcp-adapters"
|
||||
repo: "langchain-ai/langchain-mcp-adapters"
|
||||
description: "Make Anthropic Model Context Protocol (MCP) tools compatible with LangGraph agents."
|
||||
description: "Make Anthropic Model Context Protocol (MCP) tools compatible with LangGraph agents."
|
||||
- name: "open-deep-research"
|
||||
repo: "langchain-ai/open_deep_research"
|
||||
description: "Open source assistant for iterative web research and report writing."
|
||||
- name: "langgraph-swarm"
|
||||
repo: "langchain-ai/langgraph-swarm-py"
|
||||
description: "Build swarm-style multi-agent systems using LangGraph."
|
||||
- name: "delve-taxonomy-generator"
|
||||
repo: "andrestorres123/delve"
|
||||
description: "A taxonomy generator for unstructured data"
|
||||
- name: "nodeology"
|
||||
repo: "xyin-anl/Nodeology"
|
||||
description: "Enable researcher to build scientific workflows easily with simplified interface."
|
||||
- name: "langgraph-bigtool"
|
||||
repo: "langchain-ai/langgraph-bigtool"
|
||||
description: "Build LangGraph agents with large numbers of tools."
|
||||
- name: "ai-data-science-team"
|
||||
repo: "business-science/ai-data-science-team"
|
||||
description: "An AI-powered data science team of agents to help you perform common data science tasks 10X faster."
|
||||
- name: "langgraph-reflection"
|
||||
repo: "langchain-ai/langgraph-reflection"
|
||||
description: "LangGraph agent that runs a reflection step."
|
||||
- name: "langgraph-codeact"
|
||||
repo: "langchain-ai/langgraph-codeact"
|
||||
description: "LangGraph implementation of CodeAct agent that generates and executes code instead of tool calling."
|
||||
|
||||
+1
@@ -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==
|
||||
+1
File diff suppressed because one or more lines are too long
+1
File diff suppressed because one or more lines are too long
+1
File diff suppressed because one or more lines are too long
@@ -1,4 +1,4 @@
|
||||
# 🦜🕸️ LangGraph Adopters
|
||||
# 🦜🕸️ Companies using LangGraph
|
||||
|
||||
This list of companies using LangGraph and their success stories is compiled from public sources. If your company uses LangGraph, we'd love for you to share your story and add it to the list. You’re also welcome to contribute updates based on publicly available information from other companies, such as blog posts or press releases.
|
||||
|
||||
@@ -9,17 +9,23 @@ This list of companies using LangGraph and their success stories is compiled fro
|
||||
| [AppFolio](https://www.appfolio.com/) | Real Estate | Copilot for domain-specific task | [Case study, 2024](https://blog.langchain.dev/customers-appfolio/) |
|
||||
| [Athena Intelligence](https://www.athenaintel.com/) | Software & Technology (GenAI Native) | Research & summarization | [Case study, 2024](https://blog.langchain.dev/customers-athena-intelligence/) |
|
||||
| [Captide](https://www.captide.co/) | Software & Technology (GenAI Native) | Data extraction | [Case study, 2025](https://blog.langchain.dev/how-captide-is-redefining-equity-research-with-agentic-workflows-built-on-langgraph-and-langsmith/) |
|
||||
| [Cisco Outshift](https://outshift.cisco.com/) | Software & Technology | DevOps | [Blog post, 2025](https://outshift.cisco.com/blog/build-react-agent-application-for-devops-tasks-using-rest-apis) |
|
||||
| [C.H. Robinson](https://www.chrobinson.com/en-us/) | Logistics | Automation | [Case study, 2025](https://blog.langchain.dev/customers-chrobinson/) |
|
||||
| [Elastic](https://www.elastic.co/) | Software & Technology | Copilot for domain-specific task | [Blog post, 2025](https://www.elastic.co/blog/elastic-security-generative-ai-features) |
|
||||
| [GitLab](https://about.gitlab.com/) | Software & Technology | Code generation | [Duo workflow docs](https://handbook.gitlab.com/handbook/engineering/architecture/design-documents/duo_workflow/) |
|
||||
| [Inconvo](https://inconvo.ai/?ref=blog.langchain.dev) | Software & Technology | Code generation | [Case study, 2025](https://blog.langchain.dev/customers-inconvo/) |
|
||||
| [Infor](https://infor.com/) | Software & Technology | GenAI embedded product experiences; customer support; copilot | [Case study, 2025](https://blog.langchain.dev/customers-infor/) |
|
||||
| [Klarna](https://www.klarna.com/) | Fintech | Copilot for domain-specific task | [Case study, 2025](https://blog.langchain.dev/customers-klarna/) |
|
||||
| [Komodo Health](https://www.komodohealth.com/) | Healthcare | Copilot for domain-specific task | [Blog post](https://www.komodohealth.com/perspectives/new-gen-ai-assistant-empowers-the-enterprise/) |
|
||||
| [LinkedIn](https://www.linkedin.com/) | Social Media | Code generation; Search & discovery | [Blog post, 2025](https://www.linkedin.com/blog/engineering/ai/practical-text-to-sql-for-data-analytics); [Blog post, 2024](https://www.linkedin.com/blog/engineering/generative-ai/behind-the-platform-the-journey-to-create-the-linkedin-genai-application-tech-stack) |
|
||||
| [Minimal](https://gominimal.ai/) | E-commerce | Customer support | [Case study, 2025](https://blog.langchain.dev/how-minimal-built-a-multi-agent-customer-support-system-with-langgraph-langsmith/) |
|
||||
| [OpenRecovery](https://www.openrecovery.com/) | Healthcare | Copilot for domain-specific task | [Case study, 2024](https://blog.langchain.dev/customers-openrecovery/) |
|
||||
| [Qodo](https://www.qodo.ai/) | Software & Technology (GenAI Native) | Code generation | [Blog post, 2025](https://www.qodo.ai/blog/why-we-chose-langgraph-to-build-our-coding-agent/) |
|
||||
| [Rakuten](https://www.rakuten.com/) | E-commerce / Fintech | Copilot for domain-specific task | [Blog post, 2025](https://rakuten.today/blog/from-ai-hype-to-real-world-tools-rakuten-teams-up-with-langchain.html) |
|
||||
| [Replit](https://replit.com/) | Software & Technology | Code generation | [Blog post, 2024](https://blog.langchain.dev/customers-replit/); [Breakout agent story, 2024](https://www.langchain.com/breakoutagents/replit); [Fireside chat video, 2024](https://www.youtube.com/watch?v=ViykMqljjxU) |
|
||||
| [Rexera](https://www.rexera.com/) | Real Estate (GenAI Native) | Copilot for domain-specific task | [Case study, 2024](https://blog.langchain.dev/customers-rexera/) |
|
||||
| [Tradestack](https://www.tradestack.uk/) | Software & Technology (GenAI Native) | Copilot for domain-specific task | [Case study, 2024](https://blog.langchain.dev/customers-tradestack/) |
|
||||
| [Uber](https://www.uber.com/) | Transportation | Developer productivity; Code generation | [Presentation, 2024](https://dpe.org/sessions/ty-smith-adam-huda/this-year-in-ubers-ai-driven-developer-productivity-revolution/); [Video, 2024](https://www.youtube.com/watch?v=8rkA5vWUE4Y) |
|
||||
| [Unify](https://www.unifygtm.com/) | Software & Technology (GenAI Native) | Copilot for domain-specific task | [Blog post, 2024](https://blog.langchain.dev/unify-launches-agents-for-account-qualification-using-langgraph-and-langsmith/) |
|
||||
| [Vizient](https://www.vizientinc.com/) | Healthcare | Copilot for domain-specific task | [Case study, 2025](https://blog.langchain.dev/p/3d2cd58c-13a5-4df9-bd84-7d54ed0ed82c/) |
|
||||
| [Vizient](https://www.vizientinc.com/) | Healthcare | Copilot for domain-specific task | [Case study, 2025](https://blog.langchain.dev/p/3d2cd58c-13a5-4df9-bd84-7d54ed0ed82c/) |
|
||||
| [Vodafone](https://www.vodafone.com/) | Telecommunications | Code generation; internal search | [Case study, 2025](https://blog.langchain.dev/customers-vodafone/) |
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# How to Deploy to LangGraph Cloud
|
||||
# How to Deploy to Cloud SaaS
|
||||
|
||||
LangGraph Cloud is available within <a href="https://www.langchain.com/langsmith" target="_blank">LangSmith</a>. To deploy a LangGraph Cloud API, navigate to the <a href="https://smith.langchain.com/" target="_blank">LangSmith UI</a>.
|
||||
Before deploying, review the [conceptual guide for the Cloud SaaS](../../concepts/langgraph_cloud.md) deployment option.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
@@ -92,3 +92,28 @@ Starting from the `LangGraph Platform` view...
|
||||
1. Check/uncheck checkbox to `Automatically update deployment on push to branch`.
|
||||
1. Branch creation/deletion and tag creation/deletion events will not trigger an update. Only pushes to an existing branch will trigger an update.
|
||||
1. Pushes in quick succession to a branch will not trigger subsequent updates. In the future, this functionality may be changed/improved.
|
||||
|
||||
## Add or Remove GitHub Repositories
|
||||
|
||||
After installing and authorizing LangChain's `hosted-langserve` GitHub app, repository access for the app can be modified to add new repositories or remove existing repositories. If a new repository is created, it may need to be added explicitly.
|
||||
|
||||
1. From the GitHub profile, navigate to `Settings` > `Applications` > `hosted-langserve` > click `Configure`.
|
||||
1. Under `Repository access`, select `All repositories` or `Only select repositories`. If `Only select repositories` is selected, new repositories must be explicitly added.
|
||||
1. Click `Save`.
|
||||
1. When creating a new deployment, the list of GitHub repositories in the dropdown menu will be updated to reflect the repository access changes.
|
||||
|
||||
## Whitelisting IP Addresses
|
||||
|
||||
All traffic from `LangGraph Platform` deployments created after January 6th 2025 will come through a NAT gateway.
|
||||
This NAT gateway will have several static ip addresses depending on the region you are deploying in. Refer to the table below for the list of IP addresses to whitelist:
|
||||
|
||||
| US | EU |
|
||||
|----------------|----------------|
|
||||
| 35.197.29.146 | 34.13.192.67 |
|
||||
| 34.145.102.123 | 34.147.105.64 |
|
||||
| 34.169.45.153 | 34.90.22.166 |
|
||||
| 34.82.222.17 | 34.147.36.213 |
|
||||
| 35.227.171.135 | 34.32.137.113 |
|
||||
| 34.169.88.30 | 34.91.238.184 |
|
||||
| 34.19.93.202 | 35.204.101.241 |
|
||||
| 34.19.34.50 | 35.204.48.32 |
|
||||
|
||||
@@ -0,0 +1,56 @@
|
||||
# How to Deploy Self-Hosted Control Plane
|
||||
|
||||
Before deploying, review the [conceptual guide for the Self-Hosted Control Plane](../../concepts/langgraph_self_hosted_control_plane.md) deployment option.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
1. You are using Kubernetes.
|
||||
1. You have self-hosted LangSmith deployed.
|
||||
1. Use the [LangGraph CLI](../../concepts/langgraph_cli.md) to [test your application locally](./test_locally.md).
|
||||
1. Use the [LangGraph CLI](../../concepts/langgraph_cli.md) to build a Docker image (i.e. `langgraph build`) and push it to a registry your Kubernetes cluster has access to.
|
||||
1. `KEDA` is installed on your cluster.
|
||||
|
||||
helm repo add kedacore https://kedacore.github.io/charts
|
||||
helm install keda kedacore/keda --namespace keda --create-namespace
|
||||
|
||||
1. Ingress Configuration (recommended)
|
||||
1. Install `Ingress Nginx` to serve as a reverse proxy for your deployment.
|
||||
|
||||
helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx
|
||||
helm repo update
|
||||
helm install ingress-nginx ingress-nginx/ingress-nginx
|
||||
|
||||
1. Provision a root domain that will suffix all domains for your workloads (e.g. `us.langgraph.app`).
|
||||
1. Provision wildcard certificates to terminate TLS for your deployments.
|
||||
1. Note: If this step is skipped, you will need to provision domains/certs for each of your deployments.
|
||||
|
||||
1. You have slack space in your cluster for multiple deployments. `Cluster-Autoscaler` is recommended to automatically provision new nodes.
|
||||
|
||||
## Setup
|
||||
|
||||
1. As part of configuring your Self-Hosted LangSmith instance, you enable the `langgraphPlatform` option. This will provision a few key resources.
|
||||
1. `listener`: This is a service that listens to the [control plane](../../concepts/langgraph_control_plane.md) for changes to your deployments and creates/updates downstream CRDs.
|
||||
1. `LangGraphPlatform CRD`: A CRD for LangGraph Platform deployments. This contains the spec for managing an instance of a LangGraph platform deployment.
|
||||
1. `operator`: This operator handles changes to your LangGraph Platform CRDs.
|
||||
1. `host-backend`: This is the [control plane](../../concepts/langgraph_control_plane.md).
|
||||
1. Two additional images will be used by the chart.
|
||||
|
||||
hostBackendImage:
|
||||
repository: "docker.io/langchain/hosted-langserve-backend"
|
||||
pullPolicy: IfNotPresent
|
||||
tag: "0.9.80"
|
||||
operatorImage:
|
||||
repository: "docker.io/langchain/langgraph-operator"
|
||||
pullPolicy: IfNotPresent
|
||||
tag: "aa9dff4"
|
||||
|
||||
1. In your `values.yaml` file, enable the `langgraphPlatform` option.
|
||||
|
||||
config:
|
||||
langgraphPlatform:
|
||||
enabled: true
|
||||
langgraphPlatformLicenseKey: "YOUR_LANGGRAPH_PLATFORM_LICENSE_KEY"
|
||||
rootDomain: "YOUR_ROOT_DOMAIN"
|
||||
|
||||
1. You can also configure base templates for your agents by overriding the base templates [here](https://github.com/langchain-ai/helm/blob/main/charts/langsmith/values.yaml#L898).
|
||||
1. You create a deployment from the [Control Plane UI](../../concepts/langgraph_control_plane.md#control-plane-ui).
|
||||
@@ -0,0 +1,53 @@
|
||||
# How to Deploy Self-Hosted Data Plane
|
||||
|
||||
Before deploying, review the [conceptual guide for the Self-Hosted Data Plane](../../concepts/langgraph_self_hosted_data_plane.md) deployment option.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
1. Use the [LangGraph CLI](../../concepts/langgraph_cli.md) to [test your application locally](./test_locally.md).
|
||||
1. Use the [LangGraph CLI](../../concepts/langgraph_cli.md) to build a Docker image (i.e. `langgraph build`) and push it to a registry your Kubernetes cluster or Amazon ECS cluster has access to.
|
||||
|
||||
## Kubernetes
|
||||
|
||||
### Prerequisites
|
||||
1. `KEDA` is installed on your cluster.
|
||||
|
||||
helm repo add kedacore https://kedacore.github.io/charts
|
||||
helm install keda kedacore/keda --namespace keda --create-namespace
|
||||
|
||||
1. A valid `Ingress` controller is install on your cluster.
|
||||
1. You have slack space in your cluster for multiple deployments. `Cluster-Autoscaler` is recommended to automatically provision new nodes.
|
||||
|
||||
### Setup
|
||||
|
||||
1. You give us your LangSmith organization ID. We will enable the Self-Hosted Data Plane for your organization.
|
||||
1. We provide you a [Helm chart](https://github.com/langchain-ai/helm/tree/main/charts/langgraph-dataplane) which you run to setup your Kubernetes cluster. This chart contains a few important components.
|
||||
1. `langgraph-listener`: This is a service that listens to LangChain's [control plane](../../concepts/langgraph_control_plane.md) for changes to your deployments and creates/updates downstream CRDs.
|
||||
1. `LangGraphPlatform CRD`: A CRD for LangGraph Platform deployments. This contains the spec for managing an instance of a LangGraph Platform deployment.
|
||||
1. `langgraph-platform-operator`: This operator handles changes to your LangGraph Platform CRDs.
|
||||
1. Configure your `langgraph-dataplane-values.yaml` file.
|
||||
|
||||
config:
|
||||
langgraphPlatformLicenseKey: "" # Your LangGraph Platform license key
|
||||
langsmithApiKey: "" # API Key of your Workspace
|
||||
langsmithWorkspaceId: "" # Workspace ID
|
||||
hostBackendUrl: "https://api.host.langchain.com" # Only override this if on EU
|
||||
smithBackendUrl: "https://api.smith.langchain.com" # Only override this if on EU
|
||||
|
||||
1. Deploy `langgraph-dataplane` Helm chart.
|
||||
|
||||
helm repo add langchain https://langchain-ai.github.io/helm/
|
||||
helm repo update
|
||||
helm upgrade -i langgraph-dataplane langchain/langgraph-dataplane --values langgraph-dataplane-values.yaml
|
||||
|
||||
1. If successful, you will see two services start up in your namespace.
|
||||
|
||||
NAME READY STATUS RESTARTS AGE
|
||||
langgraph-dataplane-listener-7fccd788-wn2dx 0/1 Running 0 9s
|
||||
langgraph-dataplane-redis-0 0/1 ContainerCreating 0 9s
|
||||
|
||||
1. You create a deployment from the [Control Plane UI](../../concepts/langgraph_control_plane.md#control-plane-ui).
|
||||
|
||||
## Amazon ECS
|
||||
|
||||
Coming soon!
|
||||
@@ -17,7 +17,7 @@ This guide explains how to add semantic search to your LangGraph deployment's cr
|
||||
...
|
||||
"store": {
|
||||
"index": {
|
||||
"embed": "openai:text-embeddings-3-small",
|
||||
"embed": "openai:text-embedding-3-small",
|
||||
"dims": 1536,
|
||||
"fields": ["$"]
|
||||
}
|
||||
@@ -27,7 +27,7 @@ This guide explains how to add semantic search to your LangGraph deployment's cr
|
||||
|
||||
This configuration:
|
||||
|
||||
- Uses OpenAI's text-embeddings-3-small model for generating embeddings
|
||||
- Uses OpenAI's text-embedding-3-small model for generating embeddings
|
||||
- Sets the embedding dimension to 1536 (matching the model's output)
|
||||
- Indexes all fields in your stored data (`["$"]` means index everything, or specify specific fields like `["text", "metadata.title"]`)
|
||||
|
||||
|
||||
@@ -36,21 +36,20 @@ Dependencies can optionally be specified in one of the following files: `pyproje
|
||||
The dependencies below will be included in the image, you can also use them in your code, as long as with a compatible version range:
|
||||
|
||||
```
|
||||
langgraph>=0.2.56,<0.3.0
|
||||
langgraph-checkpoint>=2.0.5,<3.0
|
||||
langgraph>=0.2.56,<0.4.0
|
||||
langgraph-sdk>=0.1.53
|
||||
langgraph-checkpoint>=2.0.15,<3.0
|
||||
langchain-core>=0.2.38,<0.4.0
|
||||
langsmith>=0.1.63
|
||||
orjson>=3.9.7
|
||||
httpx>=0.25.0
|
||||
tenacity>=8.0.0
|
||||
uvicorn>=0.26.0
|
||||
sse-starlette>=2.1.0
|
||||
sse-starlette>=2.1.0,<2.2.0
|
||||
uvloop>=0.18.0
|
||||
httptools>=0.5.0
|
||||
jsonschema-rs>=0.16.3
|
||||
croniter>=1.0.1
|
||||
jsonschema-rs>=0.20.0
|
||||
structlog>=23.1.0
|
||||
redis>=5.0.0,<6.0.0
|
||||
```
|
||||
|
||||
Example `requirements.txt` file:
|
||||
|
||||
@@ -36,21 +36,20 @@ Dependencies can optionally be specified in one of the following files: `pyproje
|
||||
The dependencies below will be included in the image, you can also use them in your code, as long as with a compatible version range:
|
||||
|
||||
```
|
||||
langgraph>=0.2.56,<0.3.0
|
||||
langgraph-checkpoint>=2.0.5,<3.0
|
||||
langgraph>=0.2.56,<0.4.0
|
||||
langgraph-sdk>=0.1.53
|
||||
langgraph-checkpoint>=2.0.15,<3.0
|
||||
langchain-core>=0.2.38,<0.4.0
|
||||
langsmith>=0.1.63
|
||||
orjson>=3.9.7
|
||||
httpx>=0.25.0
|
||||
tenacity>=8.0.0
|
||||
uvicorn>=0.26.0
|
||||
sse-starlette>=2.1.0
|
||||
sse-starlette>=2.1.0,<2.2.0
|
||||
uvloop>=0.18.0
|
||||
httptools>=0.5.0
|
||||
jsonschema-rs>=0.16.3
|
||||
croniter>=1.0.1
|
||||
jsonschema-rs>=0.20.0
|
||||
structlog>=23.1.0
|
||||
redis>=5.0.0,<6.0.0
|
||||
```
|
||||
|
||||
Example `pyproject.toml` file:
|
||||
@@ -65,7 +64,7 @@ license = "MIT"
|
||||
readme = "README.md"
|
||||
|
||||
[tool.poetry.dependencies]
|
||||
python = ">=3.9.0,<3.13"
|
||||
python = ">=3.9"
|
||||
langgraph = "^0.2.0"
|
||||
langchain-fireworks = "^0.1.3"
|
||||
|
||||
|
||||
@@ -0,0 +1,110 @@
|
||||
# How to Deploy a Standalone Container
|
||||
|
||||
Before deploying, review the [conceptual guide for the Standalone Container](../../concepts/langgraph_standalone_container.md) deployment option.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
1. Use the [LangGraph CLI](../../concepts/langgraph_cli.md) to [test your application locally](./test_locally.md).
|
||||
1. Use the [LangGraph CLI](../../concepts/langgraph_cli.md) to build a Docker image (i.e. `langgraph build`).
|
||||
1. The following environment variables are needed for a standalone container deployment.
|
||||
1. `REDIS_URI`: Connection details to a Redis instance. Redis will be used as a pub-sub broker to enable streaming real time output from background runs. The value of `REDIS_URI` must be a valid [Redis connection URI](https://redis-py.readthedocs.io/en/stable/connections.html#redis.Redis.from_url).
|
||||
|
||||
!!! Note "Shared Redis Instance"
|
||||
Multiple self-hosted deployments can share the same Redis instance. For example, for `Deployment A`, `REDIS_URI` can be set to `redis://<hostname_1>:<port>/1` and for `Deployment B`, `REDIS_URI` can be set to `redis://<hostname_1>:<port>/2`.
|
||||
|
||||
`1` and `2` are different database numbers within the same instance, but `<hostname_1>` is shared. **The same database number cannot be used for separate deployments**.
|
||||
|
||||
1. `DATABASE_URI`: Postgres connection details. Postgres will be used to store assistants, threads, runs, persist thread state and long term memory, and to manage the state of the background task queue with 'exactly once' semantics. The value of `DATABASE_URI` must be a valid [Postgres connection URI](https://www.postgresql.org/docs/current/libpq-connect.html#LIBPQ-CONNSTRING-URIS).
|
||||
|
||||
!!! Note "Shared Postgres Instance"
|
||||
Multiple self-hosted deployments can share the same Postgres instance. For example, for `Deployment A`, `DATABASE_URI` can be set to `postgres://<user>:<password>@/<database_name_1>?host=<hostname_1>` and for `Deployment B`, `DATABASE_URI` can be set to `postgres://<user>:<password>@/<database_name_2>?host=<hostname_1>`.
|
||||
|
||||
`<database_name_1>` and `database_name_2` are different databases within the same instance, but `<hostname_1>` is shared. **The same database cannot be used for separate deployments**.
|
||||
|
||||
1. `LANGSMITH_API_KEY`: (if using [Lite](../../concepts/langgraph_data_plane.md#lite-vs-enterprise)) LangSmith API key. This will be used to authenticate ONCE at server start up.
|
||||
1. `LANGGRAPH_CLOUD_LICENSE_KEY`: (if using [Enterprise](../../concepts/langgraph_data_plane.md#lite-vs-enterprise)) LangGraph Platform license key. This will be used to authenticate ONCE at server start up.
|
||||
1. `LANGSMITH_ENDPOINT`: To send traces to a [self-hosted LangSmith](https://docs.smith.langchain.com/self_hosting) instance, set `LANGSMITH_ENDPOINT` to the hostname of the self-hosted LangSmith instance.
|
||||
|
||||
## Kubernetes (Helm)
|
||||
|
||||
Use this [Helm chart](https://github.com/langchain-ai/helm/blob/main/charts/langgraph-cloud/README.md) to deploy a LangGraph Server to a Kubernetes cluster.
|
||||
|
||||
## Docker
|
||||
|
||||
Run the following `docker` command:
|
||||
```shell
|
||||
docker run \
|
||||
--env-file .env \
|
||||
-p 8123:8000 \
|
||||
-e REDIS_URI="foo" \
|
||||
-e DATABASE_URI="bar" \
|
||||
-e LANGSMITH_API_KEY="baz" \
|
||||
my-image
|
||||
```
|
||||
|
||||
!!! note
|
||||
|
||||
* You need to replace `my-image` with the name of the image you built in the prerequisite steps (from `langgraph build`)
|
||||
and you should provide appropriate values for `REDIS_URI`, `DATABASE_URI`, and `LANGSMITH_API_KEY`.
|
||||
* If your application requires additional environment variables, you can pass them in a similar way.
|
||||
|
||||
## Docker Compose
|
||||
|
||||
Docker Compose YAML file:
|
||||
```yml
|
||||
volumes:
|
||||
langgraph-data:
|
||||
driver: local
|
||||
services:
|
||||
langgraph-redis:
|
||||
image: redis:6
|
||||
healthcheck:
|
||||
test: redis-cli ping
|
||||
interval: 5s
|
||||
timeout: 1s
|
||||
retries: 5
|
||||
langgraph-postgres:
|
||||
image: postgres:16
|
||||
ports:
|
||||
- "5433:5432"
|
||||
environment:
|
||||
POSTGRES_DB: postgres
|
||||
POSTGRES_USER: postgres
|
||||
POSTGRES_PASSWORD: postgres
|
||||
volumes:
|
||||
- langgraph-data:/var/lib/postgresql/data
|
||||
healthcheck:
|
||||
test: pg_isready -U postgres
|
||||
start_period: 10s
|
||||
timeout: 1s
|
||||
retries: 5
|
||||
interval: 5s
|
||||
langgraph-api:
|
||||
image: ${IMAGE_NAME}
|
||||
ports:
|
||||
- "8123:8000"
|
||||
depends_on:
|
||||
langgraph-redis:
|
||||
condition: service_healthy
|
||||
langgraph-postgres:
|
||||
condition: service_healthy
|
||||
env_file:
|
||||
- .env
|
||||
environment:
|
||||
REDIS_URI: redis://langgraph-redis:6379
|
||||
LANGSMITH_API_KEY: ${LANGSMITH_API_KEY}
|
||||
POSTGRES_URI: postgres://postgres:postgres@langgraph-postgres:5432/postgres?sslmode=disable
|
||||
```
|
||||
|
||||
You can run the command `docker compose up` with this Docker Compose file in the same folder.
|
||||
|
||||
This will launch a LangGraph Server on port `8123` (if you want to change this, you can change this by changing the ports in the `langgraph-api` volume). You can test if the application is healthy by running:
|
||||
|
||||
```shell
|
||||
curl --request GET --url 0.0.0.0:8123/ok
|
||||
```
|
||||
Assuming everything is running correctly, you should see a response like:
|
||||
|
||||
```shell
|
||||
{"ok":true}
|
||||
```
|
||||
@@ -0,0 +1,31 @@
|
||||
# Testing local agents with remote traces
|
||||
|
||||
## Overview
|
||||
|
||||
A common workflow when debugging production-deployed agents is to test the same thread against a local version of the same agent, which may have modifications.
|
||||
|
||||
To support this, LangGraph Studio, in combination with LangSmith, allows you to clone remote threads traced in LangSmith into your locally running agent. This cloned thread can then be used to re-run specific nodes within Studio.
|
||||
|
||||
## Requirements
|
||||
|
||||
!!! info "Prerequisites"
|
||||
|
||||
- langgraph>=0.3.18
|
||||
- langgraph-api>=0.0.32
|
||||
|
||||
- A thread traced in LangSmith.
|
||||
- A locally running agent. See [here](../../how-tos/local-studio.md) for setup instructions.
|
||||
- Note that your local agent must be using the above specified `langgraph` and `langgraph-api` versions.
|
||||
- The nodes present in the remote trace must exist in at least one of the graphs in your local agent.
|
||||
|
||||
## Cloning Thread
|
||||
|
||||
First navigate to the LangSmith trace. Here you should see a button to "Run in Studio".
|
||||
|
||||
{width=1200}
|
||||
|
||||
This will prompt you to enter the url that your locally running agent is accessible at. Once provided, select "Clone thread locally". If you have multiple graphs in your agent, you will also be prompted to select a graph to clone this thread under.
|
||||
|
||||
Once selected, a will a new thread in your local agent will be created and the thread history will be reconstruced to reflect the original trace.
|
||||
|
||||
Alternatively, if your trace originates from an agent deployed on LangGraph Platform, you can "View original thread" to open Studio with the actual deployed thread.
|
||||
@@ -0,0 +1,366 @@
|
||||
# How to implement Generative User Interfaces with LangGraph
|
||||
|
||||
!!! info "Prerequisites"
|
||||
|
||||
- [LangGraph Platform](../../concepts/langgraph_platform.md)
|
||||
- [LangGraph Server](../../concepts/langgraph_server.md)
|
||||
- [`useStream()` React Hook](./use_stream_react.md)
|
||||
|
||||
Generative user interfaces (Generative UI) allows agents to go beyond text and generate rich user interfaces. This enables creating more interactive and context-aware applications where the UI adapts based on the conversation flow and AI responses.
|
||||
|
||||

|
||||
|
||||
LangGraph Platform supports colocating your React components with your graph code. This allows you to focus on building specific UI components for your graph while easily plugging into existing chat interfaces such as [Agent Chat](https://agentchat.vercel.app) and loading the code only when actually needed.
|
||||
|
||||
## Tutorial
|
||||
|
||||
### 1. Define and configure UI components
|
||||
|
||||
First, create your first UI component. For each component you need to provide an unique identifier that will be used to reference the component in your graph code.
|
||||
|
||||
```tsx title="src/agent/ui.tsx"
|
||||
const WeatherComponent = (props: { city: string }) => {
|
||||
return <div>Weather for {props.city}</div>;
|
||||
};
|
||||
|
||||
export default {
|
||||
weather: WeatherComponent,
|
||||
};
|
||||
```
|
||||
|
||||
Next, define your UI components in your `langgraph.json` configuration:
|
||||
|
||||
```json
|
||||
{
|
||||
"node_version": "20",
|
||||
"graphs": {
|
||||
"agent": "./src/agent/index.ts:graph"
|
||||
},
|
||||
"ui": {
|
||||
"agent": "./src/agent/ui.tsx"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
The `ui` section points to the UI components that will be used by graphs. By default, we recommend using the same key as the graph name, but you can split out the components however you like, see [Customise the namespace of UI components](#customise-the-namespace-of-ui-components) for more details.
|
||||
|
||||
LangGraph Platform will automatically bundle your UI components code and styles and serve them as external assets that can be loaded by the `LoadExternalComponent` component. Some dependencies such as `react` and `react-dom` will be automatically excluded from the bundle.
|
||||
|
||||
CSS and Tailwind 4.x is also supported out of the box, so you can freely use Tailwind classes as well as `shadcn/ui` in your UI components.
|
||||
|
||||
=== "`src/agent/ui.tsx`"
|
||||
|
||||
```tsx
|
||||
import "./styles.css";
|
||||
|
||||
const WeatherComponent = (props: { city: string }) => {
|
||||
return <div className="bg-red-500">Weather for {props.city}</div>;
|
||||
};
|
||||
|
||||
export default {
|
||||
weather: WeatherComponent,
|
||||
};
|
||||
```
|
||||
|
||||
=== "`src/agent/styles.css`"
|
||||
|
||||
```css
|
||||
@import "tailwindcss";
|
||||
```
|
||||
|
||||
### 2. Send the UI components in your graph
|
||||
|
||||
=== "Python"
|
||||
|
||||
```python title="src/agent.py"
|
||||
import uuid
|
||||
from typing import Annotated, Sequence, TypedDict
|
||||
|
||||
from langchain_core.messages import AIMessage, BaseMessage
|
||||
from langchain_openai import ChatOpenAI
|
||||
from langgraph.graph import StateGraph
|
||||
from langgraph.graph.message import add_messages
|
||||
from langgraph.graph.ui import AnyUIMessage, ui_message_reducer, push_ui_message
|
||||
|
||||
|
||||
class AgentState(TypedDict): # noqa: D101
|
||||
messages: Annotated[Sequence[BaseMessage], add_messages]
|
||||
ui: Annotated[Sequence[AnyUIMessage], ui_message_reducer]
|
||||
|
||||
|
||||
async def weather(state: AgentState):
|
||||
class WeatherOutput(TypedDict):
|
||||
city: str
|
||||
|
||||
weather: WeatherOutput = (
|
||||
await ChatOpenAI(model="gpt-4o-mini")
|
||||
.with_structured_output(WeatherOutput)
|
||||
.with_config({"tags": ["nostream"]})
|
||||
.ainvoke(state["messages"])
|
||||
)
|
||||
|
||||
message = AIMessage(
|
||||
id=str(uuid.uuid4()),
|
||||
content=f"Here's the weather for {weather['city']}",
|
||||
)
|
||||
|
||||
# Emit UI elements associated with the message
|
||||
push_ui_message("weather", weather, message=message)
|
||||
return {"messages": [message]}
|
||||
|
||||
|
||||
workflow = StateGraph(AgentState)
|
||||
workflow.add_node(weather)
|
||||
workflow.add_edge("__start__", "weather")
|
||||
graph = workflow.compile()
|
||||
```
|
||||
|
||||
=== "JS"
|
||||
|
||||
Use the `typedUi` utility to emit UI elements from your agent nodes:
|
||||
|
||||
```typescript title="src/agent/index.ts"
|
||||
import {
|
||||
typedUi,
|
||||
uiMessageReducer,
|
||||
} from "@langchain/langgraph-sdk/react-ui/server";
|
||||
|
||||
import { ChatOpenAI } from "@langchain/openai";
|
||||
import { v4 as uuidv4 } from "uuid";
|
||||
import { z } from "zod";
|
||||
|
||||
import type ComponentMap from "./ui.js";
|
||||
|
||||
import {
|
||||
Annotation,
|
||||
MessagesAnnotation,
|
||||
StateGraph,
|
||||
type LangGraphRunnableConfig,
|
||||
} from "@langchain/langgraph";
|
||||
|
||||
const AgentState = Annotation.Root({
|
||||
...MessagesAnnotation.spec,
|
||||
ui: Annotation({ reducer: uiMessageReducer, default: () => [] }),
|
||||
});
|
||||
|
||||
export const graph = new StateGraph(AgentState)
|
||||
.addNode("weather", async (state, config) => {
|
||||
// Provide the type of the component map to ensure
|
||||
// type safety of `ui.push()` calls as well as
|
||||
// pushing the messages to the `ui` and sending a custom event as well.
|
||||
const ui = typedUi<typeof ComponentMap>(config);
|
||||
|
||||
const weather = await new ChatOpenAI({ model: "gpt-4o-mini" })
|
||||
.withStructuredOutput(z.object({ city: z.string() }))
|
||||
.withConfig({ tags: ["nostream"] })
|
||||
.invoke(state.messages);
|
||||
|
||||
const response = {
|
||||
id: uuidv4(),
|
||||
type: "ai",
|
||||
content: `Here's the weather for ${weather.city}`,
|
||||
};
|
||||
|
||||
// Emit UI elements associated with the AI message
|
||||
ui.push({ name: "weather", props: weather }, { message: response });
|
||||
|
||||
return { messages: [response] };
|
||||
})
|
||||
.addEdge("__start__", "weather")
|
||||
.compile();
|
||||
```
|
||||
|
||||
### 3. Handle UI elements in your React application
|
||||
|
||||
On the client side, you can use `useStream()` and `LoadExternalComponent` to display the UI elements.
|
||||
|
||||
```tsx title="src/app/page.tsx"
|
||||
"use client";
|
||||
|
||||
import { useStream } from "@langchain/langgraph-sdk/react";
|
||||
import { LoadExternalComponent } from "@langchain/langgraph-sdk/react-ui";
|
||||
|
||||
export default function Page() {
|
||||
const { thread, values } = useStream({
|
||||
apiUrl: "http://localhost:2024",
|
||||
assistantId: "agent",
|
||||
});
|
||||
|
||||
return (
|
||||
<div>
|
||||
{thread.messages.map((message) => (
|
||||
<div key={message.id}>
|
||||
{message.content}
|
||||
{values.ui
|
||||
?.filter((ui) => ui.metadata?.message_id === message.id)
|
||||
.map((ui) => (
|
||||
<LoadExternalComponent key={ui.id} stream={thread} message={ui} />
|
||||
))}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
Behind the scenes, `LoadExternalComponent` will fetch the JS and CSS for the UI components from LangGraph Platform and render them in a shadow DOM, thus ensuring style isolation from the rest of your application.
|
||||
|
||||
## How-to guides
|
||||
|
||||
### Show loading UI when components are loading
|
||||
|
||||
You can provide a fallback UI to be rendered when the components are loading.
|
||||
|
||||
```tsx
|
||||
<LoadExternalComponent
|
||||
stream={thread}
|
||||
message={ui}
|
||||
fallback={<div>Loading...</div>}
|
||||
/>
|
||||
```
|
||||
|
||||
### Provide custom components on the client side
|
||||
|
||||
If you already have the components loaded in your client application, you can provide a map of such components to be rendered directly without fetching the UI code from LangGraph Platform.
|
||||
|
||||
```tsx
|
||||
const clientComponents = {
|
||||
weather: WeatherComponent,
|
||||
};
|
||||
|
||||
<LoadExternalComponent
|
||||
stream={thread}
|
||||
message={ui}
|
||||
components={clientComponents}
|
||||
/>;
|
||||
```
|
||||
|
||||
### Customise the namespace of UI components.
|
||||
|
||||
By default `LoadExternalComponent` will use the `assistantId` from `useStream()` hook to fetch the code for UI components. You can customise this by providing a `namespace` prop to the `LoadExternalComponent` component.
|
||||
|
||||
=== "`src/app/page.tsx`"
|
||||
|
||||
```tsx
|
||||
<LoadExternalComponent
|
||||
stream={thread}
|
||||
message={ui}
|
||||
namespace="custom-namespace"
|
||||
/>
|
||||
```
|
||||
|
||||
=== "`langgraph.json`"
|
||||
|
||||
```json
|
||||
{
|
||||
"ui": {
|
||||
"custom-namespace": "./src/agent/ui.tsx"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Access and interact with the thread state from the UI component
|
||||
|
||||
You can access the thread state inside the UI component by using the `useStreamContext` hook.
|
||||
|
||||
```tsx
|
||||
import { useStreamContext } from "@langchain/langgraph-sdk/react-ui";
|
||||
|
||||
const WeatherComponent = (props: { city: string }) => {
|
||||
const { thread, submit } = useStreamContext();
|
||||
return (
|
||||
<>
|
||||
<div>Weather for {props.city}</div>
|
||||
|
||||
<button
|
||||
onClick={() => {
|
||||
const newMessage = {
|
||||
type: "human",
|
||||
content: `What's the weather in ${props.city}?`,
|
||||
};
|
||||
|
||||
submit({ messages: [newMessage] });
|
||||
}}
|
||||
>
|
||||
Retry
|
||||
</button>
|
||||
</>
|
||||
);
|
||||
};
|
||||
```
|
||||
|
||||
### Pass additional context to the client components
|
||||
|
||||
You can pass additional context to the client components by providing a `meta` prop to the `LoadExternalComponent` component.
|
||||
|
||||
```tsx
|
||||
<LoadExternalComponent stream={thread} message={ui} meta={{ userId: "123" }} />
|
||||
```
|
||||
|
||||
Then, you can access the `meta` prop in the UI component by using the `useStreamContext` hook.
|
||||
|
||||
```tsx
|
||||
import { useStreamContext } from "@langchain/langgraph-sdk/react-ui";
|
||||
|
||||
const WeatherComponent = (props: { city: string }) => {
|
||||
const { meta } = useStreamContext<
|
||||
{ city: string },
|
||||
{ MetaType: { userId?: string } }
|
||||
>();
|
||||
|
||||
return (
|
||||
<div>
|
||||
Weather for {props.city} (user: {meta?.userId})
|
||||
</div>
|
||||
);
|
||||
};
|
||||
```
|
||||
|
||||
### Streaming UI updates before the node execution is finished
|
||||
|
||||
You can stream UI updates before the node execution is finished by using the `onCustomEvent` callback of the `useStream()` hook.
|
||||
|
||||
```tsx
|
||||
import { uiMessageReducer } from "@langchain/langgraph-sdk/react-ui";
|
||||
|
||||
const { thread, submit } = useStream({
|
||||
apiUrl: "http://localhost:2024",
|
||||
assistantId: "agent",
|
||||
onCustomEvent: (event, options) => {
|
||||
options.mutate((prev) => {
|
||||
const ui = uiMessageReducer(prev.ui ?? [], event);
|
||||
return { ...prev, ui };
|
||||
});
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
### Remove UI messages from state
|
||||
|
||||
Similar to how messages can be removed from the state by appending a RemoveMessage you can remove an UI message from the state by calling `remove_ui_message` / `ui.delete` with the ID of the UI message.
|
||||
|
||||
=== "Python"
|
||||
|
||||
```python
|
||||
from langgraph.graph.ui import push_ui_message, delete_ui_message
|
||||
|
||||
# push message
|
||||
message = push_ui_message("weather", {"city": "London"})
|
||||
|
||||
# remove said message
|
||||
delete_ui_message(message["id"])
|
||||
```
|
||||
|
||||
=== "JS"
|
||||
|
||||
```tsx
|
||||
// push message
|
||||
const message = ui.push({ name: "weather", props: { city: "London" } });
|
||||
|
||||
// remove said message
|
||||
ui.delete(message.id);
|
||||
```
|
||||
|
||||
## Learn more
|
||||
|
||||
- [JS/TS SDK Reference](../reference/sdk/js_ts_sdk_ref.md)
|
||||
@@ -63,7 +63,7 @@ Now, let's invoke our graph by interrupting before `ask_human` node:
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "Use the search tool to ask the user where they are, then look up the weather there",
|
||||
"content": "Ask the user where they are, then look up the weather there",
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -85,8 +85,7 @@ Now, let's invoke our graph by interrupting before `ask_human` node:
|
||||
messages: [
|
||||
{
|
||||
role: "human",
|
||||
content: "Use the search tool to ask the user where they are, then look up the weather there"
|
||||
}
|
||||
content: "Ask the user where they are, then look up the weather there" }
|
||||
]
|
||||
};
|
||||
|
||||
@@ -115,7 +114,7 @@ Now, let's invoke our graph by interrupting before `ask_human` node:
|
||||
--header 'Content-Type: application/json' \
|
||||
--data "{
|
||||
\"assistant_id\": \"agent\",
|
||||
\"input\": {\"messages\": [{\"role\": \"human\", \"content\": \"Use the search tool to ask the user where they are, then look up the weather there\"}]},
|
||||
\"input\": {\"messages\": [{\"role\": \"human\", \"content\": \"Ask the user where they are, then look up the weather there\"}]},
|
||||
\"interrupt_before\": [\"ask_human\"],
|
||||
\"stream_mode\": [
|
||||
\"updates\"
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 115 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 59 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 39 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 93 KiB |
@@ -1,6 +1,133 @@
|
||||
# Prompt Engineering in LangGraph Studio
|
||||
|
||||
In LangGraph Studio you can iterate on the prompts used within your graph by utilizing the LangSmith Playground. To do so:
|
||||
## Overview
|
||||
|
||||
A central aspect of agent development is prompt engineering. LangGraph Studio makes it easy to iterate on the prompts used within your graph directly within the UI.
|
||||
|
||||
## Setup
|
||||
|
||||
The first step is to define your [configuration](https://langchain-ai.github.io/langgraph/how-tos/configuration/) such that LangGraph Studio is aware of the prompts you want to iterate on and which nodes they are associated with.
|
||||
|
||||
### Reference
|
||||
|
||||
When defining your configuration, you can use special metadata keys to instruct LangGraph Studio how to handle different fields. Here's a reference for the available configuration options:
|
||||
|
||||
#### `langgraph_nodes`
|
||||
|
||||
- **Description**: Specifies which graph nodes a configuration field is associated with.
|
||||
- **Value Type**: Array of strings, where each string is the name of a node in your graph.
|
||||
- **Usage Context**: Include in the `json_schema_extra` dictionary for Pydantic models or the `metadata["json_schema_extra"]` dictionary for dataclasses.
|
||||
- **Required**: No, but necessary if you want a field to be editable for specific nodes in the UI.
|
||||
- **Example**:
|
||||
```python
|
||||
system_prompt: str = Field(
|
||||
default="You are a helpful AI assistant.",
|
||||
json_schema_extra={"langgraph_nodes": ["call_model", "other_node"]},
|
||||
)
|
||||
```
|
||||
|
||||
#### `langgraph_type`
|
||||
|
||||
- **Description**: Specifies the type of configuration field, which determines how it's handled in the UI.
|
||||
- **Value Type**: String
|
||||
- **Supported Values**:
|
||||
- `"prompt"`: Indicates the field contains prompt text that should be treated specially in the UI.
|
||||
- **Usage Context**: Include in the `json_schema_extra` dictionary for Pydantic models or the `metadata["json_schema_extra"]` dictionary for dataclasses.
|
||||
- **Required**: No, but helpful for prompt fields to enable special handling.
|
||||
- **Example**:
|
||||
```python
|
||||
system_prompt: str = Field(
|
||||
default="You are a helpful AI assistant.",
|
||||
json_schema_extra={
|
||||
"langgraph_nodes": ["call_model"],
|
||||
"langgraph_type": "prompt",
|
||||
},
|
||||
)
|
||||
```
|
||||
|
||||
### Example
|
||||
|
||||
For example, if you have a node called `call_model` whose system prompt you want to iterate on, you can define a configuration like the following.
|
||||
|
||||
```python
|
||||
## Using Pydantic
|
||||
from pydantic import BaseModel, Field
|
||||
from typing import Annotated, Literal
|
||||
|
||||
class Configuration(BaseModel):
|
||||
"""The configuration for the agent."""
|
||||
|
||||
system_prompt: str = Field(
|
||||
default="You are a helpful AI assistant.",
|
||||
description="The system prompt to use for the agent's interactions. "
|
||||
"This prompt sets the context and behavior for the agent.",
|
||||
json_schema_extra={
|
||||
"langgraph_nodes": ["call_model"],
|
||||
"langgraph_type": "prompt",
|
||||
},
|
||||
)
|
||||
|
||||
model: Annotated[
|
||||
Literal[
|
||||
"anthropic/claude-3-7-sonnet-latest",
|
||||
"anthropic/claude-3-5-haiku-latest",
|
||||
"openai/o1",
|
||||
"openai/gpt-4o-mini",
|
||||
"openai/o1-mini",
|
||||
"openai/o3-mini",
|
||||
],
|
||||
{"__template_metadata__": {"kind": "llm"}},
|
||||
] = Field(
|
||||
default="openai/gpt-4o-mini",
|
||||
description="The name of the language model to use for the agent's main interactions. "
|
||||
"Should be in the form: provider/model-name.",
|
||||
json_schema_extra={"langgraph_nodes": ["call_model"]},
|
||||
)
|
||||
|
||||
## Using Dataclasses
|
||||
from dataclasses import dataclass, field
|
||||
|
||||
@dataclass(kw_only=True)
|
||||
class Configuration:
|
||||
"""The configuration for the agent."""
|
||||
|
||||
system_prompt: str = field(
|
||||
default="You are a helpful AI assistant.",
|
||||
metadata={
|
||||
"description": "The system prompt to use for the agent's interactions. "
|
||||
"This prompt sets the context and behavior for the agent.",
|
||||
"json_schema_extra": {"langgraph_nodes": ["call_model"]},
|
||||
},
|
||||
)
|
||||
|
||||
model: Annotated[str, {"__template_metadata__": {"kind": "llm"}}] = field(
|
||||
default="anthropic/claude-3-5-sonnet-20240620",
|
||||
metadata={
|
||||
"description": "The name of the language model to use for the agent's main interactions. "
|
||||
"Should be in the form: provider/model-name.",
|
||||
"json_schema_extra": {"langgraph_nodes": ["call_model"]},
|
||||
},
|
||||
)
|
||||
|
||||
```
|
||||
|
||||
## Iterating on prompts
|
||||
|
||||
### Node Configuration
|
||||
|
||||
With this set up, running your graph and viewing in LangGraph Studio will result in the graph rendering like such.
|
||||
|
||||
**Note the configuration icon in the top right corner of the `call_model` node**:
|
||||
|
||||
{width=1200}
|
||||
|
||||
Clicking this icon will open a modal where you can edit the configuration for all of the fields associated with the `call_model` node. From here, you can save your changes and apply them to the graph. Note that these values reflect the currently active assistant, and saving will update the assistant with the new values.
|
||||
|
||||
{width=1200}
|
||||
|
||||
### Playground
|
||||
|
||||
LangGraph Studio also supports prompt engineering through an integration with the LangSmith Playground. To do so:
|
||||
|
||||
1. Open an existing thread or create a new one.
|
||||
2. Within the thread log, any nodes that have made an LLM call will have a "View LLM Runs" button. Clicking this will open a popover with the LLM runs for that node.
|
||||
@@ -8,8 +135,6 @@ In LangGraph Studio you can iterate on the prompts used within your graph by uti
|
||||
|
||||
{width=1200}
|
||||
|
||||
|
||||
|
||||
From here you can edit the prompt, test different model configurations and re-run just this LLM call without having to re-run the entire graph. When you are happy with your changes, you can copy the updated prompt back into your graph.
|
||||
|
||||
For more information on how to use the LangSmith Playground, see the [LangSmith Playground documentation](https://docs.smith.langchain.com/prompt_engineering/how_to_guides#playground).
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,10 +1,10 @@
|
||||
# Test Cloud Deployment
|
||||
# Test LangGraph Platform Deployment
|
||||
|
||||
The LangGraph Studio UI connects directly to LangGraph Cloud deployments.
|
||||
The LangGraph Studio UI connects directly to LangGraph Platform deployments.
|
||||
|
||||
Starting from the <a href="https://smith.langchain.com/" target="_blank">LangSmith UI</a>...
|
||||
|
||||
1. In the left-hand navigation panel, select `LangGraph Cloud`. The `LangGraph Cloud` view contains a list of existing LangGraph Cloud deployments.
|
||||
1. In the left-hand navigation panel, select `LangGraph Platform`. The `LangGraph Platform` view contains a list of existing LangGraph Platform deployments.
|
||||
1. Select an existing deployment to test with LangGraph Studio.
|
||||
1. In the top-right corner, select `Open LangGraph Studio`.
|
||||
1. [Invoke an assistant](./invoke_studio.md) or [view an existing thread](./threads_studio.md).
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
# How to integrate LangGraph into your React application
|
||||
|
||||
!!! info "Prerequisites"
|
||||
- [LangGraph Platform](../../concepts/langgraph_platform.md)
|
||||
!!! info "Prerequisites"
|
||||
|
||||
- [LangGraph Platform](../../concepts/langgraph_platform.md)
|
||||
- [LangGraph Server](../../concepts/langgraph_server.md)
|
||||
|
||||
The `useStream()` React hook provides a seamless way to integrate LangGraph into your React applications. It handles all the complexities of streaming, state management, and branching logic, letting you focus on building great chat experiences.
|
||||
@@ -9,19 +10,18 @@ The `useStream()` React hook provides a seamless way to integrate LangGraph into
|
||||
Key features:
|
||||
|
||||
- Messages streaming: Handle a stream of message chunks to form a complete message
|
||||
- Automatic state management for messages, loading states, and errors
|
||||
- Automatic state management for messages, interrupts, loading states, and errors
|
||||
- Conversation branching: Create alternate conversation paths from any point in the chat history
|
||||
- UI-agnostic design - bring your own components and styling
|
||||
- UI-agnostic design: bring your own components and styling
|
||||
|
||||
Let's explore how to use `useStream()` in your React application.
|
||||
|
||||
The `useStream()` provides a solid foundation for creating bespoke chat experiences. For pre-built chat components and interfaces, we recommend checking out [CopilotKit](https://docs.copilotkit.ai/coagents/quickstart/langgraph) and [assistant-ui](https://www.assistant-ui.com/docs/runtimes/langgraph).
|
||||
|
||||
The `useStream()` provides a solid foundation for creating bespoke chat experiences. For pre-built chat components and interfaces, we also recommend checking out [CopilotKit](https://docs.copilotkit.ai/coagents/quickstart/langgraph) and [assistant-ui](https://www.assistant-ui.com/docs/runtimes/langgraph).
|
||||
|
||||
## Installation
|
||||
|
||||
```bash
|
||||
npm install @langchain/langgraph-sdk @langchain/langchain-core react
|
||||
npm install @langchain/langgraph-sdk @langchain/core
|
||||
```
|
||||
|
||||
## Example
|
||||
@@ -65,9 +65,7 @@ export default function App() {
|
||||
Stop
|
||||
</button>
|
||||
) : (
|
||||
<button key="submit" type="submit">
|
||||
Send
|
||||
</button>
|
||||
<button keytype="submit">Send</button>
|
||||
)}
|
||||
</form>
|
||||
</div>
|
||||
@@ -81,6 +79,7 @@ The `useStream()` hook takes care of all the complex state management behind the
|
||||
|
||||
- Thread state management
|
||||
- Loading and error states
|
||||
- Interrupts
|
||||
- Message handling and updates
|
||||
- Branching support
|
||||
|
||||
@@ -134,9 +133,9 @@ We recommend storing the `threadId` in your URL's query parameters to let users
|
||||
|
||||
### Messages Handling
|
||||
|
||||
To enable messages handling, you need to pass the `messagesKey` option to the `useStream()` hook.
|
||||
The `useStream()` hook will keep track of the message chunks received from the server and concatenate them together to form a complete message. The completed message chunks can be retrieved via the `messages` property.
|
||||
|
||||
When enabled, the `useStream()` hook will keep track of the message chunks received from the server and concatenate them together to form a complete message. The completed message chunks can be retrieved via the `messages` property.
|
||||
By default, the `messagesKey` is set to `messages`, where it will append the new messages chunks to `values["messages"]`. If you store messages in a different key, you can change the value of `messagesKey`.
|
||||
|
||||
```tsx
|
||||
import type { Message } from "@langchain/langgraph-sdk";
|
||||
@@ -159,9 +158,45 @@ export default function HomePage() {
|
||||
}
|
||||
```
|
||||
|
||||
### Branching Support
|
||||
Under the hood, the `useStream()` hook will use the `streamMode: "messages-key"` to receive a stream of messages (i.e. individual LLM tokens) from any LangChain chat model invocations inside your graph nodes. Learn more about messages streaming in the [How to stream messages from your graph](./stream_messages.md) guide.
|
||||
|
||||
To enable branching, you need to enable messages handling. Pass the `messagesKey` option to the `useStream()` hook. For each message, you can use `getMessagesMetadata()` to get the first checkpoint from which the message has been first seen. You can then create a new run from the checkpoint preceding the first seen checkpoint to create a new branch in a thread.
|
||||
### Interrupts
|
||||
|
||||
The `useStream()` hook exposes the `interrupt` property, which will be filled with the last interrupt from the thread. You can use interrupts to:
|
||||
|
||||
- Render a confirmation UI before executing a node
|
||||
- Wait for human input, allowing agent to ask the user with clarifying questions
|
||||
|
||||
Learn more about interrupts in the [How to handle interrupts](../../how-tos/human_in_the_loop/wait-user-input.ipynb) guide.
|
||||
|
||||
```tsx
|
||||
const thread = useStream<{ messages: Message[] }, { InterruptType: string }>({
|
||||
apiUrl: "http://localhost:2024",
|
||||
assistantId: "agent",
|
||||
messagesKey: "messages",
|
||||
});
|
||||
|
||||
if (thread.interrupt) {
|
||||
return (
|
||||
<div>
|
||||
Interrupted! {thread.interrupt.value}
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => {
|
||||
// `resume` can be any value that the agent accepts
|
||||
thread.submit(undefined, { command: { resume: true } });
|
||||
}}
|
||||
>
|
||||
Resume
|
||||
</button>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
### Branching
|
||||
|
||||
For each message, you can use `getMessagesMetadata()` to get the first checkpoint from which the message has been first seen. You can then create a new run from the checkpoint preceding the first seen checkpoint to create a new branch in a thread.
|
||||
|
||||
A branch can be created in following ways:
|
||||
|
||||
@@ -169,23 +204,12 @@ A branch can be created in following ways:
|
||||
2. Request a regeneration of a previous assistant message.
|
||||
|
||||
```tsx
|
||||
/* eslint-disable @typescript-eslint/no-floating-promises */
|
||||
"use client";
|
||||
|
||||
import type { Message } from "@langchain/langgraph-sdk";
|
||||
import { useStream } from "@langchain/langgraph-sdk/react";
|
||||
import {
|
||||
Annotation,
|
||||
MessagesAnnotation,
|
||||
type StateType,
|
||||
type UpdateType,
|
||||
} from "@langchain/langgraph/web";
|
||||
import { useState } from "react";
|
||||
|
||||
const AgentState = Annotation.Root({
|
||||
...MessagesAnnotation.spec,
|
||||
});
|
||||
|
||||
function BranchSwitcher({
|
||||
branch,
|
||||
branchOptions,
|
||||
@@ -263,10 +287,7 @@ function EditMessage({
|
||||
}
|
||||
|
||||
export default function App() {
|
||||
const thread = useStream<
|
||||
StateType<typeof AgentState.spec>,
|
||||
UpdateType<typeof AgentState.spec>
|
||||
>({
|
||||
const thread = useStream({
|
||||
apiUrl: "http://localhost:2024",
|
||||
assistantId: "agent",
|
||||
messagesKey: "messages",
|
||||
@@ -344,13 +365,38 @@ export default function App() {
|
||||
}
|
||||
```
|
||||
|
||||
For advanced use cases you can use the `experimental_branchTree` property to get the tree representation of the thread, which can be used to render branching controls for non-message based graphs.
|
||||
|
||||
### Optimistic Updates
|
||||
|
||||
You can optimistically update the client state before performing a network request to the agent, allowing you to provide immediate feedback to the user, such as showing the user message immediately before the agent has seen the request.
|
||||
|
||||
```tsx
|
||||
const stream = useStream({
|
||||
apiUrl: "http://localhost:2024",
|
||||
assistantId: "agent",
|
||||
messagesKey: "messages",
|
||||
});
|
||||
|
||||
const handleSubmit = (text: string) => {
|
||||
const newMessage = { type: "human" as const, content: text };
|
||||
|
||||
stream.submit(
|
||||
{ messages: [newMessage] },
|
||||
{
|
||||
optimisticValues(prev) {
|
||||
const prevMessages = prev.messages ?? [];
|
||||
const newMessages = [...prevMessages, newMessage];
|
||||
return { ...prev, messages: newMessages };
|
||||
},
|
||||
}
|
||||
);
|
||||
};
|
||||
```
|
||||
|
||||
### TypeScript
|
||||
|
||||
The `useStream()` hook is fully typed to help catch errors early and provide better IDE support. You can specify types for:
|
||||
|
||||
- State shape
|
||||
- Update format
|
||||
- Custom events
|
||||
The `useStream()` hook is friendly for apps written in TypeScript and you can specify types for the state to get better type safety and IDE support.
|
||||
|
||||
```tsx
|
||||
// Define your types
|
||||
@@ -359,25 +405,46 @@ type State = {
|
||||
context?: Record<string, unknown>;
|
||||
};
|
||||
|
||||
type Update = {
|
||||
messages: Message[] | Message;
|
||||
context?: Record<string, unknown>;
|
||||
};
|
||||
|
||||
type CustomEvent = {
|
||||
type: "progress" | "debug";
|
||||
payload: unknown;
|
||||
};
|
||||
|
||||
// Use them with the hook
|
||||
const thread = useStream<State, Update, CustomEvent>({
|
||||
const thread = useStream<State>({
|
||||
apiUrl: "http://localhost:2024",
|
||||
assistantId: "agent",
|
||||
messagesKey: "messages",
|
||||
});
|
||||
```
|
||||
|
||||
If you're using LangGraph.js, you can reuse your graph's annotation types:
|
||||
You can also optionally specify types for different scenarios, such as:
|
||||
|
||||
- `ConfigurableType`: Type for the `config.configurable` property (default: `Record<string, unknown>`)
|
||||
- `InterruptType`: Type for the interrupt value - i.e. contents of `interrupt(...)` function (default: `unknown`)
|
||||
- `CustomEventType`: Type for the custom events (default: `unknown`)
|
||||
- `UpdateType`: Type for the submit function (default: `Partial<State>`)
|
||||
|
||||
```tsx
|
||||
const thread = useStream<
|
||||
State,
|
||||
{
|
||||
UpdateType: {
|
||||
messages: Message[] | Message;
|
||||
context?: Record<string, unknown>;
|
||||
};
|
||||
InterruptType: string;
|
||||
CustomEventType: {
|
||||
type: "progress" | "debug";
|
||||
payload: unknown;
|
||||
};
|
||||
ConfigurableType: {
|
||||
model: string;
|
||||
};
|
||||
}
|
||||
>({
|
||||
apiUrl: "http://localhost:2024",
|
||||
assistantId: "agent",
|
||||
messagesKey: "messages",
|
||||
});
|
||||
```
|
||||
|
||||
If you're using LangGraph.js, you can also reuse your graph's annotation types. However, make sure to only import the types of the annotation schema in order to avoid importing the entire LangGraph.js runtime (i.e. via `import type { ... }` directive).
|
||||
|
||||
```tsx
|
||||
import {
|
||||
@@ -394,7 +461,7 @@ const AgentState = Annotation.Root({
|
||||
|
||||
const thread = useStream<
|
||||
StateType<typeof AgentState.spec>,
|
||||
UpdateType<typeof AgentState.spec>
|
||||
{ UpdateType: UpdateType<typeof AgentState.spec> }
|
||||
>({
|
||||
apiUrl: "http://localhost:2024",
|
||||
assistantId: "agent",
|
||||
@@ -410,7 +477,7 @@ The `useStream()` hook provides several callback options to help you respond to
|
||||
- `onFinish`: Called when the stream is finished.
|
||||
- `onUpdateEvent`: Called when an update event is received.
|
||||
- `onCustomEvent`: Called when a custom event is received. See [Custom events](../../concepts/streaming.md#custom) to learn how to stream custom events.
|
||||
- `onMetadataEvent`: Called when a metadata event is received.
|
||||
- `onMetadataEvent`: Called when a metadata event is received, which contains the Run ID and Thread ID.
|
||||
|
||||
## Learn More
|
||||
|
||||
|
||||
+119
-114
@@ -1,142 +1,147 @@
|
||||
# Use Webhooks
|
||||
# Using Webhooks
|
||||
|
||||
You may wish to use webhooks in your client, especially when using async streams in case you want to update something in your service once the API call to LangGraph Cloud has finished running. To do so, you will need to expose an endpoint that can accept POST requests, and then pass it to your API request in the "webhook" parameter.
|
||||
When working with LangGraph Cloud, you may want to use webhooks to receive updates after an API call completes. Webhooks are useful for triggering actions in your service once a run has finished processing. To implement this, you need to expose an endpoint that can accept `POST` requests and pass this endpoint as a `webhook` parameter in your API request.
|
||||
|
||||
Currently, the SDK has not exposed this endpoint but you can access it through curl commands as follows.
|
||||
Currently, the SDK does not provide built-in support for defining webhook endpoints, but you can specify them manually using API requests.
|
||||
|
||||
The following endpoints accept `webhook` as a parameter:
|
||||
## Supported Endpoints
|
||||
|
||||
- Create Run -> POST /thread/{thread_id}/runs
|
||||
- Create Thread Cron -> POST /thread/{thread_id}/runs/crons
|
||||
- Stream Run -> POST /thread/{thread_id}/runs/stream
|
||||
- Wait Run -> POST /thread/{thread_id}/runs/wait
|
||||
- Create Cron -> POST /runs/crons
|
||||
- Stream Run Stateless -> POST /runs/stream
|
||||
- Wait Run Stateless -> POST /runs/wait
|
||||
The following API endpoints accept a `webhook` parameter:
|
||||
|
||||
In this example, we will show calling a webhook after streaming a run.
|
||||
| Operation | HTTP Method | Endpoint |
|
||||
|-----------|------------|----------|
|
||||
| Create Run | `POST` | `/thread/{thread_id}/runs` |
|
||||
| Create Thread Cron | `POST` | `/thread/{thread_id}/runs/crons` |
|
||||
| Stream Run | `POST` | `/thread/{thread_id}/runs/stream` |
|
||||
| Wait Run | `POST` | `/thread/{thread_id}/runs/wait` |
|
||||
| Create Cron | `POST` | `/runs/crons` |
|
||||
| Stream Run Stateless | `POST` | `/runs/stream` |
|
||||
| Wait Run Stateless | `POST` | `/runs/wait` |
|
||||
|
||||
## Setup
|
||||
In this guide, we’ll show how to trigger a webhook after streaming a run.
|
||||
|
||||
First, let's setup our assistant and thread:
|
||||
## Setting Up Your Assistant and Thread
|
||||
|
||||
Before making API calls, set up your assistant and thread.
|
||||
|
||||
=== "Python"
|
||||
```python
|
||||
from langgraph_sdk import get_client
|
||||
|
||||
```python
|
||||
from langgraph_sdk import get_client
|
||||
client = get_client(url=<DEPLOYMENT_URL>)
|
||||
assistant_id = "agent"
|
||||
thread = await client.threads.create()
|
||||
print(thread)
|
||||
```
|
||||
|
||||
client = get_client(url=<DEPLOYMENT_URL>)
|
||||
# Using the graph deployed with the name "agent"
|
||||
assistant_id = "agent"
|
||||
# create thread
|
||||
thread = await client.threads.create()
|
||||
print(thread)
|
||||
```
|
||||
=== "JavaScript"
|
||||
```js
|
||||
import { Client } from "@langchain/langgraph-sdk";
|
||||
|
||||
=== "Javascript"
|
||||
|
||||
```js
|
||||
import { Client } from "@langchain/langgraph-sdk";
|
||||
|
||||
const client = new Client({ apiUrl: <DEPLOYMENT_URL> });
|
||||
// Using the graph deployed with the name "agent"
|
||||
const assistantID = "agent";
|
||||
// create thread
|
||||
const thread = await client.threads.create();
|
||||
console.log(thread);
|
||||
```
|
||||
const client = new Client({ apiUrl: <DEPLOYMENT_URL> });
|
||||
const assistantID = "agent";
|
||||
const thread = await client.threads.create();
|
||||
console.log(thread);
|
||||
```
|
||||
|
||||
=== "CURL"
|
||||
```bash
|
||||
curl --request POST \
|
||||
--url <DEPLOYMENT_URL>/assistants/search \
|
||||
--header 'Content-Type: application/json' \
|
||||
--data '{ "limit": 10, "offset": 0 }' | jq -c 'map(select(.config == null or .config == {})) | .[0]' && \
|
||||
curl --request POST \
|
||||
--url <DEPLOYMENT_URL>/threads \
|
||||
--header 'Content-Type: application/json' \
|
||||
--data '{}'
|
||||
```
|
||||
|
||||
```bash
|
||||
curl --request POST \
|
||||
--url <DEPLOYMENT_URL>/assistants/search \
|
||||
--header 'Content-Type: application/json' \
|
||||
--data '{
|
||||
"limit": 10,
|
||||
"offset": 0
|
||||
}' | jq -c 'map(select(.config == null or .config == {})) | .[0]' && \
|
||||
curl --request POST \
|
||||
--url <DEPLOYMENT_URL>/threads \
|
||||
--header 'Content-Type: application/json' \
|
||||
--data '{}'
|
||||
```
|
||||
### Example Response
|
||||
```json
|
||||
{
|
||||
"thread_id": "9dde5490-2b67-47c8-aa14-4bfec88af217",
|
||||
"created_at": "2024-08-30T23:07:38.242730+00:00",
|
||||
"updated_at": "2024-08-30T23:07:38.242730+00:00",
|
||||
"metadata": {},
|
||||
"status": "idle",
|
||||
"config": {},
|
||||
"values": null
|
||||
}
|
||||
```
|
||||
|
||||
Output:
|
||||
## Using a Webhook with a Graph Run
|
||||
|
||||
{
|
||||
'thread_id': '9dde5490-2b67-47c8-aa14-4bfec88af217',
|
||||
'created_at': '2024-08-30T23:07:38.242730+00:00',
|
||||
'updated_at': '2024-08-30T23:07:38.242730+00:00',
|
||||
'metadata': {},
|
||||
'status': 'idle',
|
||||
'config': {},
|
||||
'values': None
|
||||
}
|
||||
To use a webhook, specify the `webhook` parameter in your API request. When the run completes, LangGraph Cloud sends a `POST` request to the specified webhook URL.
|
||||
|
||||
## Use graph with a webhook
|
||||
|
||||
To invoke a run with a webhook, we specify the `webhook` parameter with the desired endpoint when creating a run. Webhook requests are triggered by the end of a run.
|
||||
|
||||
For example, if we can receive requests at `https://my-server.app/my-webhook-endpoint`, we can pass this to `stream`:
|
||||
For example, if your server listens for webhook events at `https://my-server.app/my-webhook-endpoint`, include this in your request:
|
||||
|
||||
=== "Python"
|
||||
```python
|
||||
input = { "messages": [{ "role": "user", "content": "Hello!" }] }
|
||||
|
||||
```python
|
||||
# create input
|
||||
input = { "messages": [{ "role": "user", "content": "Hello!" }] }
|
||||
async for chunk in client.runs.stream(
|
||||
thread_id=thread["thread_id"],
|
||||
assistant_id=assistant_id,
|
||||
input=input,
|
||||
stream_mode="events",
|
||||
webhook="https://my-server.app/my-webhook-endpoint"
|
||||
):
|
||||
pass
|
||||
```
|
||||
|
||||
async for chunk in client.runs.stream(
|
||||
thread_id=thread["thread_id"],
|
||||
assistant_id=assistant_id,
|
||||
input=input,
|
||||
stream_mode="events",
|
||||
webhook="https://my-server.app/my-webhook-endpoint"
|
||||
):
|
||||
# Do something with the stream output
|
||||
pass
|
||||
```
|
||||
=== "JavaScript"
|
||||
```js
|
||||
const input = { messages: [{ role: "human", content: "Hello!" }] };
|
||||
|
||||
=== "Javascript"
|
||||
const streamResponse = client.runs.stream(
|
||||
thread["thread_id"],
|
||||
assistantID,
|
||||
{
|
||||
input: input,
|
||||
webhook: "https://my-server.app/my-webhook-endpoint"
|
||||
}
|
||||
);
|
||||
|
||||
```js
|
||||
// create input
|
||||
const input = { messages: [{ role: "human", content: "Hello!" }] };
|
||||
|
||||
// stream events
|
||||
const streamResponse = client.runs.stream(
|
||||
thread["thread_id"],
|
||||
assistantID,
|
||||
{
|
||||
input: input,
|
||||
webhook: "https://my-server.app/my-webhook-endpoint"
|
||||
}
|
||||
);
|
||||
for await (const chunk of streamResponse) {
|
||||
// Do something with the stream output
|
||||
}
|
||||
```
|
||||
for await (const chunk of streamResponse) {
|
||||
// Handle stream output
|
||||
}
|
||||
```
|
||||
|
||||
=== "CURL"
|
||||
|
||||
```bash
|
||||
curl --request POST \
|
||||
--url <DEPLOYMENT_URL>/threads/<THREAD_ID>/runs/stream \
|
||||
--header 'Content-Type: application/json' \
|
||||
--data '{
|
||||
"assistant_id": <ASSISTANT_ID>,
|
||||
"input" : {"messages":[{"role": "user", "content": "Hello!"}]},
|
||||
"webhook": "https://my-server.app/my-webhook-endpoint"
|
||||
}'
|
||||
```
|
||||
|
||||
The schema for the payload sent to `my-webhook-endpoint` is that of a [run](../../concepts/langgraph_server.md/#runs). See [API Reference](https://langchain-ai.github.io/langgraph/cloud/reference/api/api_ref.html#model/run) for more detail. Note that the run input, configuration, etc. are included in the `kwargs` field.
|
||||
|
||||
### Signing webhook requests
|
||||
|
||||
To sign the webhook requests, we can specify a token parameter in the webhook URL, e.g.,
|
||||
```
|
||||
https://my-server.app/my-webhook-endpoint?token=...
|
||||
```bash
|
||||
curl --request POST \
|
||||
--url <DEPLOYMENT_URL>/threads/<THREAD_ID>/runs/stream \
|
||||
--header 'Content-Type: application/json' \
|
||||
--data '{
|
||||
"assistant_id": <ASSISTANT_ID>,
|
||||
"input": {"messages": [{"role": "user", "content": "Hello!"}]},
|
||||
"webhook": "https://my-server.app/my-webhook-endpoint"
|
||||
}'
|
||||
```
|
||||
|
||||
The server should then extract the token from the request's parameters and validate it before processing the payload.
|
||||
## Webhook Payload
|
||||
|
||||
LangGraph Cloud sends webhook notifications in the format of a [Run](../../concepts/langgraph_server.md/#runs). See the [API Reference](https://langchain-ai.github.io/langgraph/cloud/reference/api/api_ref.html#model/run) for details. The request payload includes run input, configuration, and other metadata in the `kwargs` field.
|
||||
|
||||
## Securing Webhooks
|
||||
|
||||
To ensure only authorized requests hit your webhook endpoint, consider adding a security token as a query parameter:
|
||||
|
||||
```
|
||||
https://my-server.app/my-webhook-endpoint?token=YOUR_SECRET_TOKEN
|
||||
```
|
||||
|
||||
Your server should extract and validate this token before processing requests.
|
||||
|
||||
## Testing Webhooks
|
||||
|
||||
You can test your webhook using online services like:
|
||||
|
||||
- **[Beeceptor](https://beeceptor.com/)** – Quickly create a test endpoint and inspect incoming webhook payloads.
|
||||
- **[Webhook.site](https://webhook.site/)** – View, debug, and log incoming webhook requests in real time.
|
||||
|
||||
These tools help you verify that LangGraph Cloud is correctly triggering and sending webhooks to your service.
|
||||
|
||||
---
|
||||
|
||||
By following these steps, you can integrate webhooks into your LangGraph Cloud workflow, automating actions based on completed runs.
|
||||
|
||||
@@ -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": [
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# LangGraph CLI
|
||||
|
||||
The LangGraph command line interface includes commands to build and run a LangGraph Cloud API server locally in [Docker](https://www.docker.com/). For development and testing, you can use the CLI to deploy a local API server as an alternative to the [Studio desktop app](../../concepts/langgraph_studio.md).
|
||||
The LangGraph command line interface includes commands to build and run a LangGraph Cloud API server locally in [Docker](https://www.docker.com/). For development and testing, you can use the CLI to deploy a local API server.
|
||||
|
||||
## Installation
|
||||
|
||||
@@ -29,7 +29,7 @@ The LangGraph command line interface includes commands to build and run a LangGr
|
||||
|
||||
## Configuration File {#configuration-file}
|
||||
|
||||
The LangGraph CLI requires a JSON configuration file with the following keys:
|
||||
The LangGraph CLI requires a JSON configuration file that follows this [schema](https://raw.githubusercontent.com/langchain-ai/langgraph/refs/heads/main/libs/cli/schemas/schema.json). It contains the following properties:
|
||||
|
||||
<div class="admonition tip">
|
||||
<p class="admonition-title">Note</p>
|
||||
@@ -42,15 +42,17 @@ The LangGraph CLI requires a JSON configuration file with the following keys:
|
||||
|
||||
| Key | Description |
|
||||
| ------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| <span style="white-space: nowrap;">`dependencies`</span> | **Required**. Array of dependencies for LangGraph Cloud API server. Dependencies can be one of the following: (1) `"."`, which will look for local Python packages, (2) `pyproject.toml`, `setup.py` or `requirements.txt` in the app directory `"./local_package"`, or (3) a package name. |
|
||||
| <span style="white-space: nowrap;">`dependencies`</span> | **Required**. Array of dependencies for LangGraph Cloud API server. Dependencies can be one of the following: <ul><li>A single period (`"."`), which will look for local Python packages.</li><li>The directory path where `pyproject.toml`, `setup.py` or `requirements.txt` is located.</br></br>For example, if `requirements.txt` is located in the root of the project directory, specify `"./"`. If it's located in a subdirectory called `local_package`, specify `"./local_package"`. Do not specify the string `"requirements.txt"` itself.</li><li>A Python package name.</li></ul> |
|
||||
| <span style="white-space: nowrap;">`graphs`</span> | **Required**. Mapping from graph ID to path where the compiled graph or a function that makes a graph is defined. Example: <ul><li>`./your_package/your_file.py:variable`, where `variable` is an instance of `langgraph.graph.state.CompiledStateGraph`</li><li>`./your_package/your_file.py:make_graph`, where `make_graph` is a function that takes a config dictionary (`langchain_core.runnables.RunnableConfig`) and creates an instance of `langgraph.graph.state.StateGraph` / `langgraph.graph.state.CompiledStateGraph`.</li></ul> |
|
||||
| <span style="white-space: nowrap;">`auth`</span> | _(Added in v0.0.11)_ Auth configuration containing the path to your authentication handler. Example: `./your_package/auth.py:auth`, where `auth` is an instance of `langgraph_sdk.Auth`. See [authentication guide](../../concepts/auth.md) for details. |
|
||||
| <span style="white-space: nowrap;">`env`</span> | Path to `.env` file or a mapping from environment variable to its value. |
|
||||
| <span style="white-space: nowrap;">`store`</span> | Configuration for adding semantic search to the BaseStore. Contains the following fields: <ul><li>`index`: Configuration for semantic search indexing with fields:<ul><li>`embed`: Embedding provider (e.g., "openai:text-embedding-3-small") or path to custom embedding function</li><li>`dims`: Dimension size of the embedding model. Used to initialize the vector table.</li><li>`fields` (optional): List of fields to index. Defaults to `["$"]`, which means to index entire documents. Can be specific fields like `["text", "summary", "some.value"]`</li></ul></li></ul> |
|
||||
| <span style="white-space: nowrap;">`python_version`</span> | `3.11` or `3.12`. Defaults to `3.11`. |
|
||||
| <span style="white-space: nowrap;">`store`</span> | Configuration for adding semantic search and/or time-to-live (TTL) to the BaseStore. Contains the following fields: <ul><li>`index` (optional): Configuration for semantic search indexing with fields `embed`, `dims`, and optional `fields`.</li><li>`ttl` (optional): Configuration for item expiration. An object with optional fields: `refresh_on_read` (boolean, defaults to `true`), `default_ttl` (float, lifespan in **minutes**, defaults to no expiration), and `sweep_interval_minutes` (integer, how often to check for expired items, defaults to no sweeping).</li></ul> |
|
||||
| <span style="white-space: nowrap;">`python_version`</span> | `3.11`, `3.12`, or `3.13`. Defaults to `3.11`. |
|
||||
| <span style="white-space: nowrap;">`node_version`</span> | Specify `node_version: 20` to use LangGraph.js. |
|
||||
| <span style="white-space: nowrap;">`pip_config_file`</span> | Path to `pip` config file. |
|
||||
| <span style="white-space: nowrap;">`dockerfile_lines`</span> | Array of additional lines to add to Dockerfile following the import from parent image. |
|
||||
| <span style="white-space: nowrap;">`checkpointer`</span> | Configuration for the checkpointer. Contains a `ttl` field which is an object with the following keys: <ul><li>`strategy`: How to handle expired checkpoints (e.g., `"delete"`).</li><li>`sweep_interval_minutes`: How often to check for expired checkpoints (integer).</li><li>`default_ttl`: Default time-to-live for checkpoints in **minutes** (integer). Defines how long checkpoints are kept before the specified strategy is applied.</li></ul> |
|
||||
| <span style="white-space: nowrap;">`http`</span> | HTTP server configuration with the following fields: <ul><li>`app`: Path to custom Starlette/FastAPI app (e.g., `"./src/agent/webapp.py:app"`). See [custom routes guide](../../how-tos/http/custom_routes.md).</li><li>`disable_assistants`: Disable `/assistants` routes</li><li>`disable_threads`: Disable `/threads` routes</li><li>`disable_runs`: Disable `/runs` routes</li><li>`disable_store`: Disable `/store` routes</li><li>`disable_meta`: Disable `/ok`, `/info`, `/metrics`, and `/docs` routes</li><li>`cors`: CORS configuration with fields for `allow_origins`, `allow_methods`, `allow_headers`, etc.</li></ul> |
|
||||
|
||||
=== "JS"
|
||||
|
||||
@@ -58,9 +60,10 @@ The LangGraph CLI requires a JSON configuration file with the following keys:
|
||||
| ------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| <span style="white-space: nowrap;">`graphs`</span> | **Required**. Mapping from graph ID to path where the compiled graph or a function that makes a graph is defined. Example: <ul><li>`./src/graph.ts:variable`, where `variable` is an instance of `CompiledStateGraph`</li><li>`./src/graph.ts:makeGraph`, where `makeGraph` is a function that takes a config dictionary (`LangGraphRunnableConfig`) and creates an instance of `StateGraph` / `CompiledStateGraph`.</li></ul> |
|
||||
| <span style="white-space: nowrap;">`env`</span> | Path to `.env` file or a mapping from environment variable to its value. |
|
||||
| <span style="white-space: nowrap;">`store`</span> | Configuration for adding semantic search to the BaseStore. Contains the following fields: <ul><li>`index`: Configuration for semantic search indexing with fields:<ul><li>`embed`: Embedding provider (e.g., "openai:text-embedding-3-small") or path to custom embedding function</li><li>`dims`: Dimension size of the embedding model. Used to initialize the vector table.</li><li>`fields` (optional): List of fields to index. Defaults to `["$"]`, which means to index entire documents. Can be specific fields like `["text", "summary", "some.value"]`</li></ul></li></ul> |
|
||||
| <span style="white-space: nowrap;">`store`</span> | Configuration for adding semantic search and/or time-to-live (TTL) to the BaseStore. Contains the following fields: <ul><li>`index` (optional): Configuration for semantic search indexing with fields `embed`, `dims`, and optional `fields`.</li><li>`ttl` (optional): Configuration for item expiration. An object with optional fields: `refresh_on_read` (boolean, defaults to `true`), `default_ttl` (float, lifespan in **minutes**, defaults to no expiration), and `sweep_interval_minutes` (integer, how often to check for expired items, defaults to no sweeping).</li></ul> |
|
||||
| <span style="white-space: nowrap;">`node_version`</span> | Specify `node_version: 20` to use LangGraph.js. |
|
||||
| <span style="white-space: nowrap;">`dockerfile_lines`</span> | Array of additional lines to add to Dockerfile following the import from parent image. |
|
||||
| <span style="white-space: nowrap;">`checkpointer`</span> | Configuration for the checkpointer. Contains a `ttl` field which is an object with the following keys: <ul><li>`strategy`: How to handle expired checkpoints (e.g., `"delete"`).</li><li>`sweep_interval_minutes`: How often to check for expired checkpoints (integer).</li><li>`default_ttl`: Default time-to-live for checkpoints in **minutes** (integer). Defines how long checkpoints are kept before the specified strategy is applied.</li></ul> |
|
||||
|
||||
### Examples
|
||||
|
||||
@@ -81,7 +84,7 @@ The LangGraph CLI requires a JSON configuration file with the following keys:
|
||||
|
||||
All deployments come with a DB-backed BaseStore. Adding an "index" configuration to your `langgraph.json` will enable [semantic search](../deployment/semantic_search.md) within the BaseStore of your deployment.
|
||||
|
||||
The `fields` configuration determines which parts of your documents to embed:
|
||||
The `index.fields` configuration determines which parts of your documents to embed:
|
||||
|
||||
- If omitted or set to `["$"]`, the entire document will be embedded
|
||||
- To embed specific fields, use JSON path notation: `["metadata.title", "content.text"]`
|
||||
@@ -170,6 +173,62 @@ The LangGraph CLI requires a JSON configuration file with the following keys:
|
||||
|
||||
See the [authentication conceptual guide](../../concepts/auth.md) for details, and the [setting up custom authentication](../../tutorials/auth/getting_started.md) guide for a practical walk through of the process.
|
||||
|
||||
#### Configuring Store Item Time-to-Live (TTL)
|
||||
|
||||
You can configure default data expiration for items/memories in the BaseStore using the `store.ttl` key. This determines how long items are retained after they are last accessed (with reads potentially refreshing the timer based on `refresh_on_read`). Note that these defaults can be overwritten on a per-call basis by modifying the corresponding arguments in `get`, `search`, etc.
|
||||
|
||||
The `ttl` configuration is an object containing optional fields:
|
||||
|
||||
- `refresh_on_read`: If `true` (the default), accessing an item via `get` or `search` resets its expiration timer. Set to `false` to only refresh TTL on writes (`put`).
|
||||
- `default_ttl`: The default lifespan of an item in **minutes**. If not set, items do not expire by default.
|
||||
- `sweep_interval_minutes`: How frequently (in minutes) the system should run a background process to delete expired items. If not set, sweeping does not occur automatically.
|
||||
|
||||
Here is an example enabling a 7-day TTL (10080 minutes), refreshing on reads, and sweeping every hour:
|
||||
|
||||
```json
|
||||
{
|
||||
"dependencies": ["."],
|
||||
"graphs": {
|
||||
"memory_agent": "./agent/graph.py:graph"
|
||||
},
|
||||
"store": {
|
||||
"ttl": {
|
||||
"refresh_on_read": true,
|
||||
"sweep_interval_minutes": 60,
|
||||
"default_ttl": 10080
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### Configuring Checkpoint Time-to-Live (TTL)
|
||||
|
||||
You can configure the time-to-live (TTL) for checkpoints using the `checkpointer` key. This determines how long checkpoint data is retained before being automatically handled according to the specified strategy (e.g., deletion). The `ttl` configuration is an object containing:
|
||||
|
||||
- `strategy`: The action to take on expired checkpoints (currently `"delete"` is the only accepted option).
|
||||
- `sweep_interval_minutes`: How frequently (in minutes) the system checks for expired checkpoints.
|
||||
- `default_ttl`: The default lifespan of a checkpoint in **minutes**.
|
||||
|
||||
Here's an example setting a default TTL of 30 days (43200 minutes):
|
||||
|
||||
```json
|
||||
{
|
||||
"dependencies": ["."],
|
||||
"graphs": {
|
||||
"chat": "./chat/graph.py:graph"
|
||||
},
|
||||
"checkpointer": {
|
||||
"ttl": {
|
||||
"strategy": "delete",
|
||||
"sweep_interval_minutes": 10,
|
||||
"default_ttl": 43200
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
In this example, checkpoints older than 30 days will be deleted, and the check runs every 10 minutes.
|
||||
|
||||
|
||||
=== "JS"
|
||||
|
||||
|
||||
@@ -2,6 +2,28 @@
|
||||
|
||||
The LangGraph Cloud Server supports specific environment variables for configuring a deployment.
|
||||
|
||||
## `BG_JOB_ISOLATED_LOOPS`
|
||||
|
||||
Set `BG_JOB_ISOLATED_LOOPS` to `True` to execute background runs in an isolated event loop separate from the serving API event loop.
|
||||
|
||||
This environment variable should be set to `True` if the implementation of a graph/node contains synchronous code. In this situation, the synchronous code will block the serving API event loop, which may cause the API to be unavailable. A symptom of an unavailable API is continuous application restarts due to failing health checks.
|
||||
|
||||
Defaults to `False`.
|
||||
|
||||
## `BG_JOB_TIMEOUT_SECS`
|
||||
|
||||
The timeout of a background run can be increased. However, the infrastructure for a Cloud SaaS deployment enforces a 1 hour timeout limit for API requests. This means the connection between client and server will timeout after 1 hour. This is not configurable.
|
||||
|
||||
A background run can execute for longer than 1 hour, but a client must reconnect to the server (e.g. join stream via `POST /threads/{thread_id}/runs/{run_id}/stream`) to retrieve output from the run if the run is taking longer than 1 hour.
|
||||
|
||||
Defaults to `3600`.
|
||||
|
||||
## `DD_API_KEY`
|
||||
|
||||
Specify `DD_API_KEY` (your [Datadog API Key](https://docs.datadoghq.com/account_management/api-app-keys/)) to automatically enable Datadog tracing for the deployment. Specify other [`DD_*` environment variables](https://ddtrace.readthedocs.io/en/stable/configuration.html) to configure the tracing instrumentation.
|
||||
|
||||
If `DD_API_KEY` is specified, the application process is wrapped in the [`ddtrace-run` command](https://ddtrace.readthedocs.io/en/stable/installation_quickstart.html). Other `DD_*` environment variables (e.g. `DD_SITE`, `DD_ENV`, `DD_SERVICE`, `DD_TRACE_ENABLED`) are typically needed to properly configure the tracing instrumentation. See [`DD_*` environment variables](https://ddtrace.readthedocs.io/en/stable/configuration.html) for more details.
|
||||
|
||||
## `LANGCHAIN_TRACING_SAMPLING_RATE`
|
||||
|
||||
Sampling rate for traces sent to LangSmith. Valid values: Any float between `0` and `1`.
|
||||
@@ -22,6 +44,10 @@ Set this environment variable to have a BYOC deployment send traces to a self-ho
|
||||
|
||||
`SELF_HOSTED_LANGSMITH_HOSTNAME` is the hostname of the self-hosted LangSmith instance. It must be accessible to the BYOC deployment. `LANGSMITH_API_KEY` is a LangSmith API generated from the self-hosted LangSmith instance.
|
||||
|
||||
## `LOG_LEVEL`
|
||||
|
||||
Configure [log level](https://docs.python.org/3/library/logging.html#logging-levels). Defaults to `INFO`.
|
||||
|
||||
## `N_JOBS_PER_WORKER`
|
||||
|
||||
Number of jobs per worker for the LangGraph Cloud task queue. Defaults to `10`.
|
||||
@@ -49,3 +75,9 @@ Database Connectivity:
|
||||
|
||||
- The externally managed Postgres instance must be accessible by the LangGraph Server service in the ECS cluster. The BYOC user is responsible for ensuring connectivity.
|
||||
- For example, if an AWS RDS Postgres instance is provisioned, it can be provisioned in the same VPC (`langgraph-cloud-vpc`) as the ECS cluster with the `langgraph-cloud-service-sg` security group to ensure connectivity.
|
||||
|
||||
## `REDIS_URI_CUSTOM`
|
||||
|
||||
For [Bring Your Own Cloud (BYOC)](../../concepts/bring_your_own_cloud.md) deployments only.
|
||||
|
||||
Specify `REDIS_URI_CUSTOM` to use an externally managed Redis instance. The value of `REDIS_URI_CUSTOM` must be a valid [Redis connection URI](https://redis-py.readthedocs.io/en/stable/connections.html#redis.Redis.from_url).
|
||||
|
||||
@@ -14,7 +14,7 @@ As a result, there are many different types of [agent architectures](https://blo
|
||||
|
||||
## Router
|
||||
|
||||
A router allows an LLM to select a single step from a specified set of options. This is an agent architecture that exhibits a relatively limited level of control because the LLM usually focuses on making a single decision and produces a specific output from limited set of pre-defined options. Routers typically employ a few different concepts to achieve this.
|
||||
A router allows an LLM to select a single step from a specified set of options. This is an agent architecture that exhibits a relatively limited level of control because the LLM usually focuses on making a single decision and produces a specific output from a limited set of pre-defined options. Routers typically employ a few different concepts to achieve this.
|
||||
|
||||
### Structured Output
|
||||
|
||||
|
||||
@@ -2,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. **[Cloud SaaS](#cloud-saas)**: Available for **Plus** and **Enterprise** plans.
|
||||
|
||||
2. **[Self-Hosted Enterprise](#self-hosted-enterprise)**: Available for the **Enterprise** plan.
|
||||
1. **[Self-Hosted Data Plane](#self-hosted-data-plane)**: Available for the **Enterprise** plan.
|
||||
|
||||
3. **[Cloud SaaS](#cloud-saas)**: Available for **Plus** and **Enterprise** plans.
|
||||
1. **[Self-Hosted Control Plane](#self-hosted-control-plane)**: Available for the **Enterprise** plan.
|
||||
|
||||
4. **[Bring Your Own Cloud](#bring-your-own-cloud)**: Available only for **Enterprise** plans and **only on AWS**.
|
||||
1. **[Standalone Container](#standalone-container)**: Available for all plans.
|
||||
|
||||
Please see the [LangGraph Platform Plans](./plans.md) for more information on the different plans.
|
||||
|
||||
The guide below will explain the differences between the deployment options.
|
||||
|
||||
## Self-Hosted Enterprise
|
||||
|
||||
!!! important
|
||||
|
||||
The Self-Hosted Enterprise version is only available for the **Enterprise** plan.
|
||||
|
||||
!!! warning "Note"
|
||||
|
||||
The LangGraph Platform Deployments view is optionally available for Self-Hosted Enterprise LangGraph deployments. With one click, self-hosted LangGraph deployments can be deployed in the same Kubernetes cluster where a self-hosted LangSmith instance is deployed.
|
||||
|
||||
With a Self-Hosted Enterprise deployment, you are responsible for managing the infrastructure, including setting up and maintaining required databases and Redis instances.
|
||||
|
||||
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
|
||||
|
||||
|
||||
@@ -36,7 +36,7 @@ LangGraph is a stateful, orchestration framework that brings added control to ag
|
||||
| Concurrency Control | Simple threading | Supports double-texting |
|
||||
| Scheduling | None | Cron scheduling |
|
||||
| Monitoring | None | Integrated with LangSmith for observability |
|
||||
| IDE integration | LangGraph Studio for Desktop | LangGraph Studio for Desktop & Cloud |
|
||||
| IDE integration | LangGraph Studio | LangGraph Studio |
|
||||
|
||||
## What are my deployment options for LangGraph Platform?
|
||||
|
||||
@@ -62,3 +62,9 @@ Yes! You can use LangGraph with any LLMs. The main reason we use LLMs that suppo
|
||||
## Does LangGraph work with OSS LLMs?
|
||||
|
||||
Yes! LangGraph is totally ambivalent to what LLMs are used under the hood. The main reason we use closed LLMs in most of the tutorials is that they seamlessly support tool calling, while OSS LLMs often don't. But tool calling is not necessary (see [this section](#does-langgraph-work-with-llms-that-dont-support-tool-calling)) so you can totally use LangGraph with OSS LLMs.
|
||||
|
||||
## Can I use LangGraph Studio without logging to LangSmith
|
||||
|
||||
Yes! You can use the [development version of LangGraph Server](../tutorials/langgraph-platform/local-server.md) to run the backend locally.
|
||||
This will connect to the studio frontend hosted as part of LangSmith.
|
||||
If you set an environment variable of `LANGSMITH_TRACING=false` then no traces will be sent to LangSmith.
|
||||
@@ -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."""
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
## LLM applications
|
||||
|
||||
LLMs make it possible to embed intelligence into a new class of applications. There are many patterns for building applications that use LLMs. [Workflows](https://www.anthropic.com/research/building-effective-agents) have scaffolding of predefined code paths around LLM calls. LLMs can direct the control flow through these predefined code paths, which some consider to be an "[agentic system](https://www.anthropic.com/research/building-effective-agents)". In other cases, it's possible to remove this scaffolding, creating autonomous agents that can [plan](https://huyenchip.com/2025/01/07/agents.html), take actions via [tool calls](https://python.langchain.com/docs/concepts/tool_calling/), and directly respond [to the feedback from their own actions](https://research.google/blog/react-synergizing-reasoning-and-acting-in-language-models/) with further actions.
|
||||
LLMs make it possible to embed intelligence into a new class of applications. There are many patterns for building applications that use LLMs. Workflows have scaffolding of predefined code paths around LLM calls. LLMs can direct the control flow through these predefined code paths, which some consider to be an "agentic system". In other cases, it's possible to remove this scaffolding, creating autonomous agents that can [plan](https://huyenchip.com/2025/01/07/agents.html), take actions via [tool calls](https://python.langchain.com/docs/concepts/tool_calling/), and directly respond [to the feedback from their own actions](https://research.google/blog/react-synergizing-reasoning-and-acting-in-language-models/) with further actions.
|
||||
|
||||

|
||||
|
||||
|
||||
@@ -647,19 +647,15 @@ def node_in_parent_graph(state: State):
|
||||
This will print out
|
||||
|
||||
```pycon
|
||||
--- First invocation ---
|
||||
In parent node: {'foo': 'bar'}
|
||||
Entered `parent_node` a total of 1 times
|
||||
Entered `node_in_subgraph` a total of 1 times
|
||||
Entered human_node in sub-graph a total of 1 times
|
||||
{'__interrupt__': (Interrupt(value='what is your name?', resumable=True, ns=['parent_node:0b23d72f-aaba-0329-1a59-ca4f3c8bad3b', 'human_node:25df717c-cb80-57b0-7410-44e20aac8f3c'], when='during'),)}
|
||||
|
||||
{'__interrupt__': (Interrupt(value='what is your name?', resumable=True, ns=['parent_node:4c3a0248-21f0-1287-eacf-3002bc304db4', 'human_node:2fe86d52-6f70-2a3f-6b2f-b1eededd6348'], when='during'),)}
|
||||
--- Resuming ---
|
||||
In parent node: {'foo': 'bar'}
|
||||
Entered `parent_node` a total of 2 times
|
||||
Entered human_node in sub-graph a total of 2 times
|
||||
Got an answer of 35
|
||||
{'parent_node': None}
|
||||
{'parent_node': {'state_counter': 1}}
|
||||
```
|
||||
|
||||
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 437 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 668 KiB |
@@ -30,6 +30,7 @@ The conceptual guide does not cover step-by-step instructions or specific implem
|
||||
- [Streaming](streaming.md): Streaming is crucial for enhancing the responsiveness of applications built on LLMs. By displaying output progressively, even before a complete response is ready, streaming significantly improves user experience (UX), particularly when dealing with the latency of LLMs.
|
||||
- [Functional API](functional_api.md): `@entrypoint` and `@task` decorators that allow you to add LangGraph functionality to an existing codebase.
|
||||
- [Durable Execution](durable_execution.md): LangGraph's built-in [persistence](./persistence.md) layer provides durable execution for workflows, ensuring that the state of each execution step is saved to a durable store.
|
||||
- [Pregel](pregel.md): Pregel is LangGraph's runtime, which is responsible for managing the execution of LangGraph applications.
|
||||
- [FAQ](faq.md): Frequently asked questions about LangGraph.
|
||||
|
||||
## LangGraph Platform
|
||||
@@ -47,7 +48,8 @@ The LangGraph Platform offers a few different deployment options described in th
|
||||
|
||||
- [Why LangGraph Platform?](./langgraph_platform.md): The LangGraph platform is an opinionated way to deploy and manage LangGraph applications. This guide provides an overview of the key features and concepts behind LangGraph Platform.
|
||||
- [Platform Architecture](./platform_architecture.md): A high-level overview of the architecture of the LangGraph Platform.
|
||||
- [Deployment Options](./deployment_options.md): LangGraph Platform offers four deployment options: [Self-Hosted Lite](./self_hosted.md#self-hosted-lite), [Self-Hosted Enterprise](./self_hosted.md#self-hosted-enterprise), [bring your own cloud (BYOC)](./bring_your_own_cloud.md), and [Cloud SaaS](./langgraph_cloud.md). This guide explains the differences between these options, and which Plans they are available on.
|
||||
- [Scalability and Resilience](./scalability_and_resilience.md): LangGraph Platform is designed to be scalable and resilient. This document explains how the platform achieves this.
|
||||
- [Deployment Options](./deployment_options.md): LangGraph Platform offers four deployment options: [Cloud SaaS](./langgraph_cloud.md), [Self-Hosted Data Plane](./langgraph_self_hosted_data_plane.md), [Self-Hosted Control Plane](./langgraph_self_hosted_control_plane.md), and [Standalone Container](./langgraph_standalone_container.md). This guide explains the differences between these options, and which Plans they are available on.
|
||||
- [Plans](./plans.md): LangGraph Platforms offer three different plans: Developer, Plus, Enterprise. This guide explains the differences between these options, what deployment options are available for each, and how to sign up for each one.
|
||||
- [Template Applications](./template_applications.md): Reference applications designed to help you get started quickly when building with LangGraph.
|
||||
|
||||
@@ -60,6 +62,8 @@ The LangGraph Platform comprises several components that work together to suppor
|
||||
- [LangGraph CLI](./langgraph_cli.md): LangGraph CLI is a command-line interface that helps to interact with a local LangGraph
|
||||
- [Python/JS SDK](./sdk.md): The Python/JS SDK provides a programmatic way to interact with deployed LangGraph Applications.
|
||||
- [Remote Graph](../how-tos/use-remote-graph.md): A RemoteGraph allows you to interact with any deployed LangGraph application as though it were running locally.
|
||||
- [LangGraph Control Plane](./langgraph_control_plane.md): The LangGraph Control Plane refers to the Control Plane UI where users create and update LangGraph Servers and the Control Plane APIs that support the UI experience.
|
||||
- [LangGraph Data Plane](./langgraph_data_plane.md): The LangGraph Data Plane refers to LangGraph Servers, the corresponding infrastructure for each server, and the "listener" application that continuously polls for updates from the LangGraph Control Plane.
|
||||
|
||||
### LangGraph Server
|
||||
|
||||
@@ -72,7 +76,7 @@ The LangGraph Platform comprises several components that work together to suppor
|
||||
|
||||
### Deployment Options
|
||||
|
||||
- [Self-Hosted Lite](./self_hosted.md): A free (up to 1 million nodes executed per year), limited version of LangGraph Platform that you can run locally or in a self-hosted manner
|
||||
- [Cloud SaaS](./langgraph_cloud.md): Hosted as part of LangSmith.
|
||||
- [Bring Your Own Cloud](./bring_your_own_cloud.md): We manage the infrastructure, so you don't have to, but the infrastructure all runs within your cloud.
|
||||
- [Self-Hosted Enterprise](./self_hosted.md): Completely managed by you.
|
||||
- [Cloud SaaS](../concepts/langgraph_cloud.md): Connect to your GitHub repositories and deploy LangGraph Servers to LangChain's cloud. We manage everything.
|
||||
- [Self-Hosted Data Plane](../concepts/langgraph_self_hosted_data_plane.md): Create deployments from the [Control Plane UI](../concepts/langgraph_control_plane.md#control-plane-ui) and deploy LangGraph Servers to your cloud. We manage the [control plane](../concepts/langgraph_control_plane.md), you manage the deployments.
|
||||
- [Self-Hosted Control Plane](../concepts/langgraph_self_hosted_control_plane.md#control-plane-ui): Create deployments from a self-hosted [Control Plane UI](../concepts/langgraph_control_plane.md) and deploy LangGraph Servers to your cloud. You manage everything.
|
||||
- [Standalone Container](../concepts/langgraph_standalone_container.md): Deploy LangGraph Server Docker images however you like.
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
- [LangGraph Platform](./langgraph_platform.md)
|
||||
- [LangGraph Server](./langgraph_server.md)
|
||||
|
||||
The LangGraph CLI is a multi-platform command-line tool for building and running the [LangGraph API server](./langgraph_server.md) locally. This offers an alternative to the [LangGraph Studio desktop app](./langgraph_studio.md) for developing and testing agents across all major operating systems (Linux, Windows, MacOS). The resulting server includes all API endpoints for your graph's runs, threads, assistants, etc. as well as the other services required to run your agent, including a managed database for checkpointing and storage.
|
||||
The LangGraph CLI is a multi-platform command-line tool for building and running the [LangGraph API server](./langgraph_server.md) locally. The resulting server includes all API endpoints for your graph's runs, threads, assistants, etc. as well as the other services required to run your agent, including a managed database for checkpointing and storage.
|
||||
|
||||
## Installation
|
||||
|
||||
|
||||
@@ -1,85 +1,17 @@
|
||||
# Cloud SaaS
|
||||
|
||||
!!! info "Prerequisites"
|
||||
- [LangGraph Platform](./langgraph_platform.md)
|
||||
- [LangGraph Server](./langgraph_server.md)
|
||||
To deploy a [LangGraph Server](../concepts/langgraph_server.md), follow the how-to guide for [how to deploy to Cloud SaaS](../cloud/deployment/cloud.md).
|
||||
|
||||
## Overview
|
||||
|
||||
LangGraph's Cloud SaaS is a managed service for deploying LangGraph Servers, regardless of its definition or dependencies. The service offers managed implementations of checkpointers and stores, allowing you to focus on building the right cognitive architecture for your use case. By handling scalable & secure infrastructure, LangGraph Cloud SaaS offers the fastest path to getting your LangGraph Server deployed to production.
|
||||
The Cloud SaaS deployment option is a fully managed model for deployment where we manage the [control plane](./langgraph_control_plane.md) and [data plane](./langgraph_data_plane.md) in our cloud.
|
||||
|
||||
## Deployment
|
||||
|
||||
A **deployment** is an instance of a LangGraph Server. A single deployment can have many [revisions](#revision). When a deployment is created, all the necessary infrastructure (e.g. database, containers, secrets store) are automatically provisioned. See the [architecture diagram](#architecture) below for more details.
|
||||
|
||||
Resource Allocation:
|
||||
|
||||
| **Deployment Type** | **CPU** | **Memory** | **Scaling** |
|
||||
|---------------------|---------|------------|---------------------|
|
||||
| Development | 1 CPU | 1 GB | Up to 1 container |
|
||||
| Production | 2 CPU | 2 GB | Up to 10 containers |
|
||||
|
||||
See the [how-to guide](../cloud/deployment/cloud.md#create-new-deployment) for creating a new deployment.
|
||||
|
||||
## Revision
|
||||
|
||||
A revision is an iteration of a [deployment](#deployment). When a new deployment is created, an initial revision is automatically created. To deploy new code changes or update environment variable configurations for a deployment, a new revision must be created. When a revision is created, a new container image is built automatically.
|
||||
|
||||
See the [how-to guide](../cloud/deployment/cloud.md#create-new-revision) for creating a new revision.
|
||||
|
||||
## Persistence
|
||||
|
||||
A dedicated database is automatically created for each deployment. The database serves as the [persistence layer](../concepts/persistence.md) for the deployment.
|
||||
|
||||
When defining a graph to be deployed to LangGraph Cloud SaaS, a [checkpointer](../concepts/persistence.md#checkpointer-libraries) should not be configured by the user. Instead, a checkpointer is automatically configured for the graph.
|
||||
|
||||
There is no direct access to the database. All access to the database occurs through the LangGraph Server APIs.
|
||||
|
||||
## Autoscaling
|
||||
`Production` type deployments automatically scale up to 10 containers. Scaling is based on the current request load for a single container. Specifically, the autoscaling implementation scales the deployment so that each container is processing about 10 concurrent requests. For example...
|
||||
|
||||
- If the deployment is processing 20 concurrent requests, the deployment will scale up from 1 container to 2 containers (20 requests / 2 containers = 10 requests per container).
|
||||
- If a deployment of 2 containers is processing 10 requests, the deployment will scale down from 2 containers to 1 container (10 requests / 1 container = 10 requests per container).
|
||||
|
||||
10 concurrent requests per container is the target threshold. However, 10 concurrent requests per container is not a hard limit. The number of concurrent requests can exceed 10 if there is a sudden burst of requests.
|
||||
|
||||
Scale down actions are delayed for 30 minutes before any action is taken. In other words, if the autoscaling implementation decides to scale down a deployment, it will first wait for 30 minutes before scaling down. After 30 minutes, the concurrency metric is recomputed and the deployment will scale down if the concurrency metric has met the target threshold. Otherwise, the deployment remains scaled up. This "cool down" period ensures that deployments do not scale up and down too frequently.
|
||||
|
||||
In the future, the autoscaling implementation may evolve to accommodate other metrics such as background run queue size.
|
||||
|
||||
## Asynchronous Deployment
|
||||
|
||||
Infrastructure for [deployments](#deployment) and [revisions](#revision) are provisioned and deployed asynchronously. They are not deployed immediately after submission. Currently, deployment can take up to several minutes.
|
||||
|
||||
- When a new deployment is created, a new database is created for the deployment. Database creation is a one-time step. This step contributes to a longer deployment time for the initial revision of the deployment.
|
||||
- When a subsequent revision is created for a deployment, there is no database creation step. The deployment time for a subsequent revision is significantly faster compared to the deployment time of the initial revision.
|
||||
- The deployment process for each revision contains a build step, which can take up to a few minutes.
|
||||
|
||||
## LangSmith Integration
|
||||
|
||||
A [LangSmith](https://docs.smith.langchain.com/) tracing project is automatically created for each deployemnt. The tracing project has the same name as the deployment. When creating a deployment, the `LANGCHAIN_TRACING_V2` and `LANGCHAIN_API_KEY` environment variables do not need to be specified; they are set internally, automatically. Traces are created for each run and are emitted to the tracing project automatically.
|
||||
|
||||
When a deployment is deleted, the traces and the tracing project are not deleted.
|
||||
|
||||
## Automatic Deletion
|
||||
|
||||
Deployments are automatically deleted after 28 consecutive days of non-use (it is in an unused state). A deployment is in an unused state if there are no traces emitted to LangSmith from the deployment after 28 consecutive days. On any given day, if a deployment emits a trace to LangSmith, the counter for consecutive days of non-use is reset.
|
||||
|
||||
- An email notification is sent after 7 consecutive days of non-use.
|
||||
- A deployment is deleted after 28 consecutive days of non-use.
|
||||
|
||||
!!! danger "Data Cannot Be Recovered"
|
||||
After a deployment is deleted, the data (i.e. [persistence](#persistence)) from the deployment cannot be recovered.
|
||||
| | [Control Plane](../concepts/langgraph_control_plane.md) | [Data Plane](../concepts/langgraph_data_plane.md) |
|
||||
|-------------------|-------------------|------------|
|
||||
| **What is it?** | <ul><li>Control Plane UI for creating deployments and revisions</li><li>Control Plane APIs for creating deployments and revisions</li></ul> | <ul><li>Data plane "listener" for reconciling deployments with control plane state</li><li>LangGraph Servers</li><li>Postgres, Redis, etc</li></ul> |
|
||||
| **Where is it hosted?** | LangChain's cloud | LangChain's cloud |
|
||||
| **Who provisions and manages it?** | LangChain | LangChain |
|
||||
|
||||
## Architecture
|
||||
|
||||
!!! warning "Subject to Change"
|
||||
The Cloud SaaS deployment architecture may change in the future.
|
||||
|
||||
A high-level diagram of a Cloud SaaS deployment.
|
||||
|
||||

|
||||
|
||||
## 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,74 @@
|
||||
# LangGraph Data Plane
|
||||
|
||||
The term "data plane" is used broadly to refer to [LangGraph Servers](./langgraph_server.md) (deployments), the corresponding infrastructure for each server, and the "listener" application that continuously polls for updates from the [LangGraph Control Plane](./langgraph_control_plane.md).
|
||||
|
||||
## Server Infrastructure
|
||||
|
||||
In addition to the [LangGraph Server](./langgraph_server.md) itself, the following infrastructure for each server are also included in the broad definition of "data plane":
|
||||
|
||||
- [Postgres](../concepts/platform_architecture.md#how-we-use-postgres)
|
||||
- [Redis](../concepts/platform_architecture.md#how-we-use-redis)
|
||||
- Secrets store
|
||||
- Autoscalers
|
||||
|
||||
See [LangGraph Platform Architecture](../concepts/platform_architecture.md) for more details.
|
||||
|
||||
## "Listener" Application
|
||||
|
||||
The data plane "listener" application periodically calls [Control Plane APIs](../concepts/langgraph_control_plane.md#control-plane-api) to:
|
||||
|
||||
- Determine if new deployments should be created.
|
||||
- Determine if existing deployments should be updated (i.e. new revisions).
|
||||
- Determine if existing deployments should be deleted.
|
||||
|
||||
In other words, the data plane "listener" reads the latest state of the control plane (desired state) and takes action to reconcile outstanding deployments (current state) to match the latest state.
|
||||
|
||||
## Data Plane Features
|
||||
|
||||
This section describes various features of the data plane.
|
||||
|
||||
### Lite vs Enterprise
|
||||
|
||||
There are two versions of the LangGraph Server: `Lite` and `Enterprise`.
|
||||
|
||||
The `Lite` version is a limited version of the LangGraph Server that you can run locally or in a self-hosted manner (up to 1 million nodes executed per year). `Lite` is only available for the [Standalone Container](../concepts/langgraph_standalone_container.md) deployment option.
|
||||
|
||||
The `Enterprise` version is the full version of the LangGraph Server. To use the `Enterprise` version, you must acquire a license key that you will need to specify when running the Docker image. To acquire a license key, please email sales@langchain.dev. `Enterprise` is available for [Cloud SaaS](../concepts/langgraph_cloud.md), [Self-Hosted Data Plane](../concepts/langgraph_self_hosted_data_plane.md), and [Self-Hosted Control Plane](../concepts/langgraph_self_hosted_control_plane.md) deployment options.
|
||||
|
||||
Feature Differences:
|
||||
|
||||
| | Lite | Enterprise |
|
||||
|-------|------------|------------|
|
||||
| [Cron Jobs](../concepts/langgraph_server.md#cron-jobs) |❌|✅|
|
||||
| [Custom Authentication](../concepts/auth.md) |❌|✅|
|
||||
|
||||
### Autoscaling
|
||||
|
||||
[`Production` type](../concepts/langgraph_control_plane.md#deployment-types) deployments automatically scale up to 10 containers. Scaling is based on the current request load for a single container. Specifically, the autoscaling implementation scales the deployment so that each container is processing about 10 concurrent requests. For example...
|
||||
|
||||
- If the deployment is processing 20 concurrent requests, the deployment will scale up from 1 container to 2 containers (20 requests / 2 containers = 10 requests per container).
|
||||
- If a deployment of 2 containers is processing 10 requests, the deployment will scale down from 2 containers to 1 container (10 requests / 1 container = 10 requests per container).
|
||||
|
||||
10 concurrent requests per container is the target threshold. However, 10 concurrent requests per container is not a hard limit. The number of concurrent requests can exceed 10 if there is a sudden burst of requests.
|
||||
|
||||
Scale down actions are delayed for 30 minutes before any action is taken. In other words, if the autoscaling implementation decides to scale down a deployment, it will first wait for 30 minutes before scaling down. After 30 minutes, the concurrency metric is recomputed and the deployment will scale down if the concurrency metric has met the target threshold. Otherwise, the deployment remains scaled up. This "cool down" period ensures that deployments do not scale up and down too frequently.
|
||||
|
||||
In the future, the autoscaling implementation may evolve to accommodate other metrics such as background run queue size.
|
||||
|
||||
### Static IP Addresses
|
||||
|
||||
!!! info "Only for Cloud SaaS"
|
||||
Static IP addresses are only available for [Cloud SaaS](../concepts/langgraph_cloud.md).
|
||||
|
||||
All traffic from deployments created after January 6th 2025 will come through a NAT gateway. This NAT gateway will have several static IP addresses depending on the data region. Refer to the table below for the list of static IP addresses:
|
||||
|
||||
| US | EU |
|
||||
|----------------|----------------|
|
||||
| 35.197.29.146 | 34.13.192.67 |
|
||||
| 34.145.102.123 | 34.147.105.64 |
|
||||
| 34.169.45.153 | 34.90.22.166 |
|
||||
| 34.82.222.17 | 34.147.36.213 |
|
||||
| 35.227.171.135 | 34.32.137.113 |
|
||||
| 34.169.88.30 | 34.91.238.184 |
|
||||
| 34.19.93.202 | 35.204.101.241 |
|
||||
| 34.19.34.50 | 35.204.48.32 |
|
||||
@@ -1,3 +1,8 @@
|
||||
---
|
||||
search:
|
||||
boost: 2
|
||||
---
|
||||
|
||||
# LangGraph Platform
|
||||
|
||||
## Overview
|
||||
@@ -11,6 +16,8 @@ The LangGraph Platform consists of several components that work together to supp
|
||||
- [LangGraph CLI](./langgraph_cli.md): LangGraph CLI is a command-line interface that helps to interact with a local LangGraph
|
||||
- [Python/JS SDK](./sdk.md): The Python/JS SDK provides a programmatic way to interact with deployed LangGraph Applications.
|
||||
- [Remote Graph](../how-tos/use-remote-graph.md): A RemoteGraph allows you to interact with any deployed LangGraph application as though it were running locally.
|
||||
- [LangGraph Control Plane](./langgraph_control_plane.md): The LangGraph Control Plane refers to the Control Plane UI where users create and update LangGraph Servers and the Control Plane APIs that support the UI experience.
|
||||
- [LangGraph Data Plane](./langgraph_data_plane.md): The LangGraph Data Plane refers to LangGraph Servers, the corresponding infrastructure for each server, and the "listener" application that continuously polls for updates from the LangGraph Control Plane.
|
||||
|
||||

|
||||
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
# Self-Hosted Control Plane
|
||||
|
||||
To deploy a [LangGraph Server](../concepts/langgraph_server.md), follow the how-to guide for [how to deploy the Self-Hosted Control Plane](../cloud/deployment/self_hosted_control_plane.md).
|
||||
|
||||
## Overview
|
||||
|
||||
The Self-Hosted Control Plane deployment option is a fully self-hosted model for deployment where you manage the [control plane](./langgraph_control_plane.md) and [data plane](./langgraph_data_plane.md) in your cloud (this option implies that the data plane is self-hosted).
|
||||
|
||||
| | [Control Plane](../concepts/langgraph_control_plane.md) | [Data Plane](../concepts/langgraph_data_plane.md) |
|
||||
|-------------------|-------------------|------------|
|
||||
| **What is it?** | <ul><li>Control Plane UI for creating deployments and revisions</li><li>Control Plane APIs for creating deployments and revisions</li></ul> | <ul><li>Data plane "listener" for reconciling deployments with control plane state</li><li>LangGraph Servers</li><li>Postgres, Redis, etc</li></ul> |
|
||||
| **Where is it hosted?** | Your cloud | Your cloud |
|
||||
| **Who provisions and manages it?** | You | You |
|
||||
|
||||
## Architecture
|
||||
|
||||

|
||||
|
||||
## Compute Platforms
|
||||
|
||||
### Kubernetes
|
||||
|
||||
The Self-Hosted Control Plane deployment option supports deploying control plane and data plane infrastructure to any Kubernetes cluster.
|
||||
@@ -0,0 +1,27 @@
|
||||
# Self-Hosted Data Plane
|
||||
|
||||
To deploy a [LangGraph Server](../concepts/langgraph_server.md), follow the how-to guide for [how to deploy the Self-Hosted Data Plane](../cloud/deployment/self_hosted_data_plane.md).
|
||||
|
||||
## Overview
|
||||
|
||||
LangGraph Platform's Self-Hosted Data Plane deployment option is a "hybrid" model for deployemnt where we manage the [control plane](./langgraph_control_plane.md) in our cloud and you manage the [data plane](./langgraph_data_plane.md) in your cloud.
|
||||
|
||||
| | [Control Plane](../concepts/langgraph_control_plane.md) | [Data Plane](../concepts/langgraph_data_plane.md) |
|
||||
|-------------------|-------------------|------------|
|
||||
| **What is it?** | <ul><li>Control Plane UI for creating deployments and revisions</li><li>Control Plane APIs for creating deployments and revisions</li></ul> | <ul><li>Data plane "listener" for reconciling deployments with control plane state</li><li>LangGraph Servers</li><li>Postgres, Redis, etc</li></ul> |
|
||||
| **Where is it hosted?** | LangChain's cloud | Your cloud |
|
||||
| **Who provisions and manages it?** | LangChain | You |
|
||||
|
||||
## Architecture
|
||||
|
||||

|
||||
|
||||
## 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.
|
||||
@@ -7,7 +7,7 @@
|
||||
|
||||
LangGraph Studio offers a new way to develop LLM applications by providing a specialized agent IDE that enables visualization, interaction, and debugging of complex agentic applications.
|
||||
|
||||
With visual graphs and the ability to edit state, you can better understand agent workflows and iterate faster. LangGraph Studio integrates with LangSmith allowing you to collaborate with teammates to debug failure modes.
|
||||
With visual graphs and the ability to edit state, you can better understand agent workflows and iterate faster. LangGraph Studio integrates with LangSmith allowing you to collaborate with teammates to debug failure modes.
|
||||
|
||||

|
||||
|
||||
@@ -15,7 +15,7 @@ With visual graphs and the ability to edit state, you can better understand agen
|
||||
|
||||
The key features of LangGraph Studio are:
|
||||
|
||||
- Visualizes your graph
|
||||
- Visualize your graphs
|
||||
- Test your graph by running it from the UI
|
||||
- Debug your agent by [modifying its state and rerunning](human_in_the_loop.md)
|
||||
- Create and manage [assistants](assistants.md)
|
||||
@@ -23,86 +23,54 @@ The key features of LangGraph Studio are:
|
||||
- View and manage [long term memory](memory.md)
|
||||
- Add node input/outputs to [LangSmith](https://smith.langchain.com/) datasets for testing
|
||||
|
||||
## Types
|
||||
## Getting started
|
||||
|
||||
### Development server with web UI
|
||||
There are two ways to connect your LangGraph app with the studio:
|
||||
|
||||
You can [run a local in-memory development server](../tutorials/langgraph-platform/local-server.md) that can be used to connect a local LangGraph app with a web version of the studio.
|
||||
For example, if you start the local server with `langgraph dev` (running at `http://127.0.0.1:2024` by default), you can connect to the studio by navigating to:
|
||||
### Deployed Application
|
||||
|
||||
If you have deployed your LangGraph application on LangGraph Platform, you can access the studio as part of that deployment. To do so, navigate to the deployment in LangGraph Platform within the LangSmith UI and click the "LangGraph Studio" button.
|
||||
|
||||
### Local Development Server
|
||||
|
||||
If you have a LangGraph application that is [running locally in-memory](../tutorials/langgraph-platform/local-server.md), you can connect it to LangGraph Studio in the browser within LangSmith.
|
||||
|
||||
By default, starting the local server with `langgraph dev` will run the server at `http://127.0.0.1:2024` and automatically open Studio in your browser. However, you can also manually connect to Studio by either:
|
||||
|
||||
1. In LangGraph Platform, clicking the "LangGraph Studio" button and entering the server URL in the dialog that appears.
|
||||
|
||||
or
|
||||
|
||||
2. Navigating to the URL in your browser:
|
||||
|
||||
```
|
||||
https://smith.langchain.com/studio/?baseUrl=http://127.0.0.1:2024
|
||||
```
|
||||
|
||||
See [instructions here](../cloud/reference/cli.md#dev) for more information.
|
||||
## Related
|
||||
|
||||
The web UI version of the studio will connect to your locally running server — your agent is still running locally and never leaves your device.
|
||||
For more information please see the following:
|
||||
|
||||
### Cloud studio
|
||||
- [LangGraph Studio how-to guides](../how-tos/index.md#langgraph-studio)
|
||||
- [LangGraph CLI Documentation](../cloud/reference/cli.md)
|
||||
|
||||
If you have deployed your LangGraph application on LangGraph Platform (Cloud), you can access the studio as part of that
|
||||
|
||||
### Desktop app
|
||||
|
||||
LangGraph Studio is available as a [desktop app](https://studio.langchain.com/) for MacOS users.
|
||||
|
||||
While in Beta, LangGraph Studio is available for free to all [LangSmith](https://smith.langchain.com/) users on any plan tier.
|
||||
|
||||
## Studio FAQs
|
||||
## LangGraph Studio FAQs
|
||||
|
||||
### Why is my project failing to start?
|
||||
|
||||
There are a few reasons that your project might fail to start, here are some of the most common ones.
|
||||
|
||||
#### Docker issues (desktop only)
|
||||
|
||||
LangGraph Studio (desktop) requires Docker Desktop version 4.24 or higher. Please make sure you have a version of Docker installed that satisfies that requirement and also make sure you have the Docker Desktop app up and running before trying to use LangGraph Studio. In addition, make sure you have docker-compose updated to version 2.22.0 or higher.
|
||||
|
||||
#### Configuration or environment issues
|
||||
|
||||
Another reason your project might fail to start is because your configuration file is defined incorrectly, or you are missing required environment variables.
|
||||
|
||||
!!! Important "Note (desktop only)"
|
||||
|
||||
LangGraph Studio Desktop automatically populates `LANGCHAIN_*` environment variables for license verification and tracing, regardless of the contents of the `.env` file. All other environment variables defined in `.env` will be read as normal.
|
||||
|
||||
#### Incorrect data region (desktop only)
|
||||
|
||||
If you receive a license verification error when attempting to start the LangGraph Server, you may be logged into the incorrect LangSmith data region. Ensure that you're logged into the correct LangSmith data region and ensure that the LangSmith account has access to LangGraph platform.
|
||||
|
||||
1. In the top right-hand corner, click the user icon and select `Logout`.
|
||||
1. At the login screen, click the `Data Region` dropdown menu and select the appropriate data region. Then click `Login to LangSmith`.
|
||||
A project may fail to start if the configuration file is defined incorrectly, or if required environment variables are missing. See [here](../cloud/reference/cli.md#configuration-file) for how your configuration file should be defined.
|
||||
|
||||
### How does interrupt work?
|
||||
|
||||
When you select the `Interrupts` dropdown and select a node to interrupt the graph will pause execution before and after (unless the node goes straight to `END`) that node has run. This means that you will be able to both edit the state before the node is ran and the state after the node has ran. This is intended to allow developers more fine-grained control over the behavior of a node and make it easier to observe how the node is behaving. You will not be able to edit the state after the node has ran if the node is the final node in the graph.
|
||||
|
||||
### How do I reload the app? (desktop only)
|
||||
For more information on interrupts and human in the loop, see [here](./human_in_the_loop.md).
|
||||
|
||||
If you would like to reload the app, don't use Command+R as you might normally do. Instead, close and reopen the app for a full refresh.
|
||||
|
||||
### How does automatic rebuilding work? (desktop only)
|
||||
|
||||
One of the key features of LangGraph Studio is that it automatically rebuilds your image when you change the source code. This allows for a super fast development and testing cycle which makes it easy to iterate on your graph. There are two different ways that LangGraph rebuilds your image: either by editing the image or completely rebuilding it.
|
||||
|
||||
#### Rebuilds from source code changes
|
||||
|
||||
If you modified the source code only (no configuration or dependency changes!) then the image does not require a full rebuild, and LangGraph Studio will only update the relevant parts. The UI status in the bottom left will switch from `Online` to `Stopping` temporarily while the image gets edited. The logs will be shown as this process is happening, and after the image has been edited the status will change back to `Online` and you will be able to run your graph with the modified code!
|
||||
|
||||
|
||||
#### Rebuilds from configuration or dependency changes
|
||||
|
||||
If you edit your graph configuration file (`langgraph.json`) or the dependencies (either `pyproject.toml` or `requirements.txt`) then the entire image will be rebuilt. This will cause the UI to switch away from the graph view and start showing the logs of the new image building process. This can take a minute or two, and once it is done your updated image will be ready to use!
|
||||
|
||||
### Why is my graph taking so long to startup? (desktop only)
|
||||
|
||||
The LangGraph Studio interacts with a local LangGraph API server. To stay aligned with ongoing updates, the LangGraph API requires regular rebuilding. As a result, you may occasionally experience slight delays when starting up your project.
|
||||
|
||||
## Why are extra edges showing up in my graph?
|
||||
### Why are extra edges showing up in my graph?
|
||||
|
||||
If you don't define your conditional edges carefully, you might notice extra edges appearing in your graph. This is because without proper definition, LangGraph Studio assumes the conditional edge could access all other nodes. In order for this to not be the case, you need to be explicit about how you define the nodes the conditional edge routes to. There are two ways you can do this:
|
||||
|
||||
### Solution 1: Include a path map
|
||||
#### Solution 1: Include a path map
|
||||
|
||||
The first way to solve this is to add path maps to your conditional edges. A path map is just a dictionary or array that maps the possible outputs of your router function with the names of the nodes that each output corresponds to. The path map is passed as the third argument to the `add_conditional_edges` function like so:
|
||||
|
||||
@@ -120,7 +88,7 @@ The first way to solve this is to add path maps to your conditional edges. A pat
|
||||
|
||||
In this case, the routing function returns either True or False, which map to `node_b` and `node_c` respectively.
|
||||
|
||||
### Solution 2: Update the typing of the router (Python only)
|
||||
#### Solution 2: Update the typing of the router (Python only)
|
||||
|
||||
Instead of passing a path map, you can also be explicit about the typing of your routing function by specifying the nodes it can map to using the `Literal` python definition. Here is an example of how to define a routing function in that way:
|
||||
|
||||
@@ -132,9 +100,48 @@ def routing_function(state: GraphState) -> Literal["node_b","node_c"]:
|
||||
return "node_c"
|
||||
```
|
||||
|
||||
### Studio Desktop FAQs
|
||||
|
||||
## Related
|
||||
!!! warning "Deprecation Warning"
|
||||
In order to support a wider range of platforms and users, we now recommend following the above instructions to connect to LangGraph Studio using the development server instead of the desktop app.
|
||||
|
||||
For more information please see the following:
|
||||
The LangGraph Studio Desktop App is a standalone application that allows you to connect to your LangGraph application and visualize and interact with your graph. It is available for MacOS only and requires Docker to be installed.
|
||||
|
||||
* [LangGraph Studio how-to guides](../how-tos/index.md#langgraph-studio)
|
||||
#### Why is my project failing to start?
|
||||
|
||||
In addition to the reasons listed above, for the desktop app there are a few more reasons that your project might fail to start:
|
||||
|
||||
!!! Important "Note "
|
||||
|
||||
LangGraph Studio Desktop automatically populates `LANGCHAIN_*` environment variables for license verification and tracing, regardless of the contents of the `.env` file. All other environment variables defined in `.env` will be read as normal.
|
||||
|
||||
##### Docker issues
|
||||
|
||||
LangGraph Studio (desktop) requires Docker Desktop version 4.24 or higher. Please make sure you have a version of Docker installed that satisfies that requirement and also make sure you have the Docker Desktop app up and running before trying to use LangGraph Studio. In addition, make sure you have docker-compose updated to version 2.22.0 or higher.
|
||||
|
||||
##### Incorrect data region
|
||||
|
||||
If you receive a license verification error when attempting to start the LangGraph Server, you may be logged into the incorrect LangSmith data region. Ensure that you're logged into the correct LangSmith data region and ensure that the LangSmith account has access to LangGraph platform.
|
||||
|
||||
1. In the top right-hand corner, click the user icon and select `Logout`.
|
||||
1. At the login screen, click the `Data Region` dropdown menu and select the appropriate data region. Then click `Login to LangSmith`.
|
||||
|
||||
### How do I reload the app?
|
||||
|
||||
If you would like to reload the app, don't use Command+R as you might normally do. Instead, close and reopen the app for a full refresh.
|
||||
|
||||
### How does automatic rebuilding work?
|
||||
|
||||
One of the key features of LangGraph Studio is that it automatically rebuilds your image when you change the source code. This allows for a super fast development and testing cycle which makes it easy to iterate on your graph. There are two different ways that LangGraph rebuilds your image: either by editing the image or completely rebuilding it.
|
||||
|
||||
#### Rebuilds from source code changes
|
||||
|
||||
If you modified the source code only (no configuration or dependency changes!) then the image does not require a full rebuild, and LangGraph Studio will only update the relevant parts. The UI status in the bottom left will switch from `Online` to `Stopping` temporarily while the image gets edited. The logs will be shown as this process is happening, and after the image has been edited the status will change back to `Online` and you will be able to run your graph with the modified code!
|
||||
|
||||
#### Rebuilds from configuration or dependency changes
|
||||
|
||||
If you edit your graph configuration file (`langgraph.json`) or the dependencies (either `pyproject.toml` or `requirements.txt`) then the entire image will be rebuilt. This will cause the UI to switch away from the graph view and start showing the logs of the new image building process. This can take a minute or two, and once it is done your updated image will be ready to use!
|
||||
|
||||
### Why is my graph taking so long to startup?
|
||||
|
||||
The LangGraph Studio interacts with a local LangGraph API server. To stay aligned with ongoing updates, the LangGraph API requires regular rebuilding. As a result, you may occasionally experience slight delays when starting up your project.
|
||||
|
||||
@@ -310,7 +310,7 @@ graph.add_conditional_edges(START, routing_function, {True: "node_b", False: "no
|
||||
|
||||
## `Send`
|
||||
|
||||
By default, `Nodes` and `Edges` are defined ahead of time and operate on the same shared state. However, there can be cases where the exact edges are not known ahead of time and/or you may want different versions of `State` to exist at the same time. A common example of this is with `map-reduce` design patterns. In this design pattern, a first node may generate a list of objects, and you may want to apply some other node to all those objects. The number of objects may be unknown ahead of time (meaning the number of edges may not be known) and the input `State` to the downstream `Node` should be different (one for each generated object).
|
||||
By default, `Nodes` and `Edges` are defined ahead of time and operate on the same shared state. However, there can be cases where the exact edges are not known ahead of time and/or you may want different versions of `State` to exist at the same time. A common example of this is with [map-reduce](https://langchain-ai.github.io/langgraph/how-tos/map-reduce/) design patterns. In this design pattern, a first node may generate a list of objects, and you may want to apply some other node to all those objects. The number of objects may be unknown ahead of time (meaning the number of edges may not be known) and the input `State` to the downstream `Node` should be different (one for each generated object).
|
||||
|
||||
To support this design pattern, LangGraph supports returning [`Send`][langgraph.types.Send] objects from conditional edges. `Send` takes two arguments: first is the name of the node, and second is the state to pass to that node.
|
||||
|
||||
@@ -360,7 +360,7 @@ Use [conditional edges](#conditional-edges) to route between nodes conditionally
|
||||
If you are using [subgraphs](#subgraphs), you might want to navigate from a node within a subgraph to a different subgraph (i.e. a different node in the parent graph). To do so, you can specify `graph=Command.PARENT` in `Command`:
|
||||
|
||||
```python
|
||||
def my_node(state: State) -> Command[Literal["my_other_node"]]:
|
||||
def my_node(state: State) -> Command[Literal["other_subgraph"]]:
|
||||
return Command(
|
||||
update={"foo": "bar"},
|
||||
goto="other_subgraph", # where `other_subgraph` is a node in the parent graph
|
||||
|
||||
@@ -275,7 +275,7 @@ See this how-to [video](https://www.youtube.com/watch?v=37VaU7e7t5o) for example
|
||||
|
||||
[Procedural memory](https://en.wikipedia.org/wiki/Procedural_memory), in both humans and AI agents, involves remembering the rules used to perform tasks. In humans, procedural memory is like the internalized knowledge of how to perform tasks, such as riding a bike via basic motor skills and balance. Episodic memory, on the other hand, involves recalling specific experiences, such as the first time you successfully rode a bike without training wheels or a memorable bike ride through a scenic route. For AI agents, procedural memory is a combination of model weights, agent code, and agent's prompt that collectively determine the agent's functionality.
|
||||
|
||||
In practice, it is fairly uncommon for agents to modify their model weights or rewrite their code. However, it is more common for agents to [modify their own prompts](https://docs.anthropic.com/en/docs/build-with-claude/prompt-engineering/prompt-generator).
|
||||
In practice, it is fairly uncommon for agents to modify their model weights or rewrite their code. However, it is more common for agents to modify their own prompts.
|
||||
|
||||
One effective approach to refining an agent's instructions is through ["Reflection"](https://blog.langchain.dev/reflection-agents/) or meta-prompting. This involves prompting the agent with its current instructions (e.g., the system prompt) along with recent conversations or explicit user feedback. The agent then refines its own instructions based on this input. This method is particularly useful for tasks where instructions are challenging to specify upfront, as it allows the agent to learn and adapt from its interactions.
|
||||
|
||||
|
||||
@@ -50,7 +50,7 @@ def agent(state) -> Command[Literal["agent", "another_agent"]]:
|
||||
In a more complex scenario where each agent node is itself a graph (i.e., a [subgraph](./low_level.md#subgraphs)), a node in one of the agent subgraphs might want to navigate to a different agent. For example, if you have two agents, `alice` and `bob` (subgraph nodes in a parent graph), and `alice` needs to navigate to `bob`, you can set `graph=Command.PARENT` in the `Command` object:
|
||||
|
||||
```python
|
||||
def some_node_inside_alice(state)
|
||||
def some_node_inside_alice(state):
|
||||
return Command(
|
||||
goto="bob",
|
||||
update={"my_state_key": "my_state_value"},
|
||||
@@ -89,7 +89,7 @@ def transfer_to_bob(state):
|
||||
)
|
||||
```
|
||||
|
||||
This is a special case of updating the graph state from tools where in addition the state update, the control flow is included as well.
|
||||
This is a special case of updating the graph state from tools where, in addition to the state update, the control flow is included as well.
|
||||
|
||||
!!! important
|
||||
|
||||
@@ -112,6 +112,7 @@ In this architecture, agents are defined as graph nodes. Each agent can communic
|
||||
```python
|
||||
from typing import Literal
|
||||
from langchain_openai import ChatOpenAI
|
||||
from langgraph.types import Command
|
||||
from langgraph.graph import StateGraph, MessagesState, START, END
|
||||
|
||||
model = ChatOpenAI()
|
||||
@@ -158,6 +159,7 @@ In this architecture, we define agents as nodes and add a supervisor node (LLM)
|
||||
```python
|
||||
from typing import Literal
|
||||
from langchain_openai import ChatOpenAI
|
||||
from langgraph.types import Command
|
||||
from langgraph.graph import StateGraph, MessagesState, START, END
|
||||
|
||||
model = ChatOpenAI()
|
||||
@@ -233,7 +235,7 @@ supervisor = create_react_agent(model, tools)
|
||||
|
||||
### Hierarchical
|
||||
|
||||
As you add more agents to your system, it might become too hard for the supervisor to manage all of them. The supervisor might start making poor decisions about which agent to call next, the context might become too complex for a single supervisor to keep track of. In other words, you end up with the same problems that motivated the multi-agent architecture in the first place.
|
||||
As you add more agents to your system, it might become too hard for the supervisor to manage all of them. The supervisor might start making poor decisions about which agent to call next, or the context might become too complex for a single supervisor to keep track of. In other words, you end up with the same problems that motivated the multi-agent architecture in the first place.
|
||||
|
||||
To address this, you can design your system _hierarchically_. For example, you can create separate, specialized teams of agents managed by individual supervisors, and a top-level supervisor to manage the teams.
|
||||
|
||||
@@ -337,9 +339,9 @@ builder.add_edge("agent_1", "agent_2")
|
||||
|
||||
## Communication between agents
|
||||
|
||||
The most important thing when building multi-agent systems is figuring out how the agents communicate. There are few different considerations:
|
||||
The most important thing when building multi-agent systems is figuring out how the agents communicate. There are a few different considerations:
|
||||
|
||||
- Do agents communicate via [**via graph state or via tool calls**](#graph-state-vs-tool-calls)?
|
||||
- Do agents communicate [**via graph state or via tool calls**](#graph-state-vs-tool-calls)?
|
||||
- What if two agents have [**different state schemas**](#different-state-schemas)?
|
||||
- How to communicate over a [**shared message list**](#shared-message-list)?
|
||||
|
||||
|
||||
@@ -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,13 +30,13 @@ Let's see what checkpoints are saved when a simple graph is invoked as follows:
|
||||
|
||||
```python
|
||||
from langgraph.graph import StateGraph, START, END
|
||||
from langgraph.checkpoint.memory import MemorySaver
|
||||
from langgraph.checkpoint.memory import InMemorySaver
|
||||
from typing import Annotated
|
||||
from typing_extensions import TypedDict
|
||||
from operator import add
|
||||
|
||||
class State(TypedDict):
|
||||
foo: int
|
||||
foo: str
|
||||
bar: Annotated[list[str], add]
|
||||
|
||||
def node_a(state: State):
|
||||
@@ -49,7 +53,7 @@ workflow.add_edge(START, "node_a")
|
||||
workflow.add_edge("node_a", "node_b")
|
||||
workflow.add_edge("node_b", END)
|
||||
|
||||
checkpointer = MemorySaver()
|
||||
checkpointer = InMemorySaver()
|
||||
graph = workflow.compile(checkpointer=checkpointer)
|
||||
|
||||
config = {"configurable": {"thread_id": "1"}}
|
||||
@@ -223,6 +227,10 @@ But, what if we want to retain some information *across threads*? Consider the c
|
||||
|
||||
With checkpointers alone, we cannot share information across threads. This motivates the need for the [`Store`](../reference/store.md#langgraph.store.base.BaseStore) interface. As an illustration, we can define an `InMemoryStore` to store information about a user across threads. We simply compile our graph with a checkpointer, as before, and with our new `in_memory_store` variable.
|
||||
|
||||
!!! info "LangGraph API handles stores automatically"
|
||||
|
||||
When using the LangGraph API, you don't need to implement or configure stores manually. The API handles all storage infrastructure for you behind the scenes.
|
||||
|
||||
### Basic Usage
|
||||
|
||||
First, let's showcase this in isolation without using LangGraph.
|
||||
@@ -232,7 +240,7 @@ from langgraph.store.memory import InMemoryStore
|
||||
in_memory_store = InMemoryStore()
|
||||
```
|
||||
|
||||
Memories are namespaced by a `tuple`, which in this specific example will be `(<user_id>, "memories")`. The namespace can be any length and represent anything, does not have be user specific.
|
||||
Memories are namespaced by a `tuple`, which in this specific example will be `(<user_id>, "memories")`. The namespace can be any length and represent anything, does not have to be user specific.
|
||||
|
||||
```python
|
||||
user_id = "1"
|
||||
@@ -324,10 +332,10 @@ store.put(
|
||||
With this all in place, we use the `in_memory_store` in LangGraph. The `in_memory_store` works hand-in-hand with the checkpointer: the checkpointer saves state to threads, as discussed above, and the `in_memory_store` allows us to store arbitrary information for access *across* threads. We compile the graph with both the checkpointer and the `in_memory_store` as follows.
|
||||
|
||||
```python
|
||||
from langgraph.checkpoint.memory import MemorySaver
|
||||
from langgraph.checkpoint.memory import InMemorySaver
|
||||
|
||||
# We need this because we want to enable threads (conversations)
|
||||
checkpointer = MemorySaver()
|
||||
checkpointer = InMemorySaver()
|
||||
|
||||
# ... Define the graph ...
|
||||
|
||||
@@ -387,6 +395,9 @@ We can access the memories and use them in our model call.
|
||||
def call_model(state: MessagesState, config: RunnableConfig, *, store: BaseStore):
|
||||
# Get the user id from the config
|
||||
user_id = config["configurable"]["user_id"]
|
||||
|
||||
# Namespace the memory
|
||||
namespace = (user_id, "memories")
|
||||
|
||||
# Search based on the most recent message
|
||||
memories = store.search(
|
||||
@@ -437,6 +448,7 @@ Under the hood, checkpointing is powered by checkpointer objects that conform to
|
||||
* `langgraph-checkpoint-sqlite`: An implementation of LangGraph checkpointer that uses SQLite database ([SqliteSaver][langgraph.checkpoint.sqlite.SqliteSaver] / [AsyncSqliteSaver][langgraph.checkpoint.sqlite.aio.AsyncSqliteSaver]). Ideal for experimentation and local workflows. Needs to be installed separately.
|
||||
* `langgraph-checkpoint-postgres`: An advanced checkpointer that uses Postgres database ([PostgresSaver][langgraph.checkpoint.postgres.PostgresSaver] / [AsyncPostgresSaver][langgraph.checkpoint.postgres.aio.AsyncPostgresSaver]), used in LangGraph Cloud. Ideal for using in production. Needs to be installed separately.
|
||||
|
||||
|
||||
### Checkpointer interface
|
||||
|
||||
Each checkpointer conforms to [BaseCheckpointSaver][langgraph.checkpoint.base.BaseCheckpointSaver] interface and implements the following methods:
|
||||
@@ -449,7 +461,7 @@ Each checkpointer conforms to [BaseCheckpointSaver][langgraph.checkpoint.base.Ba
|
||||
If the checkpointer is used with asynchronous graph execution (i.e. executing the graph via `.ainvoke`, `.astream`, `.abatch`), asynchronous versions of the above methods will be used (`.aput`, `.aput_writes`, `.aget_tuple`, `.alist`).
|
||||
|
||||
!!! note Note
|
||||
For running your graph asynchronously, you can use `MemorySaver`, or async versions of Sqlite/Postgres checkpointers -- `AsyncSqliteSaver` / `AsyncPostgresSaver` checkpointers.
|
||||
For running your graph asynchronously, you can use `InMemorySaver`, or async versions of Sqlite/Postgres checkpointers -- `AsyncSqliteSaver` / `AsyncPostgresSaver` checkpointers.
|
||||
|
||||
### Serializer
|
||||
|
||||
|
||||
@@ -0,0 +1,347 @@
|
||||
# LangGraph's Runtime (Pregel)
|
||||
|
||||
[Pregel][langgraph.pregel.Pregel] implements LangGraph's runtime, managing the execution of LangGraph applications.
|
||||
|
||||
Compiling a [StateGraph][langgraph.graph.StateGraph] or creating an [entrypoint][langgraph.func.entrypoint] produces a [Pregel][langgraph.pregel.Pregel] instance that can be invoked with input.
|
||||
|
||||
This guide explains the runtime at a high level and provides instructions for directly implementing applications with Pregel.
|
||||
|
||||
> **Note:** The [Pregel][langgraph.pregel.Pregel] runtime is named after [Google's Pregel algorithm](https://research.google/pubs/pub37252/), which describes an efficient method for large-scale parallel computation using graphs.
|
||||
|
||||
## Overview
|
||||
|
||||
In LangGraph, Pregel combines [**actors**](https://en.wikipedia.org/wiki/Actor_model) and **channels** into a single application. **Actors** read data from channels and write data to channels. Pregel organizes the execution of the application into multiple steps, following the **Pregel Algorithm**/**Bulk Synchronous Parallel** model.
|
||||
|
||||
Each step consists of three phases:
|
||||
|
||||
- **Plan**: Determine which **actors** to execute in this step. For example, in the first step, select the **actors** that subscribe to the special **input** channels; in subsequent steps, select the **actors** that subscribe to channels updated in the previous step.
|
||||
- **Execution**: Execute all selected **actors** in parallel, until all complete, or one fails, or a timeout is reached. During this phase, channel updates are invisible to actors until the next step.
|
||||
- **Update**: Update the channels with the values written by the **actors** in this step.
|
||||
|
||||
Repeat until no **actors** are selected for execution, or a maximum number of steps is reached.
|
||||
|
||||
## Actors
|
||||
|
||||
An **actor** is a [PregelNode][langgraph.pregel.read.PregelNode]. It subscribes to channels, reads data from them, and writes data to them. It can be thought of as an **actor** in the Pregel algorithm. [PregelNodes][langgraph.pregel.read.PregelNode] implement LangChain's Runnable interface.
|
||||
|
||||
## Channels
|
||||
|
||||
Channels are used to communicate between actors (PregelNodes). Each channel has a value type, an update type, and an update function – which takes a sequence of updates and modifies the stored value. Channels can be used to send data from one chain to another, or to send data from a chain to itself in a future step. LangGraph provides a number of built-in channels:
|
||||
|
||||
### Basic channels: LastValue and Topic
|
||||
|
||||
- [LastValue][langgraph.channels.LastValue]: The default channel, stores the last value sent to the channel, useful for input and output values, or for sending data from one step to the next.
|
||||
- [Topic][langgraph.channels.Topic]: A configurable PubSub Topic, useful for sending multiple values between **actors**, or for accumulating output. Can be configured to deduplicate values or to accumulate values over the course of multiple steps.
|
||||
|
||||
### Advanced channels: Context and BinaryOperatorAggregate
|
||||
|
||||
- `Context`: exposes the value of a context manager, managing its lifecycle. Useful for accessing external resources that require setup and/or teardown; e.g., `client = Context(httpx.Client)`.
|
||||
- [BinaryOperatorAggregate][langgraph.channels.BinaryOperatorAggregate]: stores a persistent value, updated by applying a binary operator to the current value and each update sent to the channel, useful for computing aggregates over multiple steps; e.g.,`total = BinaryOperatorAggregate(int, operator.add)`
|
||||
|
||||
## Examples
|
||||
|
||||
While most users will interact with Pregel through the [StateGraph][langgraph.graph.StateGraph] API or
|
||||
the [entrypoint][langgraph.func.entrypoint] decorator, it is possible to interact with Pregel directly.
|
||||
|
||||
Below are a few different examples to give you a sense of the Pregel API.
|
||||
|
||||
=== "Single node"
|
||||
|
||||
```python
|
||||
|
||||
from langgraph.channels import EphemeralValue
|
||||
from langgraph.pregel import Pregel, Channel
|
||||
|
||||
node1 = (
|
||||
Channel.subscribe_to("a")
|
||||
| (lambda x: x + x)
|
||||
| Channel.write_to("b")
|
||||
)
|
||||
|
||||
app = Pregel(
|
||||
nodes={"node1": node1},
|
||||
channels={
|
||||
"a": EphemeralValue(str),
|
||||
"b": EphemeralValue(str),
|
||||
},
|
||||
input_channels=["a"],
|
||||
output_channels=["b"],
|
||||
)
|
||||
|
||||
app.invoke({"a": "foo"})
|
||||
```
|
||||
|
||||
```con
|
||||
{'b': 'foofoo'}
|
||||
```
|
||||
|
||||
=== "Multiple nodes"
|
||||
|
||||
```python
|
||||
from langgraph.channels import LastValue, EphemeralValue
|
||||
from langgraph.pregel import Pregel, Channel
|
||||
|
||||
node1 = (
|
||||
Channel.subscribe_to("a")
|
||||
| (lambda x: x + x)
|
||||
| Channel.write_to("b")
|
||||
)
|
||||
|
||||
node2 = (
|
||||
Channel.subscribe_to("b")
|
||||
| (lambda x: x + x)
|
||||
| Channel.write_to("c")
|
||||
)
|
||||
|
||||
|
||||
app = Pregel(
|
||||
nodes={"node1": node1, "node2": node2},
|
||||
channels={
|
||||
"a": EphemeralValue(str),
|
||||
"b": LastValue(str),
|
||||
"c": EphemeralValue(str),
|
||||
},
|
||||
input_channels=["a"],
|
||||
output_channels=["b", "c"],
|
||||
)
|
||||
|
||||
app.invoke({"a": "foo"})
|
||||
```
|
||||
|
||||
```con
|
||||
{'b': 'foofoo', 'c': 'foofoofoofoo'}
|
||||
```
|
||||
|
||||
=== "Topic"
|
||||
|
||||
```python
|
||||
from langgraph.channels import EphemeralValue, Topic
|
||||
from langgraph.pregel import Pregel, Channel
|
||||
|
||||
node1 = (
|
||||
Channel.subscribe_to("a")
|
||||
| (lambda x: x + x)
|
||||
| {
|
||||
"b": Channel.write_to("b"),
|
||||
"c": Channel.write_to("c")
|
||||
}
|
||||
)
|
||||
|
||||
node2 = (
|
||||
Channel.subscribe_to("b")
|
||||
| (lambda x: x + x)
|
||||
| {
|
||||
"c": Channel.write_to("c"),
|
||||
}
|
||||
)
|
||||
|
||||
app = Pregel(
|
||||
nodes={"node1": node1, "node2": node2},
|
||||
channels={
|
||||
"a": EphemeralValue(str),
|
||||
"b": EphemeralValue(str),
|
||||
"c": Topic(str, accumulate=True),
|
||||
},
|
||||
input_channels=["a"],
|
||||
output_channels=["c"],
|
||||
)
|
||||
|
||||
app.invoke({"a": "foo"})
|
||||
```
|
||||
|
||||
```pycon
|
||||
{'c': ['foofoo', 'foofoofoofoo']}
|
||||
```
|
||||
|
||||
=== "BinaryOperatorAggregate"
|
||||
|
||||
This examples demonstrates how to use the BinaryOperatorAggregate channel to implement a reducer.
|
||||
|
||||
```python
|
||||
from langgraph.channels import EphemeralValue, BinaryOperatorAggregate
|
||||
from langgraph.pregel import Pregel, Channel
|
||||
|
||||
|
||||
node1 = (
|
||||
Channel.subscribe_to("a")
|
||||
| (lambda x: x + x)
|
||||
| {
|
||||
"b": Channel.write_to("b"),
|
||||
"c": Channel.write_to("c")
|
||||
}
|
||||
)
|
||||
|
||||
node2 = (
|
||||
Channel.subscribe_to("b")
|
||||
| (lambda x: x + x)
|
||||
| {
|
||||
"c": Channel.write_to("c"),
|
||||
}
|
||||
)
|
||||
|
||||
def reducer(current, update):
|
||||
if current:
|
||||
return current + " | " + "update"
|
||||
else:
|
||||
return update
|
||||
|
||||
app = Pregel(
|
||||
nodes={"node1": node1, "node2": node2},
|
||||
channels={
|
||||
"a": EphemeralValue(str),
|
||||
"b": EphemeralValue(str),
|
||||
"c": BinaryOperatorAggregate(str, operator=reducer),
|
||||
},
|
||||
input_channels=["a"],
|
||||
output_channels=["c"],
|
||||
)
|
||||
|
||||
app.invoke({"a": "foo"})
|
||||
```
|
||||
|
||||
|
||||
=== "Cycle"
|
||||
|
||||
This example demonstrates how to introduce a cycle in the graph, by having
|
||||
a chain write to a channel it subscribes to. Execution will continue
|
||||
until a None value is written to the channel.
|
||||
|
||||
```python
|
||||
from langgraph.channels import EphemeralValue
|
||||
from langgraph.pregel import Pregel, Channel, ChannelWrite, ChannelWriteEntry
|
||||
|
||||
example_node = (
|
||||
Channel.subscribe_to("value")
|
||||
| (lambda x: x + x if len(x) < 10 else None)
|
||||
| ChannelWrite(writes=[ChannelWriteEntry(channel="value", skip_none=True)])
|
||||
)
|
||||
|
||||
app = Pregel(
|
||||
nodes={"example_node": example_node},
|
||||
channels={
|
||||
"value": EphemeralValue(str),
|
||||
},
|
||||
input_channels=["value"],
|
||||
output_channels=["value"],
|
||||
)
|
||||
|
||||
app.invoke({"value": "a"})
|
||||
```
|
||||
|
||||
```pycon
|
||||
{'value': 'aaaaaaaaaaaaaaaa'}
|
||||
```
|
||||
|
||||
## High-level API
|
||||
|
||||
LangGraph provides two high-level APIs for creating a Pregel application: the [StateGraph (Graph API)](./low_level.md) and the [Functional API](functional_api.md).
|
||||
|
||||
|
||||
=== "StateGraph (Graph API)"
|
||||
|
||||
The [StateGraph (Graph API)][langgraph.graph.StateGraph] is a higher-level abstraction that simplifies the creation of Pregel applications. It allows you to define a graph of nodes and edges. When you compile the graph, the StateGraph API automatically creates the Pregel application for you.
|
||||
|
||||
```python
|
||||
from typing import TypedDict, Optional
|
||||
|
||||
from langgraph.constants import START
|
||||
from langgraph.graph import StateGraph
|
||||
|
||||
class Essay(TypedDict):
|
||||
topic: str
|
||||
content: Optional[str]
|
||||
score: Optional[float]
|
||||
|
||||
def write_essay(essay: Essay):
|
||||
return {
|
||||
"content": f"Essay about {essay['topic']}",
|
||||
}
|
||||
|
||||
def score_essay(essay: Essay):
|
||||
return {
|
||||
"score": 10
|
||||
}
|
||||
|
||||
builder = StateGraph(Essay)
|
||||
builder.add_node(write_essay)
|
||||
builder.add_node(score_essay)
|
||||
builder.add_edge(START, "write_essay")
|
||||
|
||||
# Compile the graph.
|
||||
# This will return a Pregel instance.
|
||||
graph = builder.compile()
|
||||
```
|
||||
|
||||
The compiled Pregel instance will be associated with a list of nodes and channels. You can inspect the nodes and channels by printing them.
|
||||
|
||||
```python
|
||||
print(graph.nodes)
|
||||
```
|
||||
|
||||
You will see something like this:
|
||||
|
||||
```pycon
|
||||
{'__start__': <langgraph.pregel.read.PregelNode at 0x7d05e3ba1810>,
|
||||
'write_essay': <langgraph.pregel.read.PregelNode at 0x7d05e3ba14d0>,
|
||||
'score_essay': <langgraph.pregel.read.PregelNode at 0x7d05e3ba1710>}
|
||||
```
|
||||
|
||||
```python
|
||||
print(graph.channels)
|
||||
```
|
||||
|
||||
You should see something like this
|
||||
|
||||
```pycon
|
||||
{'topic': <langgraph.channels.last_value.LastValue at 0x7d05e3294d80>,
|
||||
'content': <langgraph.channels.last_value.LastValue at 0x7d05e3295040>,
|
||||
'score': <langgraph.channels.last_value.LastValue at 0x7d05e3295980>,
|
||||
'__start__': <langgraph.channels.ephemeral_value.EphemeralValue at 0x7d05e3297e00>,
|
||||
'write_essay': <langgraph.channels.ephemeral_value.EphemeralValue at 0x7d05e32960c0>,
|
||||
'score_essay': <langgraph.channels.ephemeral_value.EphemeralValue at 0x7d05e2d8ab80>,
|
||||
'branch:__start__:__self__:write_essay': <langgraph.channels.ephemeral_value.EphemeralValue at 0x7d05e32941c0>,
|
||||
'branch:__start__:__self__:score_essay': <langgraph.channels.ephemeral_value.EphemeralValue at 0x7d05e2d88800>,
|
||||
'branch:write_essay:__self__:write_essay': <langgraph.channels.ephemeral_value.EphemeralValue at 0x7d05e3295ec0>,
|
||||
'branch:write_essay:__self__:score_essay': <langgraph.channels.ephemeral_value.EphemeralValue at 0x7d05e2d8ac00>,
|
||||
'branch:score_essay:__self__:write_essay': <langgraph.channels.ephemeral_value.EphemeralValue at 0x7d05e2d89700>,
|
||||
'branch:score_essay:__self__:score_essay': <langgraph.channels.ephemeral_value.EphemeralValue at 0x7d05e2d8b400>,
|
||||
'start:write_essay': <langgraph.channels.ephemeral_value.EphemeralValue at 0x7d05e2d8b280>}
|
||||
```
|
||||
|
||||
=== "Functional API"
|
||||
|
||||
In the [Functional API](functional_api.md), you can use an [`entrypoint`][langgraph.func.entrypoint] to create
|
||||
a Pregel application. The `entrypoint` decorator allows you to define a function that takes input and returns output.
|
||||
|
||||
```python
|
||||
from typing import TypedDict, Optional
|
||||
|
||||
from langgraph.checkpoint.memory import InMemorySaver
|
||||
from langgraph.func import entrypoint
|
||||
|
||||
class Essay(TypedDict):
|
||||
topic: str
|
||||
content: Optional[str]
|
||||
score: Optional[float]
|
||||
|
||||
|
||||
checkpointer = InMemorySaver()
|
||||
|
||||
@entrypoint(checkpointer=checkpointer)
|
||||
def write_essay(essay: Essay):
|
||||
return {
|
||||
"content": f"Essay about {essay['topic']}",
|
||||
}
|
||||
|
||||
print("Nodes: ")
|
||||
print(write_essay.nodes)
|
||||
print("Channels: ")
|
||||
print(write_essay.channels)
|
||||
```
|
||||
|
||||
```pycon
|
||||
Nodes:
|
||||
{'write_essay': <langgraph.pregel.read.PregelNode object at 0x7d05e2f9aad0>}
|
||||
Channels:
|
||||
{'__start__': <langgraph.channels.ephemeral_value.EphemeralValue object at 0x7d05e2c906c0>, '__end__': <langgraph.channels.last_value.LastValue object at 0x7d05e2c90c40>, '__previous__': <langgraph.channels.last_value.LastValue object at 0x7d05e1007280>}
|
||||
```
|
||||
@@ -0,0 +1,35 @@
|
||||
# LangGraph Platform: Scalability & Resilience
|
||||
|
||||
LangGraph Platform is designed to scale horizontally with your workload. Each instance of the service is stateless, and keeps no resources in memory. The service is designed to gracefully handle new instances being added or removed, including hard shutdown cases.
|
||||
|
||||
## Server scalability
|
||||
|
||||
As you add more instances to a service, they will share the HTTP load as long as an appropriate load balancer mechanism is placed in front of them. In most deployment modalities we configure a load balancer for the service automatically. In the “self-hosted without control plane” modality it’s your responsibility to add a load balancer. Since the instances are stateless any load balancing strategy will work, no session stickiness is needed, or recommended. Any instance of the server can communicate with any queue instance (through Redis PubSub), meaning that requests to cancel or stream an in-progress run can be handled by any arbitrary instance.
|
||||
|
||||
## Queue scalability
|
||||
|
||||
As you add more instances to a service, they will increase run throughput linearly, as each instance is configured to handle a set number of concurrent runs (by default 10). Each attempt for each run will be handled by a single instance, with exactly-once semantics enforced through Postgres’s MVCC model (refer to section below for crash resilience details). Attempts that fail due to transient database errors are retried up to 3 times. We do not make use of long-lived transactions or locks, this enables us to make more efficient use of Postgres resources.
|
||||
|
||||
## Resilience
|
||||
|
||||
While a run is being handled by a queue instance, a periodic heartbeat timestamp will be recorded in Redis by that queue worker.
|
||||
|
||||
When a graceful shutdown request is received (SIGINT) an instance enters shutdown mode, which
|
||||
|
||||
- stops accepting new HTTP requests
|
||||
- gives any in-progress runs a limited number of seconds to finish (if not finished it will be put back in the queue)
|
||||
- stops the instance from picking up more runs from the queue
|
||||
|
||||
If a hard shutdown occurs, eg. due to a server crash, or an infra failure, any runs that were in progress will be picked up by a periodic sweeper task that looks for in-progress runs that have breached their heartbeat window, which will put them back in the queue for another instance to pick them up.
|
||||
|
||||
## Postgres resilience
|
||||
|
||||
For deployment modalities where we manage the Postgres database we have periodic backups, continuously replicated standby replicas for automatic failover. Optionally, on request, we can also setup read replicas as well as other advanced failover capabilities.
|
||||
|
||||
All communication with Postgres implements retries for retry-able errors. If Postgres is momentarily unavailable, such as during a database restart, most/all traffic should continue to succeed. Prolonged failure of the Postgres instance will switch traffic to the failover replica. If the failover replica also fails before the primary is brought back online the service would become unavailable.
|
||||
|
||||
## Redis resilience
|
||||
|
||||
All data that requires durable storage is stored in Postgres, not Redis. Redis is used only for ephemeral metadata, and communication between instances. Refer to the [architecture](./platform_architecture.md) page for more details on how we use Redis. Therefore we place no durability requirements on Redis.
|
||||
|
||||
All communication with Redis implements retries for retry-able errors. If Redis is momentarily unavailable, such as during a database restart, most/all traffic should continue to succeed. Prolonged failure of Redis will render the LGP service unavailable.
|
||||
@@ -1,3 +1,8 @@
|
||||
---
|
||||
search:
|
||||
exclude: true
|
||||
---
|
||||
|
||||
# Human-in-the-loop
|
||||
|
||||
!!! note "Use the `interrupt` function instead."
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -33,7 +33,7 @@
|
||||
" )\n",
|
||||
"```\n",
|
||||
"\n",
|
||||
"If you are using [subgraphs](#subgraphs), you might want to navigate from a node a subgraph to a different subgraph (i.e. a different node in the parent graph). To do so, you can specify `graph=Command.PARENT` in `Command`:\n",
|
||||
"If you are using [subgraphs](#subgraphs), you might want to navigate from a node within a subgraph to a different subgraph (i.e. a different node in the parent graph). To do so, you can specify `graph=Command.PARENT` in `Command`:\n",
|
||||
"\n",
|
||||
"```python\n",
|
||||
"def my_node(state: State) -> Command[Literal[\"my_other_node\"]]:\n",
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -122,20 +122,18 @@
|
||||
"\n",
|
||||
"# For this tutorial we will use custom tool that returns pre-defined values for weather in two cities (NYC & SF)\n",
|
||||
"\n",
|
||||
"from typing import Literal\n",
|
||||
"\n",
|
||||
"from langchain_core.tools import tool\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"@tool\n",
|
||||
"def get_weather(city: Literal[\"nyc\", \"sf\"]):\n",
|
||||
"def get_weather(location: str) -> str:\n",
|
||||
" \"\"\"Use this to get weather information.\"\"\"\n",
|
||||
" if city == \"nyc\":\n",
|
||||
" if any([city in location.lower() for city in [\"nyc\", \"new york city\"]]):\n",
|
||||
" return \"It might be cloudy in nyc\"\n",
|
||||
" elif city == \"sf\":\n",
|
||||
" elif any([city in location.lower() for city in [\"sf\", \"san francisco\"]]):\n",
|
||||
" return \"It's always sunny in sf\"\n",
|
||||
" else:\n",
|
||||
" raise AssertionError(\"Unknown city\")\n",
|
||||
" return f\"I am not sure what the weather is in {location}\"\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"tools = [get_weather]\n",
|
||||
@@ -220,7 +218,7 @@
|
||||
"id": "838a043f-90ad-4e69-9d1d-6e22db2c346c",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"Notice that when we pass the same the same thread ID, the chat history is preserved"
|
||||
"Notice that when we pass the same thread ID, the chat history is preserved."
|
||||
]
|
||||
},
|
||||
{
|
||||
|
||||
@@ -0,0 +1,82 @@
|
||||
# How to add custom lifespan events
|
||||
|
||||
When deploying agents on the LangGraph platform, you often need to initialize resources like database connections when your server starts up, and ensure they're properly closed when it shuts down. Lifespan events let you hook into your server's startup and shutdown sequence to handle these critical setup and teardown tasks.
|
||||
|
||||
This works the same way as [adding custom routes](./custom_routes.md) - you just need to provide your own [`Starlette`](https://www.starlette.io/applications/) app (including [`FastAPI`](https://fastapi.tiangolo.com/), [`FastHTML`](https://fastht.ml/) and other compatible apps).
|
||||
|
||||
Below is an example using FastAPI.
|
||||
|
||||
???+ note "Python only"
|
||||
|
||||
We currently only support custom lifespan events in Python deployments with `langgraph-api>=0.0.26`.
|
||||
|
||||
## Create app
|
||||
|
||||
Starting from an **existing** LangGraph Platform application, add the following lifespan code to your `webapp.py` file. If you are starting from scratch, you can create a new app from a template using the CLI.
|
||||
|
||||
```bash
|
||||
langgraph new --template=new-langgraph-project-python my_new_project
|
||||
```
|
||||
|
||||
Once you have a LangGraph project, add the following app code:
|
||||
|
||||
```python
|
||||
# ./src/agent/webapp.py
|
||||
from contextlib import asynccontextmanager
|
||||
from fastapi import FastAPI
|
||||
from sqlalchemy.ext.asyncio import create_async_engine, AsyncSession
|
||||
from sqlalchemy.orm import sessionmaker
|
||||
|
||||
@asynccontextmanager
|
||||
async def lifespan(app: FastAPI):
|
||||
# for example...
|
||||
engine = create_async_engine("postgresql+asyncpg://user:pass@localhost/db")
|
||||
# Create reusable session factory
|
||||
async_session = sessionmaker(engine, class_=AsyncSession)
|
||||
# Store in app state
|
||||
app.state.db_session = async_session
|
||||
yield
|
||||
# Clean up connections
|
||||
await engine.dispose()
|
||||
|
||||
# highlight-next-line
|
||||
app = FastAPI(lifespan=lifespan)
|
||||
|
||||
# ... can add custom routes if needed.
|
||||
```
|
||||
|
||||
## Configure `langgraph.json`
|
||||
|
||||
Add the following to your `langgraph.json` file. Make sure the path points to the `webapp.py` file you created above.
|
||||
|
||||
```json
|
||||
{
|
||||
"dependencies": ["."],
|
||||
"graphs": {
|
||||
"agent": "./src/agent/graph.py:graph"
|
||||
},
|
||||
"env": ".env",
|
||||
"http": {
|
||||
"app": "./src/agent/webapp.py:app"
|
||||
}
|
||||
// Other configuration options like auth, store, etc.
|
||||
}
|
||||
```
|
||||
|
||||
## Start server
|
||||
|
||||
Test the server out locally:
|
||||
|
||||
```bash
|
||||
langgraph dev --no-browser
|
||||
```
|
||||
|
||||
You should see your startup message printed when the server starts, and your cleanup message when you stop it with Ctrl+C.
|
||||
|
||||
## Deploying
|
||||
|
||||
You can deploy your app as-is to the managed langgraph cloud or to your self-hosted platform.
|
||||
|
||||
## Next steps
|
||||
|
||||
Now that you've added lifespan events to your deployment, you can use similar techniques to add [custom routes](./custom_routes.md) or [custom middleware](./custom_middleware.md) to further customize your server's behavior.
|
||||
@@ -0,0 +1,75 @@
|
||||
# How to add custom middleware
|
||||
|
||||
When deploying agents on the LangGraph platform, you can add custom middleware to your server to handle cross-cutting concerns like logging request metrics, injecting or checking headers, and enforcing security policies without modifying core server logic. This works the same way as [adding custom routes](./custom_routes.md) - you just need to provide your own [`Starlette`](https://www.starlette.io/applications/) app (including [`FastAPI`](https://fastapi.tiangolo.com/), [`FastHTML`](https://fastht.ml/) and other compatible apps).
|
||||
|
||||
Adding middleware lets you intercept and modify requests and responses globally across your deployment, whether they're hitting your custom endpoints or the built-in LangGraph Platform APIs.
|
||||
|
||||
Below is an example using FastAPI.
|
||||
|
||||
???+ note "Python only"
|
||||
|
||||
We currently only support custom middleware in Python deployments with `langgraph-api>=0.0.26`.
|
||||
|
||||
## Create app
|
||||
|
||||
Starting from an **existing** LangGraph Platform application, add the following middleware code to your `webapp.py` file. If you are starting from scratch, you can create a new app from a template using the CLI.
|
||||
|
||||
```bash
|
||||
langgraph new --template=new-langgraph-project-python my_new_project
|
||||
```
|
||||
|
||||
Once you have a LangGraph project, add the following app code:
|
||||
|
||||
```python
|
||||
# ./src/agent/webapp.py
|
||||
from fastapi import FastAPI, Request
|
||||
from starlette.middleware.base import BaseHTTPMiddleware
|
||||
|
||||
# highlight-next-line
|
||||
app = FastAPI()
|
||||
|
||||
class CustomHeaderMiddleware(BaseHTTPMiddleware):
|
||||
async def dispatch(self, request: Request, call_next):
|
||||
response = await call_next(request)
|
||||
response.headers['X-Custom-Header'] = 'Hello from middleware!'
|
||||
return response
|
||||
|
||||
# Add the middleware to the app
|
||||
app.add_middleware(CustomHeaderMiddleware)
|
||||
```
|
||||
|
||||
## Configure `langgraph.json`
|
||||
|
||||
Add the following to your `langgraph.json` file. Make sure the path points to the `webapp.py` file you created above.
|
||||
|
||||
```json
|
||||
{
|
||||
"dependencies": ["."],
|
||||
"graphs": {
|
||||
"agent": "./src/agent/graph.py:graph"
|
||||
},
|
||||
"env": ".env",
|
||||
"http": {
|
||||
"app": "./src/agent/webapp.py:app"
|
||||
}
|
||||
// Other configuration options like auth, store, etc.
|
||||
}
|
||||
```
|
||||
|
||||
## Start server
|
||||
|
||||
Test the server out locally:
|
||||
|
||||
```bash
|
||||
langgraph dev --no-browser
|
||||
```
|
||||
|
||||
Now any request to your server will include the custom header `X-Custom-Header` in its response.
|
||||
|
||||
## Deploying
|
||||
|
||||
You can deploy this app as-is to the managed langgraph cloud or to your self-hosted platform.
|
||||
|
||||
## Next steps
|
||||
|
||||
Now that you've added custom middleware to your deployment, you can use similar techniques to add [custom routes](./custom_routes.md) or define [custom lifespan events](./custom_lifespan.md) to further customize your server's behavior.
|
||||
@@ -0,0 +1,78 @@
|
||||
# How to add custom routes
|
||||
|
||||
When deploying agents on the LangGraph platform, your server automatically exposes routes for creating runs and threads, interacting with the long-term memory store, managing configurable assistants, and other core functionality ([see all default API endpoints](../../cloud/reference/api/api_ref.md)).
|
||||
|
||||
You can add custom routes by providing your own [`Starlette`](https://www.starlette.io/applications/) app (including [`FastAPI`](https://fastapi.tiangolo.com/), [`FastHTML`](https://fastht.ml/) and other compatible apps). You make LangGraph Platform aware of this by providing a path to the app in your `langgraph.json` configuration file. (`"http": {"app": "path/to/app.py:app"}`).
|
||||
|
||||
Defining a custom app object lets you add any routes you'd like, so you can do anything from adding a `/login` endpoint to writing an entire full-stack web-app, all deployed in a single LangGraph deployment.
|
||||
|
||||
Below is an example using FastAPI.
|
||||
|
||||
???+ note "Python only"
|
||||
|
||||
We currently only support custom authentication and authorization in Python deployments with `langgraph-api>=0.0.26`.
|
||||
|
||||
## Create app
|
||||
|
||||
Starting from an **existing** LangGraph Platform application, add the following custom route code to your `webapp.py` file. If you are starting from scratch, you can create a new app from a template using the CLI.
|
||||
|
||||
```bash
|
||||
langgraph new --template=new-langgraph-project-python my_new_project
|
||||
```
|
||||
|
||||
Once you have a LangGraph project, add the following app code:
|
||||
|
||||
```python
|
||||
# ./src/agent/webapp.py
|
||||
from fastapi import FastAPI
|
||||
|
||||
# highlight-next-line
|
||||
app = FastAPI()
|
||||
|
||||
|
||||
@app.get("/hello")
|
||||
def read_root():
|
||||
return {"Hello": "World"}
|
||||
|
||||
```
|
||||
|
||||
## Configure `langgraph.json`
|
||||
|
||||
Add the following to your `langgraph.json` file. Make sure the path points to the `app.py` file you created above.
|
||||
|
||||
```json
|
||||
{
|
||||
"dependencies": ["."],
|
||||
"graphs": {
|
||||
"agent": "./src/agent/graph.py:graph"
|
||||
},
|
||||
"env": ".env",
|
||||
"http": {
|
||||
"app": "./src/agent/webapp.py:app"
|
||||
}
|
||||
// Other configuration options like auth, store, etc.
|
||||
}
|
||||
```
|
||||
|
||||
## Start server
|
||||
|
||||
Test the server out locally:
|
||||
|
||||
```bash
|
||||
langgraph dev --no-browser
|
||||
```
|
||||
|
||||
If you navigate to `localhost:2024/hello` in your browser (2024 is the default development port), you should see the `hello` endpoint returning `{"Hello": "World"}`.
|
||||
|
||||
|
||||
!!! note "Shadowing default endpoints"
|
||||
|
||||
The routes you create in the app are given priority over the system defaults, meaning you can shadow and redefine the behavior of any default endpoint.
|
||||
|
||||
## Deploying
|
||||
|
||||
You can deploy this app as-is to the managed langgraph cloud or to your self-hosted platform.
|
||||
|
||||
## Next steps
|
||||
|
||||
Now that you've added a custom route to your deployment, you can use this same technique to further customize how your server behaves, such as defining custom [custom middleware](./custom_middleware.md) and [custom lifespan events](./custom_lifespan.md).
|
||||
@@ -397,7 +397,8 @@
|
||||
"# We define a fake node to ask the human\n",
|
||||
"def ask_human(state):\n",
|
||||
" tool_call_id = state[\"messages\"][-1].tool_calls[0][\"id\"]\n",
|
||||
" location = interrupt(\"Please provide your location:\")\n",
|
||||
" ask = AskHuman.model_validate(state[\"messages\"][-1].tool_calls[0][\"args\"])\n",
|
||||
" location = interrupt(ask.question)\n",
|
||||
" tool_message = [{\"tool_call_id\": tool_call_id, \"type\": \"tool\", \"content\": location}]\n",
|
||||
" return {\"messages\": tool_message}\n",
|
||||
"\n",
|
||||
@@ -491,7 +492,7 @@
|
||||
" \"messages\": [\n",
|
||||
" (\n",
|
||||
" \"user\",\n",
|
||||
" \"Use the search tool to ask the user where they are, then look up the weather there\",\n",
|
||||
" \"Ask the user where they are, then look up the weather there\",\n",
|
||||
" )\n",
|
||||
" ]\n",
|
||||
" },\n",
|
||||
|
||||
@@ -59,12 +59,10 @@ LangGraph makes it easy to manage conversation [memory](../concepts/memory.md) i
|
||||
[Human-in-the-loop](../concepts/human_in_the_loop.md) functionality allows
|
||||
you to involve humans in the decision-making process of your graph. These how-to guides show how to implement human-in-the-loop workflows in your graph.
|
||||
|
||||
|
||||
Key workflows:
|
||||
|
||||
- [How to wait for user input](human_in_the_loop/wait-user-input.ipynb): A basic example that shows how to implement a human-in-the-loop workflow in your graph using the `interrupt` function.
|
||||
- [How to review tool calls](human_in_the_loop/review-tool-calls.ipynb): Incorporate human-in-the-loop for reviewing/editing/accepting tool call requests before they executed using the `interrupt` function.
|
||||
|
||||
|
||||
Other methods:
|
||||
|
||||
@@ -165,6 +163,7 @@ These guides show how to use the prebuilt ReAct agent:
|
||||
- [How to add human-in-the-loop processes to a ReAct agent](create-react-agent-hitl.ipynb)
|
||||
- [How to return structured output from a ReAct agent](create-react-agent-structured-output.ipynb)
|
||||
- [How to add semantic search for long-term memory to a ReAct agent](memory/semantic-search.ipynb#using-in-create-react-agent)
|
||||
- [How to manage message history in a ReAct agent](create-react-agent-manage-message-history.ipynb)
|
||||
|
||||
Interested in further customizing the ReAct agent? This guide provides an
|
||||
overview of its underlying implementation to help you customize for your own needs:
|
||||
@@ -200,21 +199,29 @@ Learn how to set up your app for deployment to LangGraph Platform:
|
||||
- [How to test locally](../cloud/deployment/test_locally.md)
|
||||
- [How to rebuild graph at runtime](../cloud/deployment/graph_rebuild.md)
|
||||
- [How to use LangGraph Platform to deploy CrewAI, AutoGen, and other frameworks](autogen-langgraph-platform.ipynb)
|
||||
- [How to integrate LangGraph into your React application](../cloud/how-tos/use_stream_react.md)
|
||||
|
||||
### Deployment
|
||||
|
||||
LangGraph applications can be deployed using LangGraph Cloud, which provides a range of services to help you deploy, manage, and scale your applications.
|
||||
LangGraph applications can be deployed using LangGraph Platform, which provides a range of services to help you deploy, manage, and scale your applications.
|
||||
|
||||
- [How to deploy to LangGraph cloud](../cloud/deployment/cloud.md)
|
||||
- [How to deploy to a self-hosted environment](./deploy-self-hosted.md)
|
||||
- [How to deploy to Cloud SaaS](../cloud/deployment/cloud.md)
|
||||
- [How to deploy the Self-Hosted Data Plane](../cloud/deployment/self_hosted_data_plane.md)
|
||||
- [How to deploy the Self-Hosted Control Plane](../cloud/deployment/self_hosted_control_plane.md)
|
||||
- [How to deploy a Standalone Container](../cloud/deployment/standalone_container.md)
|
||||
- [How to interact with the deployment using RemoteGraph](./use-remote-graph.md)
|
||||
- [How to add TTLs to your LangGraph application](./ttl/configure_ttl.md)
|
||||
|
||||
### Authentication & Access Control
|
||||
|
||||
- [How to add custom authentication](./auth/custom_auth.md)
|
||||
- [How to update the security schema of your OpenAPI spec](./auth/openapi_security.md)
|
||||
|
||||
### Modifying the API
|
||||
|
||||
- [How to add custom routes](./http/custom_routes.md)
|
||||
- [How to add custom middleware](./http/custom_middleware.md)
|
||||
- [How to add custom lifespan events](./http/custom_lifespan.md)
|
||||
|
||||
### Assistants
|
||||
|
||||
[Assistants](../concepts/assistants.md) is a configured instance of a template.
|
||||
@@ -253,6 +260,13 @@ Streaming the results of your LLM application is vital for ensuring a good user
|
||||
- [How to stream in debug mode](../cloud/how-tos/stream_debug.md)
|
||||
- [How to stream multiple modes](../cloud/how-tos/stream_multiple.md)
|
||||
|
||||
### Frontend and Generative UI
|
||||
|
||||
With LangGraph Platform you can integrate LangGraph agents into your React applications and colocate UI components with your agent code.
|
||||
|
||||
- [How to integrate LangGraph into your React application](../cloud/how-tos/use_stream_react.md)
|
||||
- [How to implement Generative User Interfaces with LangGraph](../cloud/how-tos/generative_ui_react.md)
|
||||
|
||||
### Human-in-the-loop
|
||||
|
||||
When designing complex graphs, relying entirely on the LLM for decision-making can be risky, particularly when it involves tools that interact with files, APIs, or databases. These interactions may lead to unintended data access or modifications, depending on the use case. To mitigate these risks, LangGraph allows you to integrate human-in-the-loop behavior, ensuring your LLM applications operate as intended without undesirable outcomes.
|
||||
@@ -284,13 +298,13 @@ Graph execution can take a while, and sometimes users may change their mind abou
|
||||
|
||||
LangGraph Studio is a built-in UI for visualizing, testing, and debugging your agents.
|
||||
|
||||
- [How to connect to a LangGraph Cloud deployment](../cloud/how-tos/test_deployment.md)
|
||||
- [How to connect to a LangGraph Platform deployment](../cloud/how-tos/test_deployment.md)
|
||||
- [How to connect to a local dev server](../how-tos/local-studio.md)
|
||||
- [How to connect to a local deployment (Docker)](../cloud/how-tos/test_local_deployment.md)
|
||||
- [How to test your graph in LangGraph Studio (MacOS only)](../cloud/how-tos/invoke_studio.md)
|
||||
- [How to interact with threads in LangGraph Studio](../cloud/how-tos/threads_studio.md)
|
||||
- [How to add nodes as dataset examples in LangGraph Studio](../cloud/how-tos/datasets_studio.md)
|
||||
- [How to engineer prompts in LangGraph Studio](../cloud/how-tos/iterate_graph_studio.md)
|
||||
- [How to test your agent against remote traces](../cloud/how-tos/clone_traces_studio.md)
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
@@ -306,4 +320,4 @@ These are the guides for resolving common errors you may find while building wit
|
||||
|
||||
These guides provide troubleshooting information for errors that are specific to the LangGraph Platform.
|
||||
|
||||
- [INVALID_LICENSE](../troubleshooting/errors/INVALID_LICENSE.md)
|
||||
- [INVALID_LICENSE](../troubleshooting/errors/INVALID_LICENSE.md)
|
||||
|
||||
@@ -1,15 +1,6 @@
|
||||
# How to connect a local agent to LangGraph Studio
|
||||
|
||||
This guide shows you how to connect your local agent to [LangGraph Studio](../concepts/langgraph_studio.md) for visualization, interaction, and debugging.
|
||||
|
||||
## Connection Options
|
||||
|
||||
There are two ways to connect your local agent to LangGraph Studio:
|
||||
|
||||
- [Development Server](../concepts/langgraph_studio.md#development-server-with-web-ui): Python package, all platforms, no Docker
|
||||
- [LangGraph Desktop](../concepts/langgraph_studio.md#desktop-app): Application, Mac only, requires Docker
|
||||
|
||||
In this guide we will cover how to use the development server as that is generally an easier and better experience.
|
||||
This guide shows you how to connect your local agent to [LangGraph Studio](../concepts/langgraph_studio.md) for visualization, interaction, and debugging using the development server.
|
||||
|
||||
## Setup your application
|
||||
|
||||
@@ -24,9 +15,8 @@ You will need to make sure to install the `inmem` extras.
|
||||
|
||||
???+ note "Minimum version"
|
||||
|
||||
The minimum version to use the `inmem` extra with `langgraph-cli` is `0.1.55`.
|
||||
Python 3.11 or higher is required.
|
||||
|
||||
The minimum version to use the `inmem` extra with `langgraph-cli` is `0.1.55`.
|
||||
Python 3.11 or higher is required.
|
||||
|
||||
```shell
|
||||
pip install -U "langgraph-cli[inmem]"
|
||||
@@ -41,7 +31,7 @@ pip install -U "langgraph-cli[inmem]"
|
||||
langgraph dev
|
||||
```
|
||||
|
||||
This will look for the `langgraph.json` file in your current directory.
|
||||
This will look for the `langgraph.json` file in your current directory.
|
||||
In there, it will find the paths to the graph(s), and start those up.
|
||||
It will then automatically connect to the cloud-hosted studio.
|
||||
|
||||
@@ -89,4 +79,4 @@ Then attach your preferred debugger:
|
||||
2. Click + and select "Python Debug Server"
|
||||
3. Set IDE host name: `localhost`
|
||||
4. Set port: `5678` (or the port number you chose in the previous step)
|
||||
5. Click "OK" and start debugging
|
||||
5. Click "OK" and start debugging
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
"One of the most common use cases for persistence is to use it to keep track of conversation history. This is great - it makes it easy to continue conversations. As conversations get longer and longer, however, this conversation history can build up and take up more and more of the context window. This can often be undesirable as it leads to more expensive and longer calls to the LLM, and potentially ones that error. One way to work around that is to create a summary of the conversation to date, and use that with the past N messages. This guide will go through an example of how to do that.\n",
|
||||
"\n",
|
||||
"This will involve a few steps:\n",
|
||||
"\n",
|
||||
"- Check if the conversation is too long (can be done by checking number of messages or length of messages)\n",
|
||||
"- If yes, the create summary (will need a prompt for this)\n",
|
||||
"- Then remove all except the last N messages\n",
|
||||
@@ -98,7 +99,7 @@
|
||||
"from typing import Literal\n",
|
||||
"\n",
|
||||
"from langchain_anthropic import ChatAnthropic\n",
|
||||
"from langchain_core.messages import SystemMessage, RemoveMessage\n",
|
||||
"from langchain_core.messages import SystemMessage, RemoveMessage, HumanMessage\n",
|
||||
"from langgraph.checkpoint.memory import MemorySaver\n",
|
||||
"from langgraph.graph import MessagesState, StateGraph, START, END\n",
|
||||
"\n",
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
"source": [
|
||||
"# How to manage conversation history\n",
|
||||
"\n",
|
||||
"One of the most common use cases for persistence is to use it to keep track of conversation history. This is great - it makes it easy to continue conversations. As conversations get longer and longer, however, this conversation history can build up and take up more and more of the context window. This can often be undesirable as it leads to more expensive and longer calls to the LLM, and potentially ones that error. In order to prevent this from happening, you need to probably manage the conversation history.\n",
|
||||
"One of the most common use cases for persistence is to use it to keep track of conversation history. This is great - it makes it easy to continue conversations. As conversations get longer and longer, however, this conversation history can build up and take up more and more of the context window. This can often be undesirable as it leads to more expensive and longer calls to the LLM, and potentially ones that error. In order to prevent this from happening, you need to properly manage the conversation history.\n",
|
||||
"\n",
|
||||
"Note: this guide focuses on how to do this in LangGraph, where you can fully customize how this is done. If you want a more off-the-shelf solution, you can look into functionality provided in LangChain:\n",
|
||||
"\n",
|
||||
|
||||
@@ -38,7 +38,7 @@
|
||||
" </p>\n",
|
||||
"</div> \n",
|
||||
"\n",
|
||||
"The core technique the examples below is to **annotate** a parameter as \"injected\", meaning it will be injected by your program and should not be seen or populated by the LLM. Let the following codesnippet serve as a tl;dr:\n",
|
||||
"The core technique in the examples below is to **annotate** a parameter as \"injected\", meaning it will be injected by your program and should not be seen or populated by the LLM. Let the following codesnippet serve as a tl;dr:\n",
|
||||
"\n",
|
||||
"```python\n",
|
||||
"from typing import Annotated\n",
|
||||
|
||||
@@ -16,6 +16,10 @@
|
||||
" - [Memory](../../concepts/memory/)\n",
|
||||
" - [Chat Models](https://python.langchain.com/docs/concepts/chat_models/)\n",
|
||||
"\n",
|
||||
"!!! info \"Not needed for LangGraph API users\"\n",
|
||||
"\n",
|
||||
" If you're using the LangGraph API, you needn't manually implement a checkpointer. The API automatically handles checkpointing for you. This guide is relevant when implementing LangGraph in your own custom server.\n",
|
||||
"\n",
|
||||
"Many AI applications need memory to share context across multiple interactions on the same [thread](../../concepts/persistence#threads) (e.g., multiple turns of a conversation). In LangGraph functional API, this kind of memory can be added to any [entrypoint()][langgraph.func.entrypoint] workflow using [thread-level persistence](https://langchain-ai.github.io/langgraph/concepts/persistence).\n",
|
||||
"\n",
|
||||
"When creating a LangGraph workflow, you can set it up to persist its results by using a [checkpointer](https://langchain-ai.github.io/langgraph/reference/checkpoints/#basecheckpointsaver):\n",
|
||||
|
||||
@@ -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."
|
||||
]
|
||||
|
||||
@@ -65,7 +65,7 @@
|
||||
"\n",
|
||||
"**Pros and Cons**\n",
|
||||
"\n",
|
||||
"The benefit to this format is that you only need one LLM, and can save money and latency because of this. The downside to this option is that it isn't guaranteed that the single LLM will call the correct tool when you want it to. We can help the LLM by setting `tool_choice` to `any` when we use `bind_tools` which forces the LLM to select at least one tool at every turn, but this is far from a fool proof strategy. In addition, another downside is that the agent might call *multiple* tools, so we need to check for this explicitly in our routing function (or if we are using OpenAI we an set `parallell_tool_calling=False` to ensure only one tool is called at a time).\n",
|
||||
"The benefit to this format is that you only need one LLM, and can save money and latency because of this. The downside to this option is that it isn't guaranteed that the single LLM will call the correct tool when you want it to. We can help the LLM by setting `tool_choice` to `any` when we use `bind_tools` which forces the LLM to select at least one tool at every turn, but this is far from a foolproof strategy. In addition, another downside is that the agent might call *multiple* tools, so we need to check for this explicitly in our routing function (or if we are using OpenAI we can set `parallell_tool_calling=False` to ensure only one tool is called at a time).\n",
|
||||
"\n",
|
||||
"**Option 2**\n",
|
||||
"\n",
|
||||
|
||||
@@ -266,6 +266,235 @@
|
||||
" print(\"An exception was raised because bad_node sets `a` to an integer.\")\n",
|
||||
" print(e)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"id": "2270bc3c",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## Multiple Nodes\n",
|
||||
"\n",
|
||||
"Run-time validation will also work in a multi-node graph. In the example below `bad_node` updates `a` to an integer. \n",
|
||||
"\n",
|
||||
"Because run-time validation occurs on **inputs**, the validation error will occur when `ok_node` is called (not when `bad_node` returns an update to the state which is inconsistent with the schema)."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"id": "d832cdcc",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"from langgraph.graph import StateGraph, START, END\n",
|
||||
"from typing_extensions import TypedDict\n",
|
||||
"\n",
|
||||
"from pydantic import BaseModel\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"# The overall state of the graph (this is the public state shared across nodes)\n",
|
||||
"class OverallState(BaseModel):\n",
|
||||
" a: str\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"def bad_node(state: OverallState):\n",
|
||||
" return {\n",
|
||||
" \"a\": 123 # Invalid\n",
|
||||
" }\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"def ok_node(state: OverallState):\n",
|
||||
" return {\"a\": \"goodbye\"}\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"# Build the state graph\n",
|
||||
"builder = StateGraph(OverallState)\n",
|
||||
"builder.add_node(bad_node)\n",
|
||||
"builder.add_node(ok_node)\n",
|
||||
"builder.add_edge(START, \"bad_node\")\n",
|
||||
"builder.add_edge(\"bad_node\", \"ok_node\")\n",
|
||||
"builder.add_edge(\"ok_node\", END)\n",
|
||||
"graph = builder.compile()\n",
|
||||
"\n",
|
||||
"# Test the graph with a valid input\n",
|
||||
"try:\n",
|
||||
" graph.invoke({\"a\": \"hello\"})\n",
|
||||
"except Exception as e:\n",
|
||||
" print(\"An exception was raised because bad_node sets `a` to an integer.\")\n",
|
||||
" print(e)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"id": "456b1f77",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## Advanced Pydantic Model Usage\n",
|
||||
"\n",
|
||||
"This section covers more advanced topics when using Pydantic models with LangGraph.\n",
|
||||
"\n",
|
||||
"### Serialization Behavior\n",
|
||||
"\n",
|
||||
"When using Pydantic models as state schemas, it's important to understand how serialization works, especially when:\n",
|
||||
"- Passing Pydantic objects as inputs\n",
|
||||
"- Receiving outputs from the graph\n",
|
||||
"- Working with nested Pydantic models\n",
|
||||
"\n",
|
||||
"Let's see these behaviors in action:"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"id": "0e919cdc",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"from langgraph.graph import StateGraph, START, END\n",
|
||||
"from pydantic import BaseModel\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"class NestedModel(BaseModel):\n",
|
||||
" value: str\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"class ComplexState(BaseModel):\n",
|
||||
" text: str\n",
|
||||
" count: int\n",
|
||||
" nested: NestedModel\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"def process_node(state: ComplexState):\n",
|
||||
" # Node receives a validated Pydantic object\n",
|
||||
" print(f\"Input state type: {type(state)}\")\n",
|
||||
" print(f\"Nested type: {type(state.nested)}\")\n",
|
||||
"\n",
|
||||
" # Return a dictionary update\n",
|
||||
" return {\"text\": state.text + \" processed\", \"count\": state.count + 1}\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"# Build the graph\n",
|
||||
"builder = StateGraph(ComplexState)\n",
|
||||
"builder.add_node(\"process\", process_node)\n",
|
||||
"builder.add_edge(START, \"process\")\n",
|
||||
"builder.add_edge(\"process\", END)\n",
|
||||
"graph = builder.compile()\n",
|
||||
"\n",
|
||||
"# Create a Pydantic instance for input\n",
|
||||
"input_state = ComplexState(text=\"hello\", count=0, nested=NestedModel(value=\"test\"))\n",
|
||||
"print(f\"Input object type: {type(input_state)}\")\n",
|
||||
"\n",
|
||||
"# Invoke graph with a Pydantic instance\n",
|
||||
"result = graph.invoke(input_state)\n",
|
||||
"print(f\"Output type: {type(result)}\")\n",
|
||||
"print(f\"Output content: {result}\")\n",
|
||||
"\n",
|
||||
"# Convert back to Pydantic model if needed\n",
|
||||
"output_model = ComplexState(**result)\n",
|
||||
"print(f\"Converted back to Pydantic: {type(output_model)}\")"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"id": "f13f28ce",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"### Runtime Type Coercion\n",
|
||||
"\n",
|
||||
"Pydantic performs runtime type coercion for certain data types. This can be helpful but also lead to unexpected behavior if you're not aware of it."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"id": "faf59316",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"from langgraph.graph import StateGraph, START, END\n",
|
||||
"from pydantic import BaseModel\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"class CoercionExample(BaseModel):\n",
|
||||
" # Pydantic will coerce string numbers to integers\n",
|
||||
" number: int\n",
|
||||
" # Pydantic will parse string booleans to bool\n",
|
||||
" flag: bool\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"def inspect_node(state: CoercionExample):\n",
|
||||
" print(f\"number: {state.number} (type: {type(state.number)})\")\n",
|
||||
" print(f\"flag: {state.flag} (type: {type(state.flag)})\")\n",
|
||||
" return {}\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"builder = StateGraph(CoercionExample)\n",
|
||||
"builder.add_node(\"inspect\", inspect_node)\n",
|
||||
"builder.add_edge(START, \"inspect\")\n",
|
||||
"builder.add_edge(\"inspect\", END)\n",
|
||||
"graph = builder.compile()\n",
|
||||
"\n",
|
||||
"# Demonstrate coercion with string inputs that will be converted\n",
|
||||
"result = graph.invoke({\"number\": \"42\", \"flag\": \"true\"})\n",
|
||||
"\n",
|
||||
"# This would fail with a validation error\n",
|
||||
"try:\n",
|
||||
" graph.invoke({\"number\": \"not-a-number\", \"flag\": \"true\"})\n",
|
||||
"except Exception as e:\n",
|
||||
" print(f\"\\nExpected validation error: {e}\")"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"id": "2844475b",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"### Working with Message Models\n",
|
||||
"\n",
|
||||
"When working with LangChain message types in your state schema, there are important considerations for serialization. You should use `AnyMessage` (rather than `BaseMessage`) for proper serialization/deserialization when using message objects over the wire:"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"id": "bd0734b0",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"from langgraph.graph import StateGraph, START, END\n",
|
||||
"from pydantic import BaseModel\n",
|
||||
"from langchain_core.messages import HumanMessage, AIMessage, AnyMessage\n",
|
||||
"from typing import List\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"class ChatState(BaseModel):\n",
|
||||
" messages: List[AnyMessage]\n",
|
||||
" context: str\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"def add_message(state: ChatState):\n",
|
||||
" return {\"messages\": state.messages + [AIMessage(content=\"Hello there!\")]}\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"builder = StateGraph(ChatState)\n",
|
||||
"builder.add_node(\"add_message\", add_message)\n",
|
||||
"builder.add_edge(START, \"add_message\")\n",
|
||||
"builder.add_edge(\"add_message\", END)\n",
|
||||
"graph = builder.compile()\n",
|
||||
"\n",
|
||||
"# Create input with a message\n",
|
||||
"initial_state = ChatState(\n",
|
||||
" messages=[HumanMessage(content=\"Hi\")], context=\"Customer support chat\"\n",
|
||||
")\n",
|
||||
"\n",
|
||||
"result = graph.invoke(initial_state)\n",
|
||||
"print(f\"Output: {result}\")\n",
|
||||
"\n",
|
||||
"# Convert back to Pydantic model to see message types\n",
|
||||
"output_model = ChatState(**result)\n",
|
||||
"for i, msg in enumerate(output_model.messages):\n",
|
||||
" print(f\"Message {i}: {type(msg).__name__} - {msg.content}\")"
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -210,7 +210,7 @@
|
||||
"id": "cbb06aea-6654-4245-91f8-af6e8f2b5377",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"Let's now add personalization: we'll respond differently to the user based on the state values AFTER the state has been updated from the tool. To achieve this, let's define a function that will dynamically construct the system prompt based on the graph state. It will be called ever time the LLM is called and the function output will be passed to the LLM:"
|
||||
"Let's now add personalization: we'll respond differently to the user based on the state values AFTER the state has been updated from the tool. To achieve this, let's define a function that will dynamically construct the system prompt based on the graph state. It will be called every time the LLM is called and the function output will be passed to the LLM:"
|
||||
]
|
||||
},
|
||||
{
|
||||
|
||||
+26
-1
@@ -1,6 +1,31 @@
|
||||
---
|
||||
hide_comments: true
|
||||
title: Home
|
||||
title: LangGraph
|
||||
---
|
||||
|
||||
<script>
|
||||
// This script only runs in MkDocs, not on GitHub
|
||||
var hideGitHubVersion = function() {
|
||||
document.querySelectorAll('.github-only').forEach(el => el.style.display = 'none');
|
||||
};
|
||||
|
||||
// Handle both initial load and subsequent navigation
|
||||
document.addEventListener('DOMContentLoaded', hideGitHubVersion);
|
||||
document$.subscribe(hideGitHubVersion);
|
||||
</script>
|
||||
|
||||
<p class="mkdocs-only">
|
||||
<img class="logo-light" src="static/wordmark_dark.svg" alt="LangGraph Logo" width="80%">
|
||||
<img class="logo-dark" src="static/wordmark_light.svg" alt="LangGraph Logo" width="80%">
|
||||
</p>
|
||||
|
||||
<style>
|
||||
.md-content h1 {
|
||||
display: none;
|
||||
}
|
||||
.md-header__topic {
|
||||
display: none;
|
||||
}
|
||||
</style>
|
||||
|
||||
{!../README.md!}
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
# LLMs-txt Overview
|
||||
|
||||
## Overview
|
||||
|
||||
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`
|
||||
|
||||
- **`llms.txt`** is an index file containing links with brief descriptions of the content. An LLM or agent must follow these links to access detailed information.
|
||||
|
||||
- **`llms-full.txt`** includes all the detailed content directly in a single file, eliminating the need for additional navigation.
|
||||
|
||||
A key consideration when using `llms-full.txt` is its size. For extensive documentation, this file may become too large to fit into an LLM's context window.
|
||||
|
||||
## 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 still use `llms.txt` effectively through an MCP server.
|
||||
|
||||
### 🚀 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`
|
||||
|
||||
The LangGraph `llms-full.txt` file typically contains several hundred thousand tokens, exceeding the context window limitations of most LLMs. To effectively use this file:
|
||||
|
||||
1. **With IDEs (e.g., Cursor, Windsurf)**:
|
||||
- Add the `llms-full.txt` as custom documentation. The IDE will automatically chunk and index the content, implementing Retrieval-Augmented Generation (RAG).
|
||||
|
||||
2. **Without IDE support**:
|
||||
- Use a chat model with a large context window.
|
||||
- Implement a RAG strategy to manage and query the documentation efficiently.
|
||||
|
||||
@@ -0,0 +1,204 @@
|
||||
# LangGraph
|
||||
|
||||
## Tutorials
|
||||
|
||||
[Learn the basics](https://langchain-ai.github.io/langgraph/tutorials/introduction/): LLM should read this page when needing to build a LangGraph chatbot or when learning about chat agents with memory, human-in-the-loop functionality, and state management. This page provides a comprehensive LangGraph quickstart tutorial covering building a support chatbot with web search capability, conversation memory, human review routing, custom state management, and time travel functionality to explore alternative conversation paths.
|
||||
|
||||
[Local Deploy](https://langchain-ai.github.io/langgraph/tutorials/langgraph-platform/local-server/): LLM should read this page when setting up a LangGraph app locally using `langgraph dev` and troubleshooting LangGraph server deployment. This page contains a quickstart guide for launching a LangGraph server locally, including installation steps, app creation from templates, environment setup, API testing with Python/JS SDKs, and links to deployment options and further documentation.
|
||||
|
||||
[Workflows and Agents](https://langchain-ai.github.io/langgraph/tutorials/workflows/): LLM should read this page when implementing agent systems, designing workflow architectures, or troubleshooting LLM orchestration strategies. The page covers patterns for LLM system design, comparing workflows (predefined paths) vs agents (dynamic control), with implementations of prompt chaining, parallelization, routing, orchestrator-worker, evaluator-optimizer, and agent patterns using both graph and functional APIs in LangGraph.
|
||||
|
||||
## Concepts
|
||||
|
||||
[Concepts](https://langchain-ai.github.io/langgraph/concepts/): LLM should read this page when needing to understand LangGraph's key concepts or when planning to deploy LangGraph applications. Comprehensive guide covering LangGraph fundamentals (graph primitives, agents, multi-agent systems, breakpoints, persistence), features (time travel, memory, streaming), and LangGraph Platform deployment options (self-hosted, cloud, enterprise).
|
||||
|
||||
[Agent architectures](https://langchain-ai.github.io/langgraph/concepts/agentic_concepts/): LLM should read this page when designing agent architectures, implementing control flows for LLM applications, or customizing agent behavior patterns. This page covers different LLM agent architectures including routers, tool calling agents (ReAct), structured outputs, memory systems, planning capabilities, and advanced customization options like human-in-the-loop, parallelization, subgraphs, and reflection mechanisms.
|
||||
|
||||
[Application Structure](https://langchain-ai.github.io/langgraph/concepts/application_structure/): LLM should read this page when needing to understand LangGraph application structure, preparing to deploy a LangGraph application, or troubleshooting configuration issues. This page details the structure of LangGraph applications, including required components (graphs, langgraph.json config file, dependency files, optional .env), file organization patterns for Python/JavaScript projects, configuration file format with all supported fields, and how to specify dependencies, graphs, and environment variables.
|
||||
|
||||
[Assistants](https://langchain-ai.github.io/langgraph/concepts/assistants/): LLM should read this page when looking for information about LangGraph assistants, understanding assistant configuration in LangGraph Platform, or learning about versioning agent configurations. This page explains LangGraph assistants, which allow developers to modify agent configurations (prompts, models, etc.) without changing graph logic, supports versioning for tracking changes, and is available only in LangGraph Platform (not open source).
|
||||
|
||||
[Authentication & Access Control](https://langchain-ai.github.io/langgraph/concepts/auth/): LLM should read this page when implementing authentication in LangGraph Platform, designing access control for LangGraph applications, or troubleshooting security issues in LangGraph deployments. This page explains LangGraph's authentication and authorization system, covering the difference between authentication and authorization, system architecture, implementing custom auth handlers, common access patterns, and supported resources/actions for access control.
|
||||
|
||||
[Bring Your Own Cloud (BYOC)](https://langchain-ai.github.io/langgraph/concepts/bring_your_own_cloud/): LLM should read this page when learning about LangGraph Platform deployment options, understanding Bring Your Own Cloud architecture, or managing deployments in AWS. This page explains LangGraph's BYOC deployment model, detailing how it separates control plane (managed by LangChain) from data plane (in customer's AWS account), outlines AWS requirements, infrastructure setup via Terraform, required permissions, and explains the deployment workflow.
|
||||
|
||||
[Deployment Options](https://langchain-ai.github.io/langgraph/concepts/deployment_options/): LLM should read this page when needing information about LangGraph deployment options, comparing different deployment methods, or understanding LangGraph Platform plans. This page outlines four deployment options for LangGraph Platform: Self-Hosted Lite (available for all plans), Self-Hosted Enterprise (Enterprise plan only), Cloud SaaS (Plus and Enterprise plans), and Bring Your Own Cloud (Enterprise plan only, AWS-only).
|
||||
|
||||
[Double Texting](https://langchain-ai.github.io/langgraph/concepts/double_texting/): LLM should read this page when handling concurrent user interactions in LangGraph Platform, implementing double-texting safeguards, or designing stateful conversation systems. This page explains four approaches to handling "double texting" in LangGraph (when users send a second message before the first completes): Reject, Enqueue, Interrupt, and Rollback, noting these features are currently only available in LangGraph Platform.
|
||||
|
||||
[Durable Execution](https://langchain-ai.github.io/langgraph/concepts/durable_execution/): LLM should read this page when needing to understand durable execution in LangGraph, implementing workflow persistence, or troubleshooting workflow resumption. This page explains durable execution in LangGraph: how workflows save progress to resume later, requirements (checkpointers and thread IDs), determinism guidelines for consistent replay, using tasks to encapsulate non-deterministic operations, and approaches for pausing/resuming workflows.
|
||||
|
||||
[FAQ](https://langchain-ai.github.io/langgraph/concepts/faq/): LLM should read this page when needing to understand differences between LangGraph and LangChain, exploring deployment options for LangGraph Platform, or determining compatibility with various LLMs. FAQ covering LangGraph basics, comparisons with other frameworks, deployment options (free self-hosted, Cloud SaaS, BYOC, Enterprise), compatibility with different LLMs including OSS models, and feature differences between open-source LangGraph and proprietary LangGraph Platform.
|
||||
|
||||
[Functional API](https://langchain-ai.github.io/langgraph/concepts/functional_api/): LLM should read this page when implementing workflows with persistent state, adding human-in-the-loop features, or converting existing code to use LangGraph. The page documents LangGraph's Functional API, which allows adding persistence, memory, and human-in-the-loop capabilities with minimal code changes using @entrypoint and @task decorators, handling serialization requirements, state management, and common patterns for parallel execution and error handling.
|
||||
|
||||
[Why LangGraph?](https://langchain-ai.github.io/langgraph/concepts/high_level/): LLM should read this page when understanding LangGraph's core capabilities, exploring LLM application infrastructure, or evaluating agent/workflow persistence options. LangGraph provides infrastructure for LLM applications with three key benefits: persistence for memory and human-in-the-loop capabilities, streaming of workflow events and LLM outputs, and tools for debugging and deployment via LangGraph Platform.
|
||||
|
||||
[Human-in-the-loop](https://langchain-ai.github.io/langgraph/concepts/human_in_the_loop/): LLM should read this page when implementing human-in-the-loop workflows in LangGraph, designing approval systems with LLMs, or creating interactive multi-turn conversation agents. This page explains human-in-the-loop patterns in LangGraph using the interrupt function, showing how to pause graph execution for human review/input and resume with Command. Includes design patterns for approval workflows, state editing, tool call reviews, and multi-turn conversations, with code examples and warnings about execution flow and common pitfalls.
|
||||
|
||||
[LangGraph CLI](https://langchain-ai.github.io/langgraph/concepts/langgraph_cli/): LLM should read this page when looking for information about LangGraph CLI installation or when needing to deploy a LangGraph API server locally. The page covers LangGraph CLI installation methods (Homebrew, pip), key commands (build, dev, up, dockerfile), and features like hot reloading, debugger support, and database management for running LangGraph servers.
|
||||
|
||||
[Cloud SaaS](https://langchain-ai.github.io/langgraph/concepts/langgraph_cloud/): LLM should read this page when learning about LangGraph's Cloud SaaS offering, understanding deployment options for LangGraph Servers, or planning autoscaling infrastructure for LangGraph applications. This page describes LangGraph Cloud SaaS, a managed deployment service for LangGraph Servers with details on deployment types (Development/Production), revisions, persistence, autoscaling capabilities (up to 10 containers), LangSmith integration, IP whitelisting, and automatic deletion policies after 28 days of non-use.
|
||||
|
||||
[LangGraph Platform](https://langchain-ai.github.io/langgraph/concepts/langgraph_platform/): LLM should read this page when seeking information about LangGraph Platform's components or evaluating production deployment options for agentic applications. The page details the LangGraph Platform, a commercial solution for deploying agentic applications, including its components (Server, Studio, CLI, SDK, Remote Graph) and key benefits like streaming support, background runs, long run handling, burstiness management, and human-in-the-loop capabilities.
|
||||
|
||||
[LangGraph Server](https://langchain-ai.github.io/langgraph/concepts/langgraph_server/): LLM should read this page when developing applications with LangGraph Server, deploying agent-based applications, or integrating persistent state management in agent workflows. LangGraph Server provides an API for creating and managing agent applications with key features like streaming endpoints, background runs, task queues, persistence, webhooks, cron jobs, and monitoring capabilities through a structured system of assistants, threads, runs, and stores.
|
||||
|
||||
[LangGraph Studio](https://langchain-ai.github.io/langgraph/concepts/langgraph_studio/): LLM should read this page when looking for information about LangGraph Studio features, needing to troubleshoot LangGraph Studio issues, or learning how to connect a LangGraph application to the Studio. LangGraph Studio is a specialized agent IDE for visualizing, interacting with, and debugging LLM applications, offering features such as graph visualization, state editing, assistant management, and integration with LangSmith, with instructions for connecting via deployed applications or local development servers, plus troubleshooting FAQs.
|
||||
|
||||
[LangGraph Glossary](https://langchain-ai.github.io/langgraph/concepts/low_level/): LLM should read this page when needing to understand LangGraph terminology, implementing agent workflows as graphs, or developing modular multi-step AI systems. The page covers core LangGraph concepts including StateGraph, nodes, edges, state management, messaging, persistence, configuration, human-in-the-loop features, subgraphs, and visualization capabilities.
|
||||
|
||||
[Memory](https://langchain-ai.github.io/langgraph/concepts/memory/): LLM should read this page when implementing memory systems for AI agents, managing conversation context across sessions, or designing systems that require both short-term and long-term information retention. This page explains memory systems in LangGraph, covering short-term (thread-scoped) memory for managing conversation history and long-term memory across threads, with techniques for handling long conversations, summarizing past interactions, and organizing persistent memories in namespaces.
|
||||
|
||||
[Multi-agent Systems](https://langchain-ai.github.io/langgraph/concepts/multi_agent/): LLM should read this page when implementing multi-agent systems, troubleshooting complex agent architectures, or designing agent communication patterns. Multi-agent systems organize LLMs into modular architectures (network, supervisor, hierarchical, custom) with different communication patterns, using Command objects for handoffs between agents, and supporting various state management approaches.
|
||||
|
||||
[Persistence](https://langchain-ai.github.io/langgraph/concepts/persistence/): LLM should read this page when needing to understand LangGraph persistence mechanisms, implementing stateful workflows, or managing conversation history across interactions. This page covers LangGraph's persistence features including checkpointers, threads, state snapshots, replay functionality, forking state, cross-thread memory via InMemoryStore, and semantic search capabilities for stored memories.
|
||||
|
||||
[LangGraph Platform Plans](https://langchain-ai.github.io/langgraph/concepts/plans/): LLM should read this page when determining LangGraph Platform pricing tiers, comparing deployment options, or researching features available across different plans. This page outlines LangGraph Platform plans (Developer, Plus, Enterprise), detailing deployment options, usage limitations, feature availability, and pricing structure for agentic application deployment.
|
||||
|
||||
[LangGraph Platform Architecture](https://langchain-ai.github.io/langgraph/concepts/platform_architecture/): LLM should read this page when needing to understand LangGraph Platform's technical architecture or troubleshooting deployment issues. The page details how LangGraph Platform uses Postgres for persistent storage of user/run data and Redis for worker communication (run cancellation, output streaming) and ephemeral metadata storage (retry attempts).
|
||||
|
||||
[LangGraph's Runtime (Pregel)](https://langchain-ai.github.io/langgraph/concepts/pregel/): LLM should read this page when learning about LangGraph's runtime, implementing applications with Pregel directly, or understanding how LangGraph executes graph applications. Explains LangGraph's Pregel runtime which manages graph application execution through a three-phase process (Plan, Execution, Update), describes different channel types (LastValue, Topic, Context, BinaryOperatorAggregate), provides direct implementation examples, and contrasts the StateGraph API with the Functional API.
|
||||
|
||||
[LangGraph Platform: Scalability & Resilience](https://langchain-ai.github.io/langgraph/concepts/scalability_and_resilience/): LLM should read this page when needing to understand LangGraph Platform's scaling capabilities, designing high-availability LangGraph deployments, or troubleshooting resilience issues. This page details LangGraph Platform's horizontal scaling features including stateless server instances, queue worker scaling, resilience mechanisms for handling crashes, and database failover strategies in Postgres and Redis.
|
||||
|
||||
[LangGraph SDK](https://langchain-ai.github.io/langgraph/concepts/sdk/): LLM should read this page when looking for installation instructions for LangGraph SDK, needing to choose between sync and async Python clients, or requiring SDK API references. The page covers LangGraph SDK installation for Python and JS, provides API reference links, explains the difference between synchronous and asynchronous Python clients, and includes code examples for both client types.
|
||||
|
||||
[Self-Hosted](https://langchain-ai.github.io/langgraph/concepts/self_hosted/): LLM should read this page when looking for LangGraph deployment options, understanding self-hosted versions, or seeking requirements for self-hosting LangGraph. This page details two self-hosted deployment options for LangGraph Platform: Self-Hosted Lite (limited to 1M nodes/year) and Self-Hosted Enterprise (full version requiring license). Includes requirements, deployment process using Redis/Postgres, Docker, and optional Kubernetes deployment via Helm chart.
|
||||
|
||||
[Streaming](https://langchain-ai.github.io/langgraph/concepts/streaming/): LLM should read this page when implementing streaming features in LangGraph applications, understanding different streaming modes, or building responsive LLM applications. This page explains streaming in LangGraph, covering the main types (workflow progress, LLM tokens, custom updates) and streaming modes (values, updates, custom, messages, debug, events), with details on how to use multiple modes simultaneously and differences between LangGraph library and Platform implementations.
|
||||
|
||||
[Template Applications](https://langchain-ai.github.io/langgraph/concepts/template_applications/): LLM should read this page when looking for LangGraph template applications, setting up a new LangGraph project, or finding reference implementations for agentic workflows. This page presents LangGraph template applications with installation requirements, available templates (including ReAct Agent, Memory Agent, Retrieval Agent, etc.), instructions for creating new apps using the CLI, deployment options, and links to further learning resources.
|
||||
|
||||
[Time Travel ⏱️](https://langchain-ai.github.io/langgraph/concepts/time-travel/): LLM should read this page when debugging LLM-based agent behavior, analyzing decision-making paths, or exploring alternative execution branches in LangGraph. This page explains LangGraph's Time Travel debugging features: Replaying (reproducing past actions up to specific checkpoints) and Forking (creating alternative execution paths from specific points), with code examples for retrieving checkpoints, configuring replay, and creating forked states.
|
||||
|
||||
## How Tos
|
||||
|
||||
[How-to Guides](https://langchain-ai.github.io/langgraph/how-tos/): LLM should read this page when looking for specific implementation techniques in LangGraph or when trying to deploy LangGraph applications to production environments. This page contains an extensive collection of how-to guides for LangGraph, covering graph fundamentals, persistence, memory management, human-in-the-loop features, tool calling, multi-agent systems, streaming, and deployment options through LangGraph Platform.
|
||||
|
||||
[How to implement handoffs between agents](https://langchain-ai.github.io/langgraph/how-tos/agent-handoffs/): LLM should read this page when implementing multi-agent systems that require agent coordination, when building systems with specialized agents that need to work together, or when needing to implement handoffs between agents. This page explains how to implement handoffs between agents in LangGraph using Command objects, both directly from agent nodes and through specialized handoff tools, with code examples for creating multi-agent systems.
|
||||
|
||||
[How to run a graph asynchronously](https://langchain-ai.github.io/langgraph/how-tos/async/): LLM should read this page when needing to implement asynchronous graph execution in LangGraph or when optimizing IO-bound LLM applications. This page explains how to convert synchronous graphs to asynchronous in LangGraph, including updating node definitions with async/await, using StateGraph with TypedDict, implementing conditional edges, and streaming results.
|
||||
|
||||
[How to integrate LangGraph with AutoGen, CrewAI, and other frameworks](https://langchain-ai.github.io/langgraph/how-tos/autogen-integration/): LLM should read this page when integrating LangGraph with other agent frameworks, building multi-agent systems, or adding persistence features to agents. The page demonstrates how to combine LangGraph with AutoGen by calling AutoGen agents inside LangGraph nodes, showing code examples for setting up the integration with memory and conversation persistence.
|
||||
|
||||
[How to integrate LangGraph (functional API) with AutoGen, CrewAI, and other frameworks](https://langchain-ai.github.io/langgraph/how-tos/autogen-integration-functional/): LLM should read this page when integrating LangGraph with other agent frameworks, building multi-agent systems with different frameworks, or adding LangGraph features to existing agent systems. This page demonstrates how to integrate LangGraph's functional API with AutoGen, including code examples for creating a workflow that calls AutoGen agents, leveraging LangGraph's memory and persistence features.
|
||||
|
||||
[How to create branches for parallel node execution](https://langchain-ai.github.io/langgraph/how-tos/branching/): LLM should read this page when needing to implement parallel node execution in LangGraph, optimizing graph performance, or handling conditional branching in workflows. This page explains how to create branches for parallel execution in LangGraph using fan-out/fan-in mechanisms, reducer functions for state accumulation, handling exceptions during parallel execution, and implementing conditional branching logic between nodes.
|
||||
|
||||
[How to combine control flow and state updates with Command](https://langchain-ai.github.io/langgraph/how-tos/command): LLM should read this page when learning how to combine control flow with state updates in LangGraph, understanding Command objects, or navigating between parent graphs and subgraphs. This page explains how to use Command objects to simultaneously update state and control flow between nodes, demonstrates using Command.PARENT to navigate from subgraphs to parent graphs, and includes examples of implementing reducers for state updates across graph hierarchies.
|
||||
|
||||
[How to add runtime configuration to your graph](https://langchain-ai.github.io/langgraph/how-tos/configuration/): LLM should read this page when implementing runtime configuration for LangGraph, adding model selection options to agents, or enabling dynamic system messages. This page demonstrates how to configure LangGraph at runtime, including selecting different LLMs dynamically and adding custom configuration options like system messages through the configurable dictionary.
|
||||
|
||||
[How to use the pre-built ReAct agent](https://langchain-ai.github.io/langgraph/how-tos/create-react-agent/): LLM should read this page when implementing a ReAct agent, needing pre-built agent solutions, or learning how to integrate tools with LLM agents. This page covers how to use the pre-built ReAct agent in LangGraph, including setup instructions, creating a weather checking tool, implementing the agent architecture, and examples of running the agent with and without tool calls.
|
||||
|
||||
[How to add human-in-the-loop processes to the prebuilt ReAct agent](https://langchain-ai.github.io/langgraph/how-tos/create-react-agent-hitl/): LLM should read this page when implementing human-in-the-loop processes for ReAct agents, debugging tool calls, or learning about interrupts in LangGraph. This guide demonstrates how to add human-in-the-loop functionality to prebuilt ReAct agents using interrupt_before=["tools"], working with MemorySaver checkpoints, and showing how to approve or edit tool calls before they execute.
|
||||
|
||||
[How to add thread-level memory to a ReAct Agent](https://langchain-ai.github.io/langgraph/how-tos/create-react-agent-memory/): LLM should read this page when adding memory to ReAct agents, implementing thread-level persistence in LangGraph, or building stateful conversational agents. This guide demonstrates how to add memory to a ReAct agent using LangGraph's checkpointer interface, with code examples showing MemorySaver implementation, thread_id configuration, and persistent chat context across multiple interactions.
|
||||
|
||||
[How to return structured output from the prebuilt ReAct agent](https://langchain-ai.github.io/langgraph/how-tos/create-react-agent-structured-output/): LLM should read this page when implementing structured output with ReAct agents, customizing agent response formats, or working with LangGraph agents. This page explains how to return structured output from prebuilt ReAct agents by providing a response_format parameter with a Pydantic schema, including examples with weather data and options for customizing the prompt.
|
||||
|
||||
[How to add a custom system prompt to the prebuilt ReAct agent](https://langchain-ai.github.io/langgraph/how-tos/create-react-agent-system-prompt/): LLM should read this page when learning to customize ReAct agents, needing to add system prompts to agents, or working with LangGraph's prebuilt agents. This tutorial demonstrates how to add a custom system prompt to a prebuilt ReAct agent, with code examples showing model setup, tool creation, and using the prompt parameter in the create_react_agent function.
|
||||
|
||||
[How to add cross-thread persistence to your graph](https://langchain-ai.github.io/langgraph/how-tos/cross-thread-persistence): LLM should read this page when needing to implement persistence across multiple threads in LangGraph, when storing user data between conversations, or when implementing shared memory in graph-based LLM applications. This page demonstrates how to use LangGraph's Store API to persist data across threads, including creating an InMemoryStore with embedding search capabilities, passing stores to graph nodes, and accessing user-specific memories in different conversation threads.
|
||||
|
||||
[How to add cross-thread persistence (functional API)](https://langchain-ai.github.io/langgraph/how-tos/cross-thread-persistence-functional): LLM should read this page when needing to implement cross-thread persistence in LangGraph functional API, storing user data across different conversation threads, or creating shared memory between workflows. This page explains how to add cross-thread persistence to LangGraph using the Store interface, including defining a store, configuring the entrypoint decorator, and implementing a workflow that can store and retrieve user information across different conversation threads.
|
||||
|
||||
[How to do a Self-hosted deployment of LangGraph](https://langchain-ai.github.io/langgraph/how-tos/deploy-self-hosted/): LLM should read this page when implementing a self-hosted deployment of LangGraph, configuring required environment variables, or building Docker images for LangGraph applications. This page explains how to deploy LangGraph applications using Docker, covering environment requirements (Redis, Postgres), how to build Docker images with the LangGraph CLI, configuration using environment variables, and deployment options using Docker or Docker Compose.
|
||||
|
||||
[How to disable streaming for models that don't support it](https://langchain-ai.github.io/langgraph/how-tos/disable-streaming/): LLM should read this page when handling models that don't support streaming, implementing LangGraph with non-streaming models, or troubleshooting streaming errors with OpenAI's O1 models. This page explains how to use the disable_streaming=True parameter with ChatOpenAI to make non-streaming models work with LangGraph's astream_events API, with code examples showing the error case and proper implementation.
|
||||
|
||||
[How to edit graph state](https://langchain-ai.github.io/langgraph/how-tos/human_in_the_loop/edit-graph-state/): LLM should read this page when needing to implement human intervention in LangGraph workflows, wanting to edit graph state during execution, or implementing breakpoints in agent systems. This page explains how to edit graph state in LangGraph using breakpoints, including implementing human-in-the-loop interactions, setting up interruptions before specific nodes, and updating state during agent execution.
|
||||
|
||||
[How to Review Tool Calls](https://langchain-ai.github.io/langgraph/how-tos/human_in_the_loop/review-tool-calls/): LLM should read this page when implementing human review of tool calls, creating interactive agent workflows, or building approval systems for AI actions. This page explains how to implement human-in-the-loop review for tool calls in LangGraph, including approving tool calls, modifying tool calls manually, and providing natural language feedback to agents with complete code examples and explanations.
|
||||
|
||||
[How to view and update past graph state](https://langchain-ai.github.io/langgraph/how-tos/human_in_the_loop/time-travel/): LLM should read this page when needing to access or modify past states in LangGraph, when debugging agent execution, or when implementing user interventions in agent workflows. This page demonstrates how to view and update past graph states in LangGraph using get_state and update_state methods, with examples of replaying execution from checkpoints and branching workflows.
|
||||
|
||||
[How to wait for user input using interrupt](https://langchain-ai.github.io/langgraph/how-tos/human_in_the_loop/wait-user-input/): LLM should read this page when implementing wait-for-user functions in LangGraph, implementing human-in-the-loop interactions, or learning how to use the interrupt() function. This page explains how to pause graph execution to collect user input using LangGraph's interrupt() function, with examples of simple feedback collection and more complex agent interactions that ask clarifying questions.
|
||||
|
||||
[How to define input/output schema for your graph](https://langchain-ai.github.io/langgraph/how-tos/input_output_schema/): LLM should read this page when needing to define separate input/output schemas for LangGraph, implementing schema-based data filtering, or understanding schema definitions in StateGraph. This page explains how to define distinct input and output schemas for a StateGraph, showing how input schema validates the provided data structure while output schema filters internal data to return only relevant information, with code examples demonstrating implementation.
|
||||
|
||||
[How to handle large numbers of tools](https://langchain-ai.github.io/langgraph/how-tos/many-tools/): LLM should read this page when handling large tool collections, implementing dynamic tool selection, or creating retrieval-based tool management in LangGraph. This page demonstrates how to manage large numbers of tools by using vector search to dynamically select relevant tools based on user queries, implementing tool selection nodes in LangGraph, and handling tool selection errors with retry mechanisms.
|
||||
|
||||
[How to create map-reduce branches for parallel execution](https://langchain-ai.github.io/langgraph/how-tos/map-reduce/): LLM should read this page when learning to implement parallel execution in LangGraph, creating map-reduce operations, or handling dynamic task decomposition. This guide explains how to use LangGraph's Send API to create map-reduce workflows, breaking tasks into parallel sub-tasks and recombining results, with examples showing joke generation across multiple subjects.
|
||||
|
||||
[How to add summary of the conversation history](https://langchain-ai.github.io/langgraph/how-tos/memory/add-summary-conversation-history/): LLM should read this page when implementing conversation summarization, managing context windows, or building chatbots with memory management. This page demonstrates how to add summary functionality to conversation history using LangGraph, including checking conversation length, creating summaries, and removing old messages while maintaining context.
|
||||
|
||||
[How to delete messages](https://langchain-ai.github.io/langgraph/how-tos/memory/delete-messages): LLM should read this page when attempting to manage message history in LangGraph, needing to delete specific messages from conversational state, or implementing memory management in LLM applications. This page explains how to delete messages from a LangGraph application using RemoveMessage modifiers, covering both manual deletion with message IDs and programmatic deletion within graph logic to maintain conversation history limits.
|
||||
|
||||
[How to manage conversation history](https://langchain-ai.github.io/langgraph/how-tos/memory/manage-conversation-history/): LLM should read this page when managing conversation history in LangGraph, preventing context window issues, or implementing custom message filtering. This page explains how to manage conversation history in LangGraph to prevent context window overflow by implementing message filtering functions that control which messages are sent to the LLM.
|
||||
|
||||
[How to add semantic search to your agent's memory](https://langchain-ai.github.io/langgraph/how-tos/memory/semantic-search/): LLM should read this page when implementing semantic search in agent memory, enabling memory-aware AI assistants, or configuring advanced memory retrieval systems. This page demonstrates how to add semantic search to LangGraph agent memory stores, covering basic setup with embeddings, storing memories, searching by semantic similarity, integrating memory in agents and ReAct agents, and advanced usage like multi-vector indexing and selective memory indexing.
|
||||
|
||||
[How to add multi-turn conversation in a multi-agent application](https://langchain-ai.github.io/langgraph/how-tos/multi-agent-multi-turn-convo/): LLM should read this page when implementing multi-turn conversations between agents, creating interactive agent systems with human input, or learning about langgraph interrupts and agent handoffs. This page demonstrates how to build a multi-agent system with multi-turn conversations, including human-in-the-loop interactions, agent handoffs, and state management using LangGraph, Command objects, and interrupts.
|
||||
|
||||
[How to add multi-turn conversation in a multi-agent application (functional API)](https://langchain-ai.github.io/langgraph/how-tos/multi-agent-multi-turn-convo-functional/): LLM should read this page when building multi-turn conversational agents, implementing agent-to-agent handoffs, or using interrupts to collect user input in LangGraph. This guide demonstrates how to create a multi-agent system with multi-turn conversations using LangGraph's functional API, featuring agent handoffs, interrupt mechanics for user input, and a complete example of travel and hotel advisor agents that can transfer control between each other.
|
||||
|
||||
[How to build a multi-agent network](https://langchain-ai.github.io/langgraph/how-tos/multi-agent-network/): LLM should read this page when implementing multi-agent networks, setting up agent communication via handoffs, or building travel assistance agents. This page explains how to create a fully-connected multi-agent network with LangGraph where agents can communicate with each other via handoffs, including custom agent implementation and using prebuilt ReAct agents with tools.
|
||||
|
||||
[How to build a multi-agent network (functional API)](https://langchain-ai.github.io/langgraph/how-tos/multi-agent-network-functional/): LLM should read this page when building multi-agent systems, implementing agent handoffs between specialists, or creating fully-connected agent networks. This guide demonstrates how to create a multi-agent network using LangGraph's functional API, with tasks for individual agents and entrypoint functions to manage agent handoffs based on tool calls.
|
||||
|
||||
[How to add node retry policies](https://langchain-ai.github.io/langgraph/how-tos/node-retries/): LLM should read this page when implementing error handling in LangGraph nodes, configuring API retry mechanisms, or troubleshooting node failures in graph workflows. Shows how to add custom retry policies to LangGraph nodes, including specifying which exceptions to retry on, setting max attempts, intervals, backoff factors, and implementing different retry behaviors for different node types.
|
||||
|
||||
[How to pass config to tools](https://langchain-ai.github.io/langgraph/how-tos/pass-config-to-tools/): LLM should read this page when implementing secure tool configuration in LangChain, passing user-specific parameters to tools, or configuring tools with runtime values. This page explains how to pass configuration to LangChain tools using RunnableConfig, allowing application-controlled values (like user IDs) to be securely passed to tools without LLM control, with examples of implementing tools that access user-specific data.
|
||||
|
||||
[How to pass private state between nodes](https://langchain-ai.github.io/langgraph/how-tos/pass_private_state/): LLM should read this page when implementing data sharing between specific nodes in LangGraph, handling private state in graph workflows, or designing multi-node sequential processes with selective data visibility. This page demonstrates how to pass private data between specific nodes in a LangGraph without making it part of the main schema, using typed dictionaries to define both public and private states, and showing a three-node example where private data flows only between the first two nodes.
|
||||
|
||||
[How to add thread-level persistence to your graph](https://langchain-ai.github.io/langgraph/how-tos/persistence/): LLM should read this page when implementing persistence in LangGraph, needing to preserve context across user interactions, or learning about thread-level state management. This page explains how to add thread-level persistence to LangGraph applications using MemorySaver, including code examples for creating stateful conversations where context is maintained across multiple interactions.
|
||||
|
||||
[How to add thread-level persistence (functional API)](https://langchain-ai.github.io/langgraph/how-tos/persistence-functional/): LLM should read this page when implementing thread-level persistence in LangGraph, creating conversational agents with memory, or using functional API with state management. This page explains how to add thread-level persistence to LangGraph functional API workflows using checkpointers, including code examples for creating a simple chatbot with memory across conversation turns.
|
||||
|
||||
[How to use MongoDB checkpointer for persistence](https://langchain-ai.github.io/langgraph/how-tos/persistence_mongodb/): LLM should read this page when implementing persistence in LangGraph agents, setting up MongoDB for state checkpointing, or working with MongoDB connections in LangGraph applications. This page explains how to use the MongoDB checkpointer for LangGraph persistence, covering connection methods (direct, client-based, async), basic setup requirements, and practical examples of saving and retrieving agent state between interactions.
|
||||
|
||||
[How to use Postgres checkpointer for persistence](https://langchain-ai.github.io/langgraph/how-tos/persistence_postgres/): LLM should read this page when setting up persistence for LangGraph agents, implementing PostgreSQL as a checkpoint storage backend, or working with either synchronous or asynchronous database connections. This page details how to use PostgreSQL for persisting LangGraph agent state, covering setup and configuration of PostgresSaver and AsyncPostgresSaver with different connection methods (pool, direct connection, connection string).
|
||||
|
||||
[How to create a custom checkpointer using Redis](https://langchain-ai.github.io/langgraph/how-tos/persistence_redis/): LLM should read this page when implementing persistence in LangGraph applications, creating custom checkpoint mechanisms for agents, or working with Redis as a storage backend. This page demonstrates how to create custom checkpointers for LangGraph agents using Redis, including implementations for both synchronous and asynchronous interfaces that save and retrieve agent state.
|
||||
|
||||
[How to create a ReAct agent from scratch](https://langchain-ai.github.io/langgraph/how-tos/react-agent-from-scratch/): LLM should read this page when needing to create a custom ReAct agent, wanting more control than prebuilt agents, or implementing ReAct from scratch with LangGraph. This guide shows how to build a custom ReAct agent using LangGraph, covering state definition, model/tool setup, node/edge configuration, graph creation, and testing the implementation with a weather query example.
|
||||
|
||||
[How to create a ReAct agent from scratch (Functional API)](https://langchain-ai.github.io/langgraph/how-tos/react-agent-from-scratch-functional): LLM should read this page when creating a ReAct agent using LangGraph's Functional API, implementing tool-calling workflows, or building conversational agents with thread persistence. This page explains how to build a ReAct agent from scratch using LangGraph's Functional API, including model and tool setup, defining tasks for model/tool calling, creating an entrypoint for orchestration, and adding thread-level persistence for conversational experiences.
|
||||
|
||||
[How to force tool-calling agent to structure output](https://langchain-ai.github.io/langgraph/how-tos/react-agent-structured-output): LLM should read this page when needing to force tool-calling agents to produce structured output, implementing consistent output formats for downstream software, or choosing between single-LLM vs two-LLM structured output approaches. The page explains two methods for implementing structured output with tool-calling agents: binding output as a tool (single LLM approach) and using two LLMs with structured output conversion, with code examples for both approaches using LangGraph.
|
||||
|
||||
[How to create and control loops](https://langchain-ai.github.io/langgraph/how-tos/recursion-limit/): LLM should read this page when building loops in computational graphs, needing to implement termination conditions, or handling recursion limits in LangGraph. The page explains how to create graphs with loops using conditional edges for termination, set recursion limits, handle GraphRecursionError, and implement complex loops with branches.
|
||||
|
||||
[How to review tool calls (Functional API)](https://langchain-ai.github.io/langgraph/how-tos/review-tool-calls-functional/): LLM should read this page when implementing human review of tool calls, creating ReAct agents with Functional API, or adding human-in-the-loop workflows. This page demonstrates how to review tool calls before execution in a ReAct agent using LangGraph's Functional API, including accepting, revising, or generating custom tool messages with the interrupt function.
|
||||
|
||||
[How to pass custom run ID or set tags and metadata for graph runs in LangSmith](https://langchain-ai.github.io/langgraph/how-tos/run-id-langsmith/): LLM should read this page when needing to customize trace information in LangSmith for LangGraph runs or when debugging graph runs with custom identifiers. The page explains how to pass custom run_id, set tags, add metadata, and customize run names for LangGraph traces in LangSmith using RunnableConfig, with examples showing implementation with a ReAct agent.
|
||||
|
||||
[How to create a sequence of steps](https://langchain-ai.github.io/langgraph/how-tos/sequence/): LLM should read this page when implementing sequential workflows in LangGraph, creating multi-step processes in applications, or learning about state management in graph-based systems. This page explains how to create sequences in LangGraph, covering methods for building sequential graphs using .add_node/.add_edge or the shorthand .add_sequence, defining state with TypedDict, creating nodes as functions that update state, and compiling/invoking graphs with examples.
|
||||
|
||||
[How to use Pydantic model as graph state](https://langchain-ai.github.io/langgraph/how-tos/state-model): LLM should read this page when implementing Pydantic models for state validation in LangGraph, handling complex state schema definitions, or troubleshooting validation errors in graph nodes. This guide explains how to use Pydantic BaseModel as a state schema in LangGraph for runtime validation, covering basic implementation, limitations, validation behavior across multiple nodes, serialization patterns, type coercion, and working with message models.
|
||||
|
||||
[How to update graph state from nodes](https://langchain-ai.github.io/langgraph/how-tos/state-reducers/): LLM should read this page when needing to update state in LangGraph, designing graphs with nodes that modify state, or implementing reducers for state management. This page explains how to define state schemas in LangGraph using TypedDict, how nodes can update state, and how to use reducers to control state updates, with specific examples using message handling.
|
||||
|
||||
[How to stream](https://langchain-ai.github.io/langgraph/how-tos/streaming/): LLM should read this page when needing to implement streaming in LangGraph applications, understanding different streaming modes, or troubleshooting LLM response delivery. This page explains how to stream LLM outputs using LangGraph, covering different streaming modes (values, updates, custom, messages, debug), with code examples for each mode and how to combine multiple streaming modes.
|
||||
|
||||
[How to stream data from within a tool](https://langchain-ai.github.io/langgraph/how-tos/streaming-events-from-within-tools/): LLM should read this page when implementing streaming functionality in tools, integrating LLM outputs with custom data streams, or developing LangGraph applications with real-time feedback. This page explains how to stream data from within tools using LangGraph, covering custom data streaming with stream_mode="custom", LLM token streaming with stream_mode="messages", and implementation approaches both with and without LangChain.
|
||||
|
||||
[How to stream LLM tokens from specific nodes](https://langchain-ai.github.io/langgraph/how-tos/streaming-specific-nodes/): LLM should read this page when needing to filter token streaming from specific nodes in LangGraph, implementing selective streaming in multi-node workflows, or controlling which node outputs are displayed. Guide explains how to stream LLM tokens from specific nodes using stream_mode="messages" and filtering by the langgraph_node metadata field, with complete code examples for implementing this in StateGraph applications.
|
||||
|
||||
[How to stream from subgraphs](https://langchain-ai.github.io/langgraph/how-tos/streaming-subgraphs/): LLM should read this page when needing to stream outputs from subgraphs in LangGraph, implementing nested graph streaming, or debugging hierarchical graph execution. This page explains how to stream outputs from subgraphs in LangGraph by using the subgraphs=True parameter in the parent graph's stream() method, with a complete code example showing the difference between regular streaming and subgraph streaming.
|
||||
|
||||
[How to stream LLM tokens from your graph](https://langchain-ai.github.io/langgraph/how-tos/streaming-tokens): LLM should read this page when needing to stream LLM tokens from a LangGraph application, implementing custom token streaming, or filtering streamed outputs. This page explains how to stream individual LLM tokens from LangGraph nodes using graph.stream() with different stream_mode options, including examples with and without LangChain, async implementations, and how to filter streamed tokens using metadata.
|
||||
|
||||
[How to use subgraphs](https://langchain-ai.github.io/langgraph/how-tos/subgraph/): LLM should read this page when building complex systems with subgraphs, implementing multi-agent systems, or needing to share state between parent graphs and subgraphs. The page explains two methods for using subgraphs: adding compiled subgraphs when schemas share keys, and invoking subgraphs via node functions when schemas differ, with code examples for both approaches.
|
||||
|
||||
[How to add thread-level persistence to a subgraph](https://langchain-ai.github.io/langgraph/how-tos/subgraph-persistence/): LLM should read this page when implementing persistence in nested LangGraph architectures, adding thread-level storage to subgraphs, or debugging state propagation in LangGraph applications. This guide demonstrates how to add thread-level persistence to subgraphs by passing a checkpointer only to the parent graph during compilation, accessing persisted states from both parent and child graphs, and retrieving subgraph state using the proper configuration parameters.
|
||||
|
||||
[How to transform inputs and outputs of a subgraph](https://langchain-ai.github.io/langgraph/how-tos/subgraph-transform-state/): LLM should read this page when needing to work with nested subgraphs, transforming state between parent and child graphs, or integrating independent state components in LangGraph. This page demonstrates how to transform inputs and outputs between parent graphs and subgraphs with different state structures, showing implementation of three nested graphs (parent, child, grandchild) with separate state dictionaries and transformation functions.
|
||||
|
||||
[How to view and update state in subgraphs](https://langchain-ai.github.io/langgraph/how-tos/subgraphs-manage-state/): LLM should read this page when working with state management in nested subgraphs, implementing human-in-the-loop patterns, or debugging complex graph flows. This guide covers viewing and updating state in LangGraph subgraphs, including how to resume execution from breakpoints, modify subgraph state, act as specific nodes, and work with multi-level nested subgraphs.
|
||||
|
||||
[How to call tools using ToolNode](https://langchain-ai.github.io/langgraph/how-tos/tool-calling/): LLM should read this page when learning how to implement tool calling with LangGraph, when working with the ToolNode component, or when building ReAct agents. This page covers using LangGraph's ToolNode for tool calling, including setup, manual invocation, working with chat models, building a ReAct agent, handling single and parallel tool calls, and error handling.
|
||||
|
||||
[How to handle tool calling errors](https://langchain-ai.github.io/langgraph/how-tos/tool-calling-errors/): LLM should read this page when handling tool call errors, implementing error handling for LLM-tool interactions, or creating fallback strategies for failed tool calls. This page covers strategies for handling tool calling errors in LangGraph, including using the prebuilt ToolNode with built-in error handling, implementing custom error handling patterns, and fallback mechanisms with model upgrades when tools fail.
|
||||
|
||||
[How to update graph state from tools](https://langchain-ai.github.io/langgraph/how-tos/update-state-from-tools/): LLM should read this page when needing to update graph state from tools in LangGraph, implementing personalized responses based on tool updates, or using Command objects to modify state. This page details how to update graph state from tools using Command objects, creating personalized agents with state tracking, and implementing dynamic prompt construction based on updated state values.
|
||||
|
||||
[How to interact with the deployment using RemoteGraph](https://langchain-ai.github.io/langgraph/how-tos/use-remote-graph/): LLM should read this page when needing to interact with LangGraph Platform deployments remotely, when implementing RemoteGraph interfaces, or when using deployed graphs as subgraphs. This page explains how to use RemoteGraph to interact with LangGraph Platform deployments, covering initialization methods (URL-based or client-based), synchronous/asynchronous invocation, thread-level persistence, and using RemoteGraph as a subgraph in larger applications.
|
||||
|
||||
[How to visualize your graph](https://langchain-ai.github.io/langgraph/how-tos/visualization): LLM should read this page when needing to visualize LangGraph graphs, looking for graph visualization methods, or working with graph visualization in Python. Comprehensive guide for visualizing graphs in LangGraph with multiple methods: Mermaid syntax, Mermaid.ink API for PNG rendering, Pyppeteer-based visualization, and Graphviz, with customization options for colors, styles, and layout.
|
||||
|
||||
[How to wait for user input (Functional API)](https://langchain-ai.github.io/langgraph/how-tos/wait-user-input-functional/): LLM should read this page when implementing human-in-the-loop workflows, integrating user input into agent systems, or adding interruption capabilities to LangGraph applications. The page explains how to use the `interrupt()` function in LangGraph's Functional API to pause execution for human input, with examples for both simple workflows and ReAct agents, including code implementations with checkpointing.
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user