langgraph-sdk 0.4.2__tar.gz → 0.4.4__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (145) hide show
  1. {langgraph_sdk-0.4.2 → langgraph_sdk-0.4.4}/.gitignore +5 -0
  2. {langgraph_sdk-0.4.2 → langgraph_sdk-0.4.4}/CHANGELOG.md +9 -0
  3. {langgraph_sdk-0.4.2 → langgraph_sdk-0.4.4}/MIGRATION.md +3 -1
  4. {langgraph_sdk-0.4.2 → langgraph_sdk-0.4.4}/Makefile +0 -1
  5. {langgraph_sdk-0.4.2 → langgraph_sdk-0.4.4}/PKG-INFO +38 -15
  6. langgraph_sdk-0.4.4/README.md +98 -0
  7. {langgraph_sdk-0.4.2 → langgraph_sdk-0.4.4}/integration/Dockerfile +13 -0
  8. {langgraph_sdk-0.4.2 → langgraph_sdk-0.4.4}/integration/docker-compose.yml +10 -3
  9. langgraph_sdk-0.4.4/integration/graph/factory_graph.py +70 -0
  10. {langgraph_sdk-0.4.2 → langgraph_sdk-0.4.4}/integration/langgraph.json +2 -1
  11. langgraph_sdk-0.4.4/langgraph_sdk/__init__.py +15 -0
  12. {langgraph_sdk-0.4.2 → langgraph_sdk-0.4.4}/langgraph_sdk/_async/cron.py +12 -4
  13. {langgraph_sdk-0.4.2 → langgraph_sdk-0.4.4}/langgraph_sdk/_async/stream.py +4 -1
  14. {langgraph_sdk-0.4.2 → langgraph_sdk-0.4.4}/langgraph_sdk/_sync/cron.py +12 -4
  15. {langgraph_sdk-0.4.2 → langgraph_sdk-0.4.4}/langgraph_sdk/_sync/stream.py +4 -1
  16. {langgraph_sdk-0.4.2 → langgraph_sdk-0.4.4}/langgraph_sdk/auth/__init__.py +69 -19
  17. {langgraph_sdk-0.4.2 → langgraph_sdk-0.4.4}/langgraph_sdk/encryption/__init__.py +12 -5
  18. {langgraph_sdk-0.4.2 → langgraph_sdk-0.4.4}/langgraph_sdk/encryption/types.py +30 -4
  19. {langgraph_sdk-0.4.2 → langgraph_sdk-0.4.4}/langgraph_sdk/schema.py +1 -1
  20. {langgraph_sdk-0.4.2 → langgraph_sdk-0.4.4}/pyproject.toml +8 -5
  21. {langgraph_sdk-0.4.2 → langgraph_sdk-0.4.4}/tests/integration/conftest.py +6 -4
  22. {langgraph_sdk-0.4.2 → langgraph_sdk-0.4.4}/tests/integration/test_assistants.py +5 -4
  23. {langgraph_sdk-0.4.2 → langgraph_sdk-0.4.4}/tests/integration/test_cancel.py +5 -4
  24. {langgraph_sdk-0.4.2 → langgraph_sdk-0.4.4}/tests/integration/test_crons.py +5 -4
  25. langgraph_sdk-0.4.4/tests/integration/test_factory_graph.py +66 -0
  26. {langgraph_sdk-0.4.2 → langgraph_sdk-0.4.4}/tests/integration/test_runs.py +5 -4
  27. {langgraph_sdk-0.4.2 → langgraph_sdk-0.4.4}/tests/integration/test_store.py +5 -4
  28. {langgraph_sdk-0.4.2 → langgraph_sdk-0.4.4}/tests/integration/test_websocket.py +5 -4
  29. {langgraph_sdk-0.4.2 → langgraph_sdk-0.4.4}/tests/streaming/test_controller.py +9 -15
  30. {langgraph_sdk-0.4.2 → langgraph_sdk-0.4.4}/tests/streaming/test_decoders.py +2 -1
  31. {langgraph_sdk-0.4.2 → langgraph_sdk-0.4.4}/tests/streaming/test_extensions_projection.py +1 -2
  32. {langgraph_sdk-0.4.2 → langgraph_sdk-0.4.4}/tests/streaming/test_lifecycle_watcher.py +2 -2
  33. {langgraph_sdk-0.4.2 → langgraph_sdk-0.4.4}/tests/streaming/test_scoped_handles.py +4 -10
  34. {langgraph_sdk-0.4.2 → langgraph_sdk-0.4.4}/tests/streaming/test_shared_stream.py +3 -11
  35. {langgraph_sdk-0.4.2 → langgraph_sdk-0.4.4}/tests/streaming/test_sync_extensions_projection.py +1 -2
  36. {langgraph_sdk-0.4.2 → langgraph_sdk-0.4.4}/tests/streaming/test_sync_projections.py +3 -7
  37. {langgraph_sdk-0.4.2 → langgraph_sdk-0.4.4}/tests/streaming/test_sync_scoped_handles.py +2 -2
  38. {langgraph_sdk-0.4.2 → langgraph_sdk-0.4.4}/tests/streaming/test_sync_thread_stream.py +29 -88
  39. {langgraph_sdk-0.4.2 → langgraph_sdk-0.4.4}/tests/streaming/test_sync_transport_ws.py +2 -3
  40. {langgraph_sdk-0.4.2 → langgraph_sdk-0.4.4}/tests/streaming/test_thread_stream.py +16 -67
  41. {langgraph_sdk-0.4.2 → langgraph_sdk-0.4.4}/tests/streaming/test_tool_calls_projection.py +3 -5
  42. {langgraph_sdk-0.4.2 → langgraph_sdk-0.4.4}/tests/streaming/test_transport_http.py +10 -42
  43. {langgraph_sdk-0.4.2 → langgraph_sdk-0.4.4}/tests/streaming/test_transport_ws.py +2 -4
  44. langgraph_sdk-0.4.4/tests/test_auth.py +132 -0
  45. {langgraph_sdk-0.4.2 → langgraph_sdk-0.4.4}/tests/test_client_stream.py +5 -5
  46. {langgraph_sdk-0.4.2 → langgraph_sdk-0.4.4}/tests/test_crons_client.py +49 -0
  47. {langgraph_sdk-0.4.2 → langgraph_sdk-0.4.4}/tests/test_encryption.py +32 -0
  48. {langgraph_sdk-0.4.2 → langgraph_sdk-0.4.4}/tests/test_langsmith_tracing.py +2 -5
  49. {langgraph_sdk-0.4.2 → langgraph_sdk-0.4.4}/tests/test_path_encoding.py +2 -1
  50. {langgraph_sdk-0.4.2 → langgraph_sdk-0.4.4}/tests/test_serde.py +1 -1
  51. langgraph_sdk-0.4.4/uv.lock +1547 -0
  52. langgraph_sdk-0.4.2/README.md +0 -75
  53. langgraph_sdk-0.4.2/langgraph_sdk/__init__.py +0 -8
  54. langgraph_sdk-0.4.2/uv.lock +0 -1662
  55. {langgraph_sdk-0.4.2 → langgraph_sdk-0.4.4}/LICENSE +0 -0
  56. {langgraph_sdk-0.4.2 → langgraph_sdk-0.4.4}/integration/graph/__init__.py +0 -0
  57. {langgraph_sdk-0.4.2 → langgraph_sdk-0.4.4}/integration/graph/deep_agent.py +0 -0
  58. {langgraph_sdk-0.4.2 → langgraph_sdk-0.4.4}/integration/graph/streaming_graph.py +0 -0
  59. {langgraph_sdk-0.4.2 → langgraph_sdk-0.4.4}/integration/graph/tools_agent.py +0 -0
  60. {langgraph_sdk-0.4.2 → langgraph_sdk-0.4.4}/integration/scripts/_common.py +0 -0
  61. {langgraph_sdk-0.4.2 → langgraph_sdk-0.4.4}/integration/scripts/test_cancel.py +0 -0
  62. {langgraph_sdk-0.4.2 → langgraph_sdk-0.4.4}/integration/scripts/test_concurrent.py +0 -0
  63. {langgraph_sdk-0.4.2 → langgraph_sdk-0.4.4}/integration/scripts/test_extensions.py +0 -0
  64. {langgraph_sdk-0.4.2 → langgraph_sdk-0.4.4}/integration/scripts/test_helpers.py +0 -0
  65. {langgraph_sdk-0.4.2 → langgraph_sdk-0.4.4}/integration/scripts/test_lifecycle.py +0 -0
  66. {langgraph_sdk-0.4.2 → langgraph_sdk-0.4.4}/integration/scripts/test_messages.py +0 -0
  67. {langgraph_sdk-0.4.2 → langgraph_sdk-0.4.4}/integration/scripts/test_reconnect.py +0 -0
  68. {langgraph_sdk-0.4.2 → langgraph_sdk-0.4.4}/integration/scripts/test_subgraphs.py +0 -0
  69. {langgraph_sdk-0.4.2 → langgraph_sdk-0.4.4}/integration/scripts/test_tools.py +0 -0
  70. {langgraph_sdk-0.4.2 → langgraph_sdk-0.4.4}/integration/scripts/test_update_state.py +0 -0
  71. {langgraph_sdk-0.4.2 → langgraph_sdk-0.4.4}/integration/scripts/test_values.py +0 -0
  72. {langgraph_sdk-0.4.2 → langgraph_sdk-0.4.4}/integration/scripts/test_websocket.py +0 -0
  73. {langgraph_sdk-0.4.2 → langgraph_sdk-0.4.4}/langgraph_sdk/_async/__init__.py +0 -0
  74. {langgraph_sdk-0.4.2 → langgraph_sdk-0.4.4}/langgraph_sdk/_async/assistants.py +0 -0
  75. {langgraph_sdk-0.4.2 → langgraph_sdk-0.4.4}/langgraph_sdk/_async/client.py +0 -0
  76. {langgraph_sdk-0.4.2 → langgraph_sdk-0.4.4}/langgraph_sdk/_async/http.py +0 -0
  77. {langgraph_sdk-0.4.2 → langgraph_sdk-0.4.4}/langgraph_sdk/_async/runs.py +0 -0
  78. {langgraph_sdk-0.4.2 → langgraph_sdk-0.4.4}/langgraph_sdk/_async/store.py +0 -0
  79. {langgraph_sdk-0.4.2 → langgraph_sdk-0.4.4}/langgraph_sdk/_async/threads.py +0 -0
  80. {langgraph_sdk-0.4.2 → langgraph_sdk-0.4.4}/langgraph_sdk/_shared/__init__.py +0 -0
  81. {langgraph_sdk-0.4.2 → langgraph_sdk-0.4.4}/langgraph_sdk/_shared/types.py +0 -0
  82. {langgraph_sdk-0.4.2 → langgraph_sdk-0.4.4}/langgraph_sdk/_shared/utilities.py +0 -0
  83. {langgraph_sdk-0.4.2 → langgraph_sdk-0.4.4}/langgraph_sdk/_sync/__init__.py +0 -0
  84. {langgraph_sdk-0.4.2 → langgraph_sdk-0.4.4}/langgraph_sdk/_sync/assistants.py +0 -0
  85. {langgraph_sdk-0.4.2 → langgraph_sdk-0.4.4}/langgraph_sdk/_sync/client.py +0 -0
  86. {langgraph_sdk-0.4.2 → langgraph_sdk-0.4.4}/langgraph_sdk/_sync/http.py +0 -0
  87. {langgraph_sdk-0.4.2 → langgraph_sdk-0.4.4}/langgraph_sdk/_sync/runs.py +0 -0
  88. {langgraph_sdk-0.4.2 → langgraph_sdk-0.4.4}/langgraph_sdk/_sync/store.py +0 -0
  89. {langgraph_sdk-0.4.2 → langgraph_sdk-0.4.4}/langgraph_sdk/_sync/threads.py +0 -0
  90. {langgraph_sdk-0.4.2 → langgraph_sdk-0.4.4}/langgraph_sdk/auth/exceptions.py +0 -0
  91. {langgraph_sdk-0.4.2 → langgraph_sdk-0.4.4}/langgraph_sdk/auth/types.py +0 -0
  92. {langgraph_sdk-0.4.2 → langgraph_sdk-0.4.4}/langgraph_sdk/cache.py +0 -0
  93. {langgraph_sdk-0.4.2 → langgraph_sdk-0.4.4}/langgraph_sdk/client.py +0 -0
  94. {langgraph_sdk-0.4.2 → langgraph_sdk-0.4.4}/langgraph_sdk/errors.py +0 -0
  95. {langgraph_sdk-0.4.2 → langgraph_sdk-0.4.4}/langgraph_sdk/py.typed +0 -0
  96. {langgraph_sdk-0.4.2 → langgraph_sdk-0.4.4}/langgraph_sdk/runtime.py +0 -0
  97. {langgraph_sdk-0.4.2 → langgraph_sdk-0.4.4}/langgraph_sdk/sse.py +0 -0
  98. {langgraph_sdk-0.4.2 → langgraph_sdk-0.4.4}/langgraph_sdk/stream/__init__.py +0 -0
  99. {langgraph_sdk-0.4.2 → langgraph_sdk-0.4.4}/langgraph_sdk/stream/controller.py +0 -0
  100. {langgraph_sdk-0.4.2 → langgraph_sdk-0.4.4}/langgraph_sdk/stream/decoders.py +0 -0
  101. {langgraph_sdk-0.4.2 → langgraph_sdk-0.4.4}/langgraph_sdk/stream/multi_cursor_buffer.py +0 -0
  102. {langgraph_sdk-0.4.2 → langgraph_sdk-0.4.4}/langgraph_sdk/stream/subscription.py +0 -0
  103. {langgraph_sdk-0.4.2 → langgraph_sdk-0.4.4}/langgraph_sdk/stream/sync_controller.py +0 -0
  104. {langgraph_sdk-0.4.2 → langgraph_sdk-0.4.4}/langgraph_sdk/stream/transport/__init__.py +0 -0
  105. {langgraph_sdk-0.4.2 → langgraph_sdk-0.4.4}/langgraph_sdk/stream/transport/base.py +0 -0
  106. {langgraph_sdk-0.4.2 → langgraph_sdk-0.4.4}/langgraph_sdk/stream/transport/http.py +0 -0
  107. {langgraph_sdk-0.4.2 → langgraph_sdk-0.4.4}/langgraph_sdk/stream/transport/sync_http.py +0 -0
  108. {langgraph_sdk-0.4.2 → langgraph_sdk-0.4.4}/langgraph_sdk/stream/transport/sync_ws.py +0 -0
  109. {langgraph_sdk-0.4.2 → langgraph_sdk-0.4.4}/langgraph_sdk/stream/transport/ws.py +0 -0
  110. {langgraph_sdk-0.4.2 → langgraph_sdk-0.4.4}/tests/fixtures/response.txt +0 -0
  111. {langgraph_sdk-0.4.2 → langgraph_sdk-0.4.4}/tests/integration/__init__.py +0 -0
  112. {langgraph_sdk-0.4.2 → langgraph_sdk-0.4.4}/tests/integration/test_concurrent.py +0 -0
  113. {langgraph_sdk-0.4.2 → langgraph_sdk-0.4.4}/tests/integration/test_extensions.py +0 -0
  114. {langgraph_sdk-0.4.2 → langgraph_sdk-0.4.4}/tests/integration/test_helpers.py +0 -0
  115. {langgraph_sdk-0.4.2 → langgraph_sdk-0.4.4}/tests/integration/test_lifecycle.py +0 -0
  116. {langgraph_sdk-0.4.2 → langgraph_sdk-0.4.4}/tests/integration/test_messages.py +0 -0
  117. {langgraph_sdk-0.4.2 → langgraph_sdk-0.4.4}/tests/integration/test_reconnect.py +0 -0
  118. {langgraph_sdk-0.4.2 → langgraph_sdk-0.4.4}/tests/integration/test_remote_graph_v3.py +0 -0
  119. {langgraph_sdk-0.4.2 → langgraph_sdk-0.4.4}/tests/integration/test_subgraphs.py +0 -0
  120. {langgraph_sdk-0.4.2 → langgraph_sdk-0.4.4}/tests/integration/test_threads_crud.py +0 -0
  121. {langgraph_sdk-0.4.2 → langgraph_sdk-0.4.4}/tests/integration/test_tools.py +0 -0
  122. {langgraph_sdk-0.4.2 → langgraph_sdk-0.4.4}/tests/integration/test_update_state.py +0 -0
  123. {langgraph_sdk-0.4.2 → langgraph_sdk-0.4.4}/tests/integration/test_values.py +0 -0
  124. {langgraph_sdk-0.4.2 → langgraph_sdk-0.4.4}/tests/streaming/__init__.py +0 -0
  125. {langgraph_sdk-0.4.2 → langgraph_sdk-0.4.4}/tests/streaming/_events.py +0 -0
  126. {langgraph_sdk-0.4.2 → langgraph_sdk-0.4.4}/tests/streaming/_fake_server.py +0 -0
  127. {langgraph_sdk-0.4.2 → langgraph_sdk-0.4.4}/tests/streaming/_sync_fake_server.py +0 -0
  128. {langgraph_sdk-0.4.2 → langgraph_sdk-0.4.4}/tests/streaming/assert_transport_replays.py +0 -0
  129. {langgraph_sdk-0.4.2 → langgraph_sdk-0.4.4}/tests/streaming/test_messages_projection.py +0 -0
  130. {langgraph_sdk-0.4.2 → langgraph_sdk-0.4.4}/tests/streaming/test_multi_cursor_buffer.py +0 -0
  131. {langgraph_sdk-0.4.2 → langgraph_sdk-0.4.4}/tests/streaming/test_output.py +0 -0
  132. {langgraph_sdk-0.4.2 → langgraph_sdk-0.4.4}/tests/streaming/test_replay_conformance.py +0 -0
  133. {langgraph_sdk-0.4.2 → langgraph_sdk-0.4.4}/tests/streaming/test_subscription.py +0 -0
  134. {langgraph_sdk-0.4.2 → langgraph_sdk-0.4.4}/tests/streaming/test_sync_shared_stream.py +0 -0
  135. {langgraph_sdk-0.4.2 → langgraph_sdk-0.4.4}/tests/streaming/test_sync_transport_http.py +0 -0
  136. {langgraph_sdk-0.4.2 → langgraph_sdk-0.4.4}/tests/streaming/test_transport_path_encoding.py +0 -0
  137. {langgraph_sdk-0.4.2 → langgraph_sdk-0.4.4}/tests/streaming/test_values_projection.py +0 -0
  138. {langgraph_sdk-0.4.2 → langgraph_sdk-0.4.4}/tests/test_api_parity.py +0 -0
  139. {langgraph_sdk-0.4.2 → langgraph_sdk-0.4.4}/tests/test_assistants_client.py +0 -0
  140. {langgraph_sdk-0.4.2 → langgraph_sdk-0.4.4}/tests/test_cache.py +0 -0
  141. {langgraph_sdk-0.4.2 → langgraph_sdk-0.4.4}/tests/test_client_exports.py +0 -0
  142. {langgraph_sdk-0.4.2 → langgraph_sdk-0.4.4}/tests/test_errors.py +0 -0
  143. {langgraph_sdk-0.4.2 → langgraph_sdk-0.4.4}/tests/test_serde_schema.py +0 -0
  144. {langgraph_sdk-0.4.2 → langgraph_sdk-0.4.4}/tests/test_skip_auto_load_api_key.py +0 -0
  145. {langgraph_sdk-0.4.2 → langgraph_sdk-0.4.4}/tests/test_threads_client.py +0 -0
@@ -77,6 +77,10 @@ __pypackages__/
77
77
  # Environments
78
78
  .env
79
79
  .envrc
80
+ *.crt
81
+ *.key
82
+ *.pem
83
+ credentials.json
80
84
  .venv
81
85
  .venvs
82
86
  env/
@@ -98,6 +102,7 @@ dmypy.json
98
102
 
99
103
  .vercel
100
104
  .turbo
105
+ node_modules/
101
106
  .editorconfig
102
107
  .scratch
103
108
  .worktrees/
@@ -39,6 +39,15 @@
39
39
  - `client.threads.stream()` now accepts `transport="sse"` (default) or
40
40
  `transport="websocket"` in place of the previous transport-agnostic default.
41
41
 
42
+ ### Fixed
43
+
44
+ - Resource-scoped auth decorators now honor `actions=` and reject empty or
45
+ invalid action lists. Because unmatched custom-auth paths remain allowed,
46
+ deployments using action-scoped handlers should configure a global
47
+ default-deny handler; `langgraph-api` 0.10+ warns about uncovered paths at
48
+ startup. Resource-specific decorators retain matching `resources=` selectors
49
+ for backward compatibility; use `@auth.on(resources=...)` for other resources.
50
+
42
51
  ### Notes
43
52
 
44
53
  - The v3 streaming surface (`AsyncThreadStream`, `SyncThreadStream`, and all
@@ -87,7 +87,9 @@ async with client.threads.stream(assistant_id="agent") as thread:
87
87
 
88
88
  ```python
89
89
  async with client.threads.stream(assistant_id="agent") as thread:
90
- await thread.run.start(input={"messages": [{"role": "user", "content": "book a flight"}]})
90
+ await thread.run.start(
91
+ input={"messages": [{"role": "user", "content": "book a flight"}]}
92
+ )
91
93
 
92
94
  # Wait for the run to pause at an interrupt node.
93
95
  # thread.interrupted becomes True when input.requested arrives.
@@ -9,7 +9,6 @@ test:
9
9
 
10
10
  # Define a variable for Python and notebook files.
11
11
  PYTHON_FILES=.
12
- MYPY_CACHE=.mypy_cache
13
12
  lint format: PYTHON_FILES=.
14
13
  lint_diff format_diff: PYTHON_FILES=$(shell git diff --name-only --relative --diff-filter=d main . | grep -E '\.py$$|\.ipynb$$')
15
14
 
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.4
1
+ Metadata-Version: 2.5
2
2
  Name: langgraph-sdk
3
- Version: 0.4.2
3
+ Version: 0.4.4
4
4
  Summary: SDK for interacting with LangGraph API
5
5
  Project-URL: Source, https://github.com/langchain-ai/langgraph/tree/main/libs/sdk-py
6
6
  Project-URL: Twitter, https://x.com/langchain_oss
@@ -13,23 +13,36 @@ Requires-Dist: httpx>=0.25.2
13
13
  Requires-Dist: langchain-core<2,>=1.4.0
14
14
  Requires-Dist: langchain-protocol>=0.0.15
15
15
  Requires-Dist: orjson>=3.11.5
16
- Requires-Dist: websockets<16,>=14
16
+ Requires-Dist: websockets<17,>=14
17
17
  Description-Content-Type: text/markdown
18
18
 
19
19
  # LangGraph Python SDK
20
20
 
21
- This repository contains the Python SDK for interacting with the LangSmith Deployment REST API.
21
+ [![PyPI - Version](https://img.shields.io/pypi/v/langgraph-sdk?label=%20)](https://pypi.org/project/langgraph-sdk/#history)
22
+ [![PyPI - License](https://img.shields.io/pypi/l/langgraph-sdk)](https://opensource.org/licenses/MIT)
23
+ [![PyPI - Downloads](https://img.shields.io/pepy/dt/langgraph-sdk)](https://pypistats.org/packages/langgraph-sdk)
24
+ [![Twitter](https://img.shields.io/twitter/url/https/twitter.com/langchain_oss.svg?style=social&label=Follow%20%40LangChain)](https://x.com/langchain_oss)
22
25
 
23
- ## Quick Start
26
+ To help you ship LangGraph apps to production faster, check out [LangSmith](https://www.langchain.com/langsmith).
27
+ [LangSmith](https://www.langchain.com/langsmith) is a unified developer platform for building, testing, and monitoring LLM applications.
24
28
 
25
- To get started with the Python SDK, [install the package](https://pypi.org/project/langgraph-sdk/)
29
+ ## Quick Install
26
30
 
27
31
  ```bash
28
- pip install -U langgraph-sdk
32
+ uv add langgraph-sdk
29
33
  ```
30
34
 
31
- You will need a running LangGraph API server. If you're running a server locally using `langgraph-cli`, SDK will automatically point at `http://localhost:8123`, otherwise
32
- you would need to specify the server URL when creating a client.
35
+ ## 🤔 What is this?
36
+
37
+ This library provides the Python SDK for interacting with the LangGraph API. Use it to connect to a running LangGraph API server, manage assistants and threads, and stream runs from Python applications.
38
+
39
+ You will need a running LangGraph API server. If you're running a server locally using `langgraph-cli`, the SDK will automatically point at `http://localhost:8123`; otherwise, specify the server URL when creating a client.
40
+
41
+ ## 📖 Documentation
42
+
43
+ For full documentation, see the [API reference](https://reference.langchain.com/python/langgraph-sdk/). For conceptual guides and tutorials, see the [LangGraph Docs](https://docs.langchain.com/oss/python/langgraph/overview).
44
+
45
+ ## Quick Start
33
46
 
34
47
  ```python
35
48
  from langgraph_sdk import get_client
@@ -48,7 +61,9 @@ thread = await client.threads.create()
48
61
 
49
62
  # Start a streaming run
50
63
  input = {"messages": [{"role": "human", "content": "what's the weather in la"}]}
51
- async for chunk in client.runs.stream(thread['thread_id'], agent['assistant_id'], input=input):
64
+ async for chunk in client.runs.stream(
65
+ thread["thread_id"], agent["assistant_id"], input=input
66
+ ):
52
67
  print(chunk)
53
68
  ```
54
69
 
@@ -61,9 +76,7 @@ async for chunk in client.runs.stream(thread['thread_id'], agent['assistant_id']
61
76
 
62
77
  ## Thread-Centric Streaming (v3)
63
78
 
64
- `client.threads.stream()` returns a context manager that owns the SSE session for one
65
- thread. Typed projections — values snapshots, message streams, tool calls, custom
66
- events — all share the same underlying connection.
79
+ `client.threads.stream()` returns a context manager that owns the SSE session for one thread. Typed projections — values snapshots, message streams, tool calls, custom events — all share the same underlying connection.
67
80
 
68
81
  ```python
69
82
  from langgraph_sdk import get_client
@@ -87,7 +100,17 @@ async with client.threads.stream(
87
100
  messages, tool_calls = await asyncio.gather(get_messages(), get_tool_calls())
88
101
 
89
102
  for stream in messages:
90
- print(await stream.text) # accumulated text
103
+ print(await stream.text) # accumulated text
91
104
 
92
- final = await thread.output # terminal state values
105
+ final = await thread.output # terminal state values
93
106
  ```
107
+
108
+ ## 📕 Releases & Versioning
109
+
110
+ See our [Releases](https://docs.langchain.com/oss/python/release-policy) and [Versioning](https://docs.langchain.com/oss/python/versioning) policies.
111
+
112
+ ## 💁 Contributing
113
+
114
+ As an open-source project in a rapidly developing field, we are extremely open to contributions, whether it be in the form of a new feature, improved infrastructure, or better documentation.
115
+
116
+ For detailed information on how to contribute, see the [Contributing Guide](https://docs.langchain.com/oss/python/contributing/overview).
@@ -0,0 +1,98 @@
1
+ # LangGraph Python SDK
2
+
3
+ [![PyPI - Version](https://img.shields.io/pypi/v/langgraph-sdk?label=%20)](https://pypi.org/project/langgraph-sdk/#history)
4
+ [![PyPI - License](https://img.shields.io/pypi/l/langgraph-sdk)](https://opensource.org/licenses/MIT)
5
+ [![PyPI - Downloads](https://img.shields.io/pepy/dt/langgraph-sdk)](https://pypistats.org/packages/langgraph-sdk)
6
+ [![Twitter](https://img.shields.io/twitter/url/https/twitter.com/langchain_oss.svg?style=social&label=Follow%20%40LangChain)](https://x.com/langchain_oss)
7
+
8
+ To help you ship LangGraph apps to production faster, check out [LangSmith](https://www.langchain.com/langsmith).
9
+ [LangSmith](https://www.langchain.com/langsmith) is a unified developer platform for building, testing, and monitoring LLM applications.
10
+
11
+ ## Quick Install
12
+
13
+ ```bash
14
+ uv add langgraph-sdk
15
+ ```
16
+
17
+ ## 🤔 What is this?
18
+
19
+ This library provides the Python SDK for interacting with the LangGraph API. Use it to connect to a running LangGraph API server, manage assistants and threads, and stream runs from Python applications.
20
+
21
+ You will need a running LangGraph API server. If you're running a server locally using `langgraph-cli`, the SDK will automatically point at `http://localhost:8123`; otherwise, specify the server URL when creating a client.
22
+
23
+ ## 📖 Documentation
24
+
25
+ For full documentation, see the [API reference](https://reference.langchain.com/python/langgraph-sdk/). For conceptual guides and tutorials, see the [LangGraph Docs](https://docs.langchain.com/oss/python/langgraph/overview).
26
+
27
+ ## Quick Start
28
+
29
+ ```python
30
+ from langgraph_sdk import get_client
31
+
32
+ # If you're using a remote server, initialize the client with `get_client(url=REMOTE_URL)`
33
+ client = get_client()
34
+
35
+ # List all assistants
36
+ assistants = await client.assistants.search()
37
+
38
+ # We auto-create an assistant for each graph you register in config.
39
+ agent = assistants[0]
40
+
41
+ # Start a new thread
42
+ thread = await client.threads.create()
43
+
44
+ # Start a streaming run
45
+ input = {"messages": [{"role": "human", "content": "what's the weather in la"}]}
46
+ async for chunk in client.runs.stream(
47
+ thread["thread_id"], agent["assistant_id"], input=input
48
+ ):
49
+ print(chunk)
50
+ ```
51
+
52
+ ## Known Limitations
53
+
54
+ - **WebSocket transport** requires `websockets>=14` and is only available on the async client (`AsyncThreadStream`). The sync client (`SyncThreadStream`) uses SSE exclusively.
55
+ - **`thread.extensions[name]`** opens a new subscription each time the same name is accessed. Assign the projection to a variable and reuse it within a single session rather than re-indexing across multiple iterations.
56
+ - **Sync streaming** drives the lifecycle watcher in a background thread. Long-lived sync sessions will hold that thread open until the context manager exits.
57
+ - **Reconnect attempts** are limited to 5 by default for both the shared SSE fan-out and the lifecycle watcher. Persistent network partitions will surface as `RuntimeError` on in-flight projections.
58
+
59
+ ## Thread-Centric Streaming (v3)
60
+
61
+ `client.threads.stream()` returns a context manager that owns the SSE session for one thread. Typed projections — values snapshots, message streams, tool calls, custom events — all share the same underlying connection.
62
+
63
+ ```python
64
+ from langgraph_sdk import get_client
65
+ import asyncio
66
+
67
+ client = get_client()
68
+
69
+ async with client.threads.stream(
70
+ thread_id="my-thread",
71
+ assistant_id="agent",
72
+ ) as thread:
73
+ await thread.run.start(input={"messages": [{"role": "user", "content": "hi"}]})
74
+
75
+ # Start all consumers concurrently so they share one SSE connection.
76
+ async def get_messages():
77
+ return [s async for s in thread.messages]
78
+
79
+ async def get_tool_calls():
80
+ return [c async for c in thread.tool_calls]
81
+
82
+ messages, tool_calls = await asyncio.gather(get_messages(), get_tool_calls())
83
+
84
+ for stream in messages:
85
+ print(await stream.text) # accumulated text
86
+
87
+ final = await thread.output # terminal state values
88
+ ```
89
+
90
+ ## 📕 Releases & Versioning
91
+
92
+ See our [Releases](https://docs.langchain.com/oss/python/release-policy) and [Versioning](https://docs.langchain.com/oss/python/versioning) policies.
93
+
94
+ ## 💁 Contributing
95
+
96
+ As an open-source project in a rapidly developing field, we are extremely open to contributions, whether it be in the form of a new feature, improved infrastructure, or better documentation.
97
+
98
+ For detailed information on how to contribute, see the [Contributing Guide](https://docs.langchain.com/oss/python/contributing/overview).
@@ -22,6 +22,19 @@ RUN pip install --no-cache-dir \
22
22
  "langchain>=1.3.0" \
23
23
  "deepagents>=0.6.2"
24
24
 
25
+ # Swap the published langgraph *core* for this monorepo's local copy, so the
26
+ # server executes the langgraph under test rather than the latest release.
27
+ # We keep the rest of the base image (langgraph-api, runtime, Go core server)
28
+ # on `latest` — that still surfaces upstream regressions — but the core the
29
+ # server runs is now the PR's, which is what lets this suite catch core
30
+ # regressions (e.g. ensure_config / runtime changes) before they're published.
31
+ # `--no-deps` keeps the base image's already-compatible
32
+ # checkpoint/prebuilt/sdk; we only replace core. The local source comes from
33
+ # the `langgraph_src` additional build context (see docker-compose.yml).
34
+ COPY --from=langgraph_src pyproject.toml README.md LICENSE /opt/langgraph-src/
35
+ COPY --from=langgraph_src langgraph /opt/langgraph-src/langgraph/
36
+ RUN pip install --no-cache-dir --force-reinstall --no-deps /opt/langgraph-src
37
+
25
38
  # Project graphs + registration config.
26
39
  COPY graph/ /app/graph/
27
40
  COPY langgraph.json /app/langgraph.json
@@ -36,11 +36,18 @@ services:
36
36
  api:
37
37
  # Thin layer on top of langchain/langgraph-api:latest-py3.12 —
38
38
  # see ./Dockerfile. The base image bundles langgraph-api +
39
- # langgraph_runtime_postgres + langgraph_license + the Go core-server,
40
- # so we only add graph deps (deepagents) and the graph files on top.
39
+ # langgraph_runtime_postgres + langgraph_license + the Go core-server;
40
+ # on top we add graph deps (deepagents), the graph files, and this
41
+ # monorepo's local langgraph *core* (so the server runs the code under
42
+ # test, not the released langgraph).
41
43
  build:
42
44
  context: .
43
45
  dockerfile: Dockerfile
46
+ additional_contexts:
47
+ # The monorepo's local langgraph core (libs/langgraph), installed over
48
+ # the base image so the server runs the langgraph under test. See the
49
+ # Dockerfile for why.
50
+ langgraph_src: ../../langgraph
44
51
  image: langgraph-v3-integration-api:local
45
52
  depends_on:
46
53
  postgres:
@@ -70,7 +77,7 @@ services:
70
77
  # Tell langgraph-api which graphs to register. The langgraph CLI sets
71
78
  # this from langgraph.json; we're bypassing the CLI (running uvicorn
72
79
  # directly) so we set it manually.
73
- LANGSERVE_GRAPHS: '{"agent":"/app/graph/streaming_graph.py:graph","tools_agent":"/app/graph/tools_agent.py:graph","deep_agent":"/app/graph/deep_agent.py:graph"}'
80
+ LANGSERVE_GRAPHS: '{"agent":"/app/graph/streaming_graph.py:graph","tools_agent":"/app/graph/tools_agent.py:graph","deep_agent":"/app/graph/deep_agent.py:graph","factory_agent":"/app/graph/factory_graph.py:make_graph"}'
74
81
 
75
82
  # The published langgraph-api image is the `licensed` variant and
76
83
  # requires a real LANGSMITH_API_KEY (or LANGGRAPH_CLOUD_LICENSE_KEY)
@@ -0,0 +1,70 @@
1
+ """Integration fixture: a graph *factory* (not a pre-compiled graph).
2
+
3
+ Registered as `factory_agent`. The other integration graphs are all
4
+ pre-compiled objects, so this is the only fixture that drives the server's
5
+ graph-factory code path on a run. That path is where langgraph-api seeds a
6
+ `ServerRuntime` into the run config; executing a run against this graph is the
7
+ end-to-end regression guard for the langgraph 1.2.3 `ensure_config`
8
+ configurable-merge surfacing a leaked `__pregel_runtime`
9
+ (`AttributeError: '_ExecutionRuntime' object has no attribute 'control'`).
10
+ """
11
+
12
+ from __future__ import annotations
13
+
14
+ from typing import TYPE_CHECKING
15
+
16
+ from langgraph.graph.state import END, CompiledStateGraph, StateGraph
17
+ from langgraph.store.base import BaseStore
18
+ from typing_extensions import TypedDict
19
+
20
+ if TYPE_CHECKING:
21
+ from langgraph.types import RunnableConfig
22
+
23
+ from langgraph_sdk.runtime import ServerRuntime
24
+
25
+
26
+ class State(TypedDict, total=False):
27
+ text: str
28
+ access_context: str
29
+ is_for_execution: bool
30
+
31
+
32
+ async def make_graph(
33
+ config: RunnableConfig, runtime: ServerRuntime
34
+ ) -> CompiledStateGraph:
35
+ """2-arg factory (config + runtime) returning a compiled echo graph.
36
+
37
+ Validates that the server injected a real `ServerRuntime`, then builds a
38
+ one-node graph whose output echoes the input and reports the runtime's
39
+ access context (so the test can confirm the factory ran under execution).
40
+ """
41
+ from langgraph_sdk.runtime import (
42
+ _ExecutionRuntime,
43
+ _ReadRuntime,
44
+ )
45
+
46
+ # `if/raise` rather than `assert` so the contract holds under `python -O`.
47
+ if not isinstance(runtime, (_ExecutionRuntime, _ReadRuntime)):
48
+ raise TypeError(
49
+ f"factory must receive a ServerRuntime, got {type(runtime).__name__}"
50
+ )
51
+ if not isinstance(runtime.store, BaseStore):
52
+ raise TypeError(
53
+ f"runtime.store must be a BaseStore, got {type(runtime.store).__name__}"
54
+ )
55
+
56
+ access_context = runtime.access_context
57
+ is_for_execution = runtime.execution_runtime is not None
58
+
59
+ def echo(state: State) -> State:
60
+ return {
61
+ "text": (state.get("text") or "") + " echoed",
62
+ "access_context": access_context,
63
+ "is_for_execution": is_for_execution,
64
+ }
65
+
66
+ workflow = StateGraph(State)
67
+ workflow.add_node("echo", echo)
68
+ workflow.set_entry_point("echo")
69
+ workflow.add_edge("echo", END)
70
+ return workflow.compile()
@@ -4,7 +4,8 @@
4
4
  "graphs": {
5
5
  "agent": "./graph/streaming_graph.py:graph",
6
6
  "tools_agent": "./graph/tools_agent.py:graph",
7
- "deep_agent": "./graph/deep_agent.py:graph"
7
+ "deep_agent": "./graph/deep_agent.py:graph",
8
+ "factory_agent": "./graph/factory_graph.py:make_graph"
8
9
  },
9
10
  "env": {}
10
11
  }
@@ -0,0 +1,15 @@
1
+ from langgraph_sdk.auth import Auth
2
+ from langgraph_sdk.client import get_client, get_sync_client
3
+ from langgraph_sdk.encryption import Encryption
4
+ from langgraph_sdk.encryption.types import DecryptResult, EncryptionContext
5
+
6
+ __version__ = "0.4.4"
7
+
8
+ __all__ = [
9
+ "Auth",
10
+ "DecryptResult",
11
+ "Encryption",
12
+ "EncryptionContext",
13
+ "get_client",
14
+ "get_sync_client",
15
+ ]
@@ -8,7 +8,11 @@ from datetime import datetime, tzinfo
8
8
  from typing import Any
9
9
 
10
10
  from langgraph_sdk._async.http import HttpClient
11
- from langgraph_sdk._shared.utilities import _quote_path_param, _resolve_timezone
11
+ from langgraph_sdk._shared.utilities import (
12
+ NOT_PROVIDED,
13
+ _quote_path_param,
14
+ _resolve_timezone,
15
+ )
12
16
  from langgraph_sdk.schema import (
13
17
  All,
14
18
  Config,
@@ -324,7 +328,7 @@ class CronClient:
324
328
  cron_id: str,
325
329
  *,
326
330
  schedule: str | None = None,
327
- end_time: datetime | None = None,
331
+ end_time: datetime | None = NOT_PROVIDED,
328
332
  input: Input | None = None,
329
333
  metadata: Mapping[str, Any] | None = None,
330
334
  config: Config | None = None,
@@ -348,7 +352,8 @@ class CronClient:
348
352
  cron_id: The cron ID to update.
349
353
  schedule: The cron schedule to execute this job on.
350
354
  Schedules are interpreted in UTC unless a timezone is specified.
351
- end_time: The end date to stop running the cron.
355
+ end_time: The end date to stop running the cron. Pass ``None`` to
356
+ clear a previously set end time; omit to leave it unchanged.
352
357
  input: The input to the graph.
353
358
  metadata: Metadata to assign to the cron job runs.
354
359
  config: The configuration for the assistant.
@@ -386,7 +391,6 @@ class CronClient:
386
391
  """
387
392
  payload = {
388
393
  "schedule": schedule,
389
- "end_time": end_time.isoformat() if end_time else None,
390
394
  "input": input,
391
395
  "metadata": metadata,
392
396
  "config": config,
@@ -403,6 +407,10 @@ class CronClient:
403
407
  "durability": durability,
404
408
  }
405
409
  payload = {k: v for k, v in payload.items() if v is not None}
410
+ # An explicit end_time=None clears the end time; NOT_PROVIDED leaves it
411
+ # unchanged. Inject after the None-strip so the explicit null survives.
412
+ if end_time is not NOT_PROVIDED:
413
+ payload["end_time"] = end_time.isoformat() if end_time is not None else None
406
414
  return await self.http.patch(
407
415
  f"/runs/crons/{_quote_path_param(cron_id)}",
408
416
  json=payload,
@@ -24,7 +24,7 @@ from langchain_core.language_models.chat_model_stream import AsyncChatModelStrea
24
24
  from langchain_protocol import Event, SubscribeParams
25
25
 
26
26
  from langgraph_sdk._async.http import HttpClient
27
- from langgraph_sdk.schema import QueryParamTypes
27
+ from langgraph_sdk.schema import LangSmithTracing, QueryParamTypes
28
28
  from langgraph_sdk.stream.controller import _SeenEventIds
29
29
  from langgraph_sdk.stream.decoders import (
30
30
  DataDecoder,
@@ -172,6 +172,7 @@ class RunModule:
172
172
  input: Any = None,
173
173
  config: dict[str, Any] | None = None,
174
174
  metadata: dict[str, Any] | None = None,
175
+ langsmith_tracing: LangSmithTracing | None = None,
175
176
  ) -> dict[str, Any]:
176
177
  """Send `run.start` to the server. Returns the result (`{"run_id": ...}`)."""
177
178
  params: dict[str, Any] = {"assistant_id": self._owner.assistant_id}
@@ -181,6 +182,8 @@ class RunModule:
181
182
  params["config"] = config
182
183
  if metadata is not None:
183
184
  params["metadata"] = metadata
185
+ if langsmith_tracing is not None:
186
+ params["langsmith_tracer"] = langsmith_tracing
184
187
  loop = asyncio.get_running_loop()
185
188
  gate: asyncio.Future[None] = loop.create_future()
186
189
  self._owner._run_start_ready = gate
@@ -7,7 +7,11 @@ from collections.abc import Mapping, Sequence
7
7
  from datetime import datetime, tzinfo
8
8
  from typing import Any
9
9
 
10
- from langgraph_sdk._shared.utilities import _quote_path_param, _resolve_timezone
10
+ from langgraph_sdk._shared.utilities import (
11
+ NOT_PROVIDED,
12
+ _quote_path_param,
13
+ _resolve_timezone,
14
+ )
11
15
  from langgraph_sdk._sync.http import SyncHttpClient
12
16
  from langgraph_sdk.schema import (
13
17
  All,
@@ -313,7 +317,7 @@ class SyncCronClient:
313
317
  cron_id: str,
314
318
  *,
315
319
  schedule: str | None = None,
316
- end_time: datetime | None = None,
320
+ end_time: datetime | None = NOT_PROVIDED,
317
321
  input: Input | None = None,
318
322
  metadata: Mapping[str, Any] | None = None,
319
323
  config: Config | None = None,
@@ -337,7 +341,8 @@ class SyncCronClient:
337
341
  cron_id: The cron ID to update.
338
342
  schedule: The cron schedule to execute this job on.
339
343
  Schedules are interpreted in UTC unless a timezone is specified.
340
- end_time: The end date to stop running the cron.
344
+ end_time: The end date to stop running the cron. Pass ``None`` to
345
+ clear a previously set end time; omit to leave it unchanged.
341
346
  input: The input to the graph.
342
347
  metadata: Metadata to assign to the cron job runs.
343
348
  config: The configuration for the assistant.
@@ -375,7 +380,6 @@ class SyncCronClient:
375
380
  """
376
381
  payload = {
377
382
  "schedule": schedule,
378
- "end_time": end_time.isoformat() if end_time else None,
379
383
  "input": input,
380
384
  "metadata": metadata,
381
385
  "config": config,
@@ -392,6 +396,10 @@ class SyncCronClient:
392
396
  "durability": durability,
393
397
  }
394
398
  payload = {k: v for k, v in payload.items() if v is not None}
399
+ # An explicit end_time=None clears the end time; NOT_PROVIDED leaves it
400
+ # unchanged. Inject after the None-strip so the explicit null survives.
401
+ if end_time is not NOT_PROVIDED:
402
+ payload["end_time"] = end_time.isoformat() if end_time is not None else None
395
403
  return self.http.patch(
396
404
  f"/runs/crons/{_quote_path_param(cron_id)}",
397
405
  json=payload,
@@ -23,7 +23,7 @@ from langchain_core.language_models.chat_model_stream import ChatModelStream
23
23
  from langchain_protocol import Event, SubscribeParams
24
24
 
25
25
  from langgraph_sdk._sync.http import SyncHttpClient
26
- from langgraph_sdk.schema import QueryParamTypes
26
+ from langgraph_sdk.schema import LangSmithTracing, QueryParamTypes
27
27
  from langgraph_sdk.stream.decoders import (
28
28
  DataDecoder,
29
29
  Decoder,
@@ -215,6 +215,7 @@ class SyncRunModule:
215
215
  input: Any = None,
216
216
  config: dict[str, Any] | None = None,
217
217
  metadata: dict[str, Any] | None = None,
218
+ langsmith_tracing: LangSmithTracing | None = None,
218
219
  ) -> dict[str, Any]:
219
220
  """Send `run.start` to the server. Returns the result (`{"run_id": ...}`)."""
220
221
  params: dict[str, Any] = {"assistant_id": self._owner.assistant_id}
@@ -224,6 +225,8 @@ class SyncRunModule:
224
225
  params["config"] = config
225
226
  if metadata is not None:
226
227
  params["metadata"] = metadata
228
+ if langsmith_tracing is not None:
229
+ params["langsmith_tracer"] = langsmith_tracing
227
230
  result = self._owner._send_command("run.start", params)
228
231
  self._owner._run_seen = True
229
232
  controller = self._owner._controller