langgraph-cli 0.4.7__tar.gz → 0.4.8__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 (122) hide show
  1. {langgraph_cli-0.4.7 → langgraph_cli-0.4.8}/Makefile +4 -1
  2. {langgraph_cli-0.4.7 → langgraph_cli-0.4.8}/PKG-INFO +5 -2
  3. {langgraph_cli-0.4.7 → langgraph_cli-0.4.8}/generate_schema.py +6 -0
  4. langgraph_cli-0.4.8/langgraph_cli/__init__.py +1 -0
  5. {langgraph_cli-0.4.7 → langgraph_cli-0.4.8}/langgraph_cli/config.py +70 -0
  6. {langgraph_cli-0.4.7 → langgraph_cli-0.4.8}/langgraph_cli/schemas.py +132 -4
  7. {langgraph_cli-0.4.7 → langgraph_cli-0.4.8}/pyproject.toml +4 -1
  8. {langgraph_cli-0.4.7 → langgraph_cli-0.4.8}/schemas/schema.json +158 -6
  9. {langgraph_cli-0.4.7 → langgraph_cli-0.4.8}/schemas/schema.v0.json +158 -6
  10. {langgraph_cli-0.4.7 → langgraph_cli-0.4.8}/tests/unit_tests/test_config.py +137 -0
  11. {langgraph_cli-0.4.7 → langgraph_cli-0.4.8}/uv.lock +536 -416
  12. langgraph_cli-0.4.7/langgraph_cli/__init__.py +0 -1
  13. {langgraph_cli-0.4.7 → langgraph_cli-0.4.8}/.gitignore +0 -0
  14. {langgraph_cli-0.4.7 → langgraph_cli-0.4.8}/LICENSE +0 -0
  15. {langgraph_cli-0.4.7 → langgraph_cli-0.4.8}/README.md +0 -0
  16. {langgraph_cli-0.4.7 → langgraph_cli-0.4.8}/examples/.env.example +0 -0
  17. {langgraph_cli-0.4.7 → langgraph_cli-0.4.8}/examples/.gitignore +0 -0
  18. {langgraph_cli-0.4.7 → langgraph_cli-0.4.8}/examples/Makefile +0 -0
  19. {langgraph_cli-0.4.7 → langgraph_cli-0.4.8}/examples/graph_prerelease_reqs/agent.py +0 -0
  20. {langgraph_cli-0.4.7 → langgraph_cli-0.4.8}/examples/graph_prerelease_reqs/deps/additional_deps/pyproject.toml +0 -0
  21. {langgraph_cli-0.4.7 → langgraph_cli-0.4.8}/examples/graph_prerelease_reqs/deps/zuper_deps/pyproject.toml +0 -0
  22. {langgraph_cli-0.4.7 → langgraph_cli-0.4.8}/examples/graph_prerelease_reqs/langgraph.json +0 -0
  23. {langgraph_cli-0.4.7 → langgraph_cli-0.4.8}/examples/graph_prerelease_reqs/pyproject.toml +0 -0
  24. {langgraph_cli-0.4.7 → langgraph_cli-0.4.8}/examples/graph_prerelease_reqs_fail/agent.py +0 -0
  25. {langgraph_cli-0.4.7 → langgraph_cli-0.4.8}/examples/graph_prerelease_reqs_fail/langgraph.json +0 -0
  26. {langgraph_cli-0.4.7 → langgraph_cli-0.4.8}/examples/graph_prerelease_reqs_fail/pyproject.toml +0 -0
  27. {langgraph_cli-0.4.7 → langgraph_cli-0.4.8}/examples/graphs/agent.py +0 -0
  28. {langgraph_cli-0.4.7 → langgraph_cli-0.4.8}/examples/graphs/langgraph.json +0 -0
  29. {langgraph_cli-0.4.7 → langgraph_cli-0.4.8}/examples/graphs/storm.py +0 -0
  30. {langgraph_cli-0.4.7 → langgraph_cli-0.4.8}/examples/graphs_reqs_a/__init__.py +0 -0
  31. {langgraph_cli-0.4.7 → langgraph_cli-0.4.8}/examples/graphs_reqs_a/graphs_submod/__init__.py +0 -0
  32. {langgraph_cli-0.4.7 → langgraph_cli-0.4.8}/examples/graphs_reqs_a/graphs_submod/agent.py +0 -0
  33. {langgraph_cli-0.4.7 → langgraph_cli-0.4.8}/examples/graphs_reqs_a/graphs_submod/subprompt.txt +0 -0
  34. {langgraph_cli-0.4.7 → langgraph_cli-0.4.8}/examples/graphs_reqs_a/hello.py +0 -0
  35. {langgraph_cli-0.4.7 → langgraph_cli-0.4.8}/examples/graphs_reqs_a/langgraph.json +0 -0
  36. {langgraph_cli-0.4.7 → langgraph_cli-0.4.8}/examples/graphs_reqs_a/prompt.txt +0 -0
  37. {langgraph_cli-0.4.7 → langgraph_cli-0.4.8}/examples/graphs_reqs_a/requirements.txt +0 -0
  38. {langgraph_cli-0.4.7 → langgraph_cli-0.4.8}/examples/graphs_reqs_b/graphs_submod/agent.py +0 -0
  39. {langgraph_cli-0.4.7 → langgraph_cli-0.4.8}/examples/graphs_reqs_b/graphs_submod/subprompt.txt +0 -0
  40. {langgraph_cli-0.4.7 → langgraph_cli-0.4.8}/examples/graphs_reqs_b/hello.py +0 -0
  41. {langgraph_cli-0.4.7 → langgraph_cli-0.4.8}/examples/graphs_reqs_b/langgraph.json +0 -0
  42. {langgraph_cli-0.4.7 → langgraph_cli-0.4.8}/examples/graphs_reqs_b/prompt.txt +0 -0
  43. {langgraph_cli-0.4.7 → langgraph_cli-0.4.8}/examples/graphs_reqs_b/requirements.txt +0 -0
  44. {langgraph_cli-0.4.7 → langgraph_cli-0.4.8}/examples/graphs_reqs_b/utils/__init__.py +0 -0
  45. {langgraph_cli-0.4.7 → langgraph_cli-0.4.8}/examples/graphs_reqs_b/utils/greeter.py +0 -0
  46. {langgraph_cli-0.4.7 → langgraph_cli-0.4.8}/examples/langgraph.json +0 -0
  47. {langgraph_cli-0.4.7 → langgraph_cli-0.4.8}/examples/my_app.py +0 -0
  48. {langgraph_cli-0.4.7 → langgraph_cli-0.4.8}/examples/pipconf.txt +0 -0
  49. {langgraph_cli-0.4.7 → langgraph_cli-0.4.8}/examples/poetry.lock +0 -0
  50. {langgraph_cli-0.4.7 → langgraph_cli-0.4.8}/examples/pyproject.toml +0 -0
  51. {langgraph_cli-0.4.7 → langgraph_cli-0.4.8}/js-examples/.dockerignore +0 -0
  52. {langgraph_cli-0.4.7 → langgraph_cli-0.4.8}/js-examples/.env.example +0 -0
  53. {langgraph_cli-0.4.7 → langgraph_cli-0.4.8}/js-examples/.eslintrc.cjs +0 -0
  54. {langgraph_cli-0.4.7 → langgraph_cli-0.4.8}/js-examples/.gitignore +0 -0
  55. {langgraph_cli-0.4.7 → langgraph_cli-0.4.8}/js-examples/LICENSE +0 -0
  56. {langgraph_cli-0.4.7 → langgraph_cli-0.4.8}/js-examples/README.md +0 -0
  57. {langgraph_cli-0.4.7 → langgraph_cli-0.4.8}/js-examples/jest.config.js +0 -0
  58. {langgraph_cli-0.4.7 → langgraph_cli-0.4.8}/js-examples/langgraph.json +0 -0
  59. {langgraph_cli-0.4.7 → langgraph_cli-0.4.8}/js-examples/package.json +0 -0
  60. {langgraph_cli-0.4.7 → langgraph_cli-0.4.8}/js-examples/src/agent/graph.ts +0 -0
  61. {langgraph_cli-0.4.7 → langgraph_cli-0.4.8}/js-examples/src/agent/state.ts +0 -0
  62. {langgraph_cli-0.4.7 → langgraph_cli-0.4.8}/js-examples/static/studio.png +0 -0
  63. {langgraph_cli-0.4.7 → langgraph_cli-0.4.8}/js-examples/tests/agent.test.ts +0 -0
  64. {langgraph_cli-0.4.7 → langgraph_cli-0.4.8}/js-examples/tests/graph.int.test.ts +0 -0
  65. {langgraph_cli-0.4.7 → langgraph_cli-0.4.8}/js-examples/tsconfig.json +0 -0
  66. {langgraph_cli-0.4.7 → langgraph_cli-0.4.8}/js-examples/yarn.lock +0 -0
  67. {langgraph_cli-0.4.7 → langgraph_cli-0.4.8}/js-monorepo-example/.eslintrc.cjs +0 -0
  68. {langgraph_cli-0.4.7 → langgraph_cli-0.4.8}/js-monorepo-example/apps/agent/langgraph.json +0 -0
  69. {langgraph_cli-0.4.7 → langgraph_cli-0.4.8}/js-monorepo-example/apps/agent/package.json +0 -0
  70. {langgraph_cli-0.4.7 → langgraph_cli-0.4.8}/js-monorepo-example/apps/agent/src/graph.ts +0 -0
  71. {langgraph_cli-0.4.7 → langgraph_cli-0.4.8}/js-monorepo-example/apps/agent/src/state.ts +0 -0
  72. {langgraph_cli-0.4.7 → langgraph_cli-0.4.8}/js-monorepo-example/apps/agent/tsconfig.json +0 -0
  73. {langgraph_cli-0.4.7 → langgraph_cli-0.4.8}/js-monorepo-example/libs/shared/package.json +0 -0
  74. {langgraph_cli-0.4.7 → langgraph_cli-0.4.8}/js-monorepo-example/libs/shared/src/index.ts +0 -0
  75. {langgraph_cli-0.4.7 → langgraph_cli-0.4.8}/js-monorepo-example/libs/shared/tsconfig.json +0 -0
  76. {langgraph_cli-0.4.7 → langgraph_cli-0.4.8}/js-monorepo-example/package.json +0 -0
  77. {langgraph_cli-0.4.7 → langgraph_cli-0.4.8}/js-monorepo-example/tsconfig.json +0 -0
  78. {langgraph_cli-0.4.7 → langgraph_cli-0.4.8}/js-monorepo-example/turbo.json +0 -0
  79. {langgraph_cli-0.4.7 → langgraph_cli-0.4.8}/js-monorepo-example/yarn.lock +0 -0
  80. {langgraph_cli-0.4.7 → langgraph_cli-0.4.8}/langgraph_cli/__main__.py +0 -0
  81. {langgraph_cli-0.4.7 → langgraph_cli-0.4.8}/langgraph_cli/analytics.py +0 -0
  82. {langgraph_cli-0.4.7 → langgraph_cli-0.4.8}/langgraph_cli/cli.py +0 -0
  83. {langgraph_cli-0.4.7 → langgraph_cli-0.4.8}/langgraph_cli/constants.py +0 -0
  84. {langgraph_cli-0.4.7 → langgraph_cli-0.4.8}/langgraph_cli/docker.py +0 -0
  85. {langgraph_cli-0.4.7 → langgraph_cli-0.4.8}/langgraph_cli/exec.py +0 -0
  86. {langgraph_cli-0.4.7 → langgraph_cli-0.4.8}/langgraph_cli/progress.py +0 -0
  87. {langgraph_cli-0.4.7 → langgraph_cli-0.4.8}/langgraph_cli/py.typed +0 -0
  88. {langgraph_cli-0.4.7 → langgraph_cli-0.4.8}/langgraph_cli/templates.py +0 -0
  89. {langgraph_cli-0.4.7 → langgraph_cli-0.4.8}/langgraph_cli/util.py +0 -0
  90. {langgraph_cli-0.4.7 → langgraph_cli-0.4.8}/langgraph_cli/version.py +0 -0
  91. {langgraph_cli-0.4.7 → langgraph_cli-0.4.8}/python-monorepo-example/apps/agent/.env.example +0 -0
  92. {langgraph_cli-0.4.7 → langgraph_cli-0.4.8}/python-monorepo-example/apps/agent/langgraph.json +0 -0
  93. {langgraph_cli-0.4.7 → langgraph_cli-0.4.8}/python-monorepo-example/apps/agent/pyproject.toml +0 -0
  94. {langgraph_cli-0.4.7 → langgraph_cli-0.4.8}/python-monorepo-example/apps/agent/src/agent/__init__.py +0 -0
  95. {langgraph_cli-0.4.7 → langgraph_cli-0.4.8}/python-monorepo-example/apps/agent/src/agent/graph.py +0 -0
  96. {langgraph_cli-0.4.7 → langgraph_cli-0.4.8}/python-monorepo-example/apps/agent/src/agent/state.py +0 -0
  97. {langgraph_cli-0.4.7 → langgraph_cli-0.4.8}/python-monorepo-example/libs/common/__init__.py +0 -0
  98. {langgraph_cli-0.4.7 → langgraph_cli-0.4.8}/python-monorepo-example/libs/common/helpers.py +0 -0
  99. {langgraph_cli-0.4.7 → langgraph_cli-0.4.8}/python-monorepo-example/libs/shared/pyproject.toml +0 -0
  100. {langgraph_cli-0.4.7 → langgraph_cli-0.4.8}/python-monorepo-example/libs/shared/src/shared/__init__.py +0 -0
  101. {langgraph_cli-0.4.7 → langgraph_cli-0.4.8}/python-monorepo-example/libs/shared/src/shared/utils.py +0 -0
  102. {langgraph_cli-0.4.7 → langgraph_cli-0.4.8}/python-monorepo-example/pyproject.toml +0 -0
  103. {langgraph_cli-0.4.7 → langgraph_cli-0.4.8}/schemas/version.schema.json +0 -0
  104. {langgraph_cli-0.4.7 → langgraph_cli-0.4.8}/tests/__init__.py +0 -0
  105. {langgraph_cli-0.4.7 → langgraph_cli-0.4.8}/tests/integration_tests/__init__.py +0 -0
  106. {langgraph_cli-0.4.7 → langgraph_cli-0.4.8}/tests/integration_tests/test_cli.py +0 -0
  107. {langgraph_cli-0.4.7 → langgraph_cli-0.4.8}/tests/unit_tests/__init__.py +0 -0
  108. {langgraph_cli-0.4.7 → langgraph_cli-0.4.8}/tests/unit_tests/agent.py +0 -0
  109. {langgraph_cli-0.4.7 → langgraph_cli-0.4.8}/tests/unit_tests/cli/__init__.py +0 -0
  110. {langgraph_cli-0.4.7 → langgraph_cli-0.4.8}/tests/unit_tests/cli/langgraph.json +0 -0
  111. {langgraph_cli-0.4.7 → langgraph_cli-0.4.8}/tests/unit_tests/cli/pyproject.toml +0 -0
  112. {langgraph_cli-0.4.7 → langgraph_cli-0.4.8}/tests/unit_tests/cli/test_cli.py +0 -0
  113. {langgraph_cli-0.4.7 → langgraph_cli-0.4.8}/tests/unit_tests/cli/test_templates.py +0 -0
  114. {langgraph_cli-0.4.7 → langgraph_cli-0.4.8}/tests/unit_tests/conftest.py +0 -0
  115. {langgraph_cli-0.4.7 → langgraph_cli-0.4.8}/tests/unit_tests/graphs/agent.py +0 -0
  116. {langgraph_cli-0.4.7 → langgraph_cli-0.4.8}/tests/unit_tests/helpers.py +0 -0
  117. {langgraph_cli-0.4.7 → langgraph_cli-0.4.8}/tests/unit_tests/multiplatform/js.mts +0 -0
  118. {langgraph_cli-0.4.7 → langgraph_cli-0.4.8}/tests/unit_tests/multiplatform/python.py +0 -0
  119. {langgraph_cli-0.4.7 → langgraph_cli-0.4.8}/tests/unit_tests/pipconfig.txt +0 -0
  120. {langgraph_cli-0.4.7 → langgraph_cli-0.4.8}/tests/unit_tests/test_config.json +0 -0
  121. {langgraph_cli-0.4.7 → langgraph_cli-0.4.8}/tests/unit_tests/test_docker.py +0 -0
  122. {langgraph_cli-0.4.7 → langgraph_cli-0.4.8}/tests/unit_tests/test_util.py +0 -0
@@ -1,4 +1,4 @@
1
- .PHONY: test lint format test-integration update-schema
1
+ .PHONY: test lint format test-integration update-schema bump-version
2
2
 
3
3
  ######################
4
4
  # TESTING AND COVERAGE
@@ -35,3 +35,6 @@ format format_diff:
35
35
 
36
36
  update-schema:
37
37
  uv run python generate_schema.py
38
+
39
+ bump-version:
40
+ uv run hatch version patch
@@ -1,8 +1,11 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: langgraph-cli
3
- Version: 0.4.7
3
+ Version: 0.4.8
4
4
  Summary: CLI for interacting with LangGraph API
5
- Project-URL: Repository, https://www.github.com/langchain-ai/langgraph
5
+ Project-URL: Source, https://github.com/langchain-ai/langgraph/tree/main/libs/cli
6
+ Project-URL: Twitter, https://x.com/LangChainAI
7
+ Project-URL: Slack, https://www.langchain.com/join-community
8
+ Project-URL: Reddit, https://www.reddit.com/r/LangChain/
6
9
  License-Expression: MIT
7
10
  License-File: LICENSE
8
11
  Requires-Python: >=3.10
@@ -15,6 +15,7 @@ import msgspec
15
15
 
16
16
  from langgraph_cli.schemas import (
17
17
  AuthConfig,
18
+ CacheConfig,
18
19
  CheckpointerConfig,
19
20
  Config,
20
21
  ConfigurableHeaderConfig,
@@ -26,6 +27,8 @@ from langgraph_cli.schemas import (
26
27
  StoreConfig,
27
28
  ThreadTTLConfig,
28
29
  TTLConfig,
30
+ WebhooksConfig,
31
+ WebhookUrlPolicy,
29
32
  )
30
33
 
31
34
 
@@ -111,11 +114,14 @@ def add_descriptions_to_schema(schema, cls):
111
114
  SecurityConfig,
112
115
  HttpConfig,
113
116
  CorsConfig,
117
+ CacheConfig,
114
118
  ThreadTTLConfig,
115
119
  CheckpointerConfig,
116
120
  SerdeConfig,
117
121
  TTLConfig,
118
122
  ConfigurableHeaderConfig,
123
+ WebhooksConfig,
124
+ WebhookUrlPolicy,
119
125
  ]:
120
126
  if potential_cls.__name__ == def_name:
121
127
  add_descriptions_to_schema(def_schema, potential_cls)
@@ -0,0 +1 @@
1
+ __version__ = "0.4.8"
@@ -154,7 +154,10 @@ def validate_config(config: Config) -> Config:
154
154
  "env": config.get("env", {}),
155
155
  "store": config.get("store"),
156
156
  "auth": config.get("auth"),
157
+ "encryption": config.get("encryption"),
157
158
  "http": config.get("http"),
159
+ # Pass through webhooks config so it can be injected into the image
160
+ "webhooks": config.get("webhooks"),
158
161
  "checkpointer": config.get("checkpointer"),
159
162
  "ui": config.get("ui"),
160
163
  "ui_config": config.get("ui_config"),
@@ -228,6 +231,14 @@ def validate_config(config: Config) -> Config:
228
231
  f"Invalid auth.path format: '{auth_conf['path']}'. "
229
232
  "Must be in format './path/to/file.py:attribute_name'"
230
233
  )
234
+ # Validate encryption config
235
+ if encryption_conf := config.get("encryption"):
236
+ if "path" in encryption_conf:
237
+ if ":" not in encryption_conf["path"]:
238
+ raise ValueError(
239
+ f"Invalid encryption.path format: '{encryption_conf['path']}'. "
240
+ "Must be in format './path/to/file.py:attribute_name'"
241
+ )
231
242
  if http_conf := config.get("http"):
232
243
  if "app" in http_conf:
233
244
  if ":" not in http_conf["app"]:
@@ -614,6 +625,49 @@ def _update_auth_path(
614
625
  )
615
626
 
616
627
 
628
+ def _update_encryption_path(
629
+ config_path: pathlib.Path, config: Config, local_deps: LocalDeps
630
+ ) -> None:
631
+ """Update encryption.path to use Docker container paths."""
632
+ encryption_conf = config.get("encryption")
633
+ if not encryption_conf or not (path_str := encryption_conf.get("path")):
634
+ return
635
+
636
+ module_str, sep, attr_str = path_str.partition(":")
637
+ if not sep or not module_str.startswith("."):
638
+ return # Already validated or absolute path
639
+
640
+ resolved = config_path.parent / module_str
641
+ if not resolved.exists():
642
+ raise FileNotFoundError(
643
+ f"Encryption file not found: {resolved} (from {path_str})"
644
+ )
645
+ if not resolved.is_file():
646
+ raise IsADirectoryError(f"Encryption path must be a file: {resolved}")
647
+
648
+ # Check faux packages first (higher priority)
649
+ for faux_path, (_, destpath) in local_deps.faux_pkgs.items():
650
+ if resolved.is_relative_to(faux_path):
651
+ new_path = f"{destpath}/{resolved.relative_to(faux_path)}:{attr_str}"
652
+ encryption_conf["path"] = new_path
653
+ return
654
+
655
+ # Check real packages
656
+ for real_path in local_deps.real_pkgs:
657
+ if resolved.is_relative_to(real_path):
658
+ new_path = (
659
+ f"/deps/{real_path.name}/{resolved.relative_to(real_path)}:{attr_str}"
660
+ )
661
+ encryption_conf["path"] = new_path
662
+ return
663
+
664
+ raise ValueError(
665
+ f"Encryption file '{resolved}' not covered by dependencies.\n"
666
+ "Add its parent directory to the 'dependencies' array in your config.\n"
667
+ f"Current dependencies: {config['dependencies']}"
668
+ )
669
+
670
+
617
671
  def _update_http_app_path(
618
672
  config_path: pathlib.Path, config: Config, local_deps: LocalDeps
619
673
  ) -> None:
@@ -809,6 +863,8 @@ def python_config_to_docker(
809
863
  _update_graph_paths(config_path, config, local_deps)
810
864
  # Rewrite auth path, so it points to the correct location in the Docker container
811
865
  _update_auth_path(config_path, config, local_deps)
866
+ # Rewrite encryption path, so it points to the correct location in the Docker container
867
+ _update_encryption_path(config_path, config, local_deps)
812
868
  # Rewrite HTTP app path, so it points to the correct location in the Docker container
813
869
  _update_http_app_path(config_path, config, local_deps)
814
870
 
@@ -899,9 +955,16 @@ ADD {relpath} /deps/{name}
899
955
  if (auth_config := config.get("auth")) is not None:
900
956
  env_vars.append(f"ENV LANGGRAPH_AUTH='{json.dumps(auth_config)}'")
901
957
 
958
+ if (encryption_config := config.get("encryption")) is not None:
959
+ env_vars.append(f"ENV LANGGRAPH_ENCRYPTION='{json.dumps(encryption_config)}'")
960
+
902
961
  if (http_config := config.get("http")) is not None:
903
962
  env_vars.append(f"ENV LANGGRAPH_HTTP='{json.dumps(http_config)}'")
904
963
 
964
+ # Inject webhooks configuration if provided
965
+ if (webhooks_config := config.get("webhooks")) is not None:
966
+ env_vars.append(f"ENV LANGGRAPH_WEBHOOKS='{json.dumps(webhooks_config)}'")
967
+
905
968
  if (checkpointer_config := config.get("checkpointer")) is not None:
906
969
  env_vars.append(
907
970
  f"ENV LANGGRAPH_CHECKPOINTER='{json.dumps(checkpointer_config)}'"
@@ -1022,9 +1085,16 @@ def node_config_to_docker(
1022
1085
  if (auth_config := config.get("auth")) is not None:
1023
1086
  env_vars.append(f"ENV LANGGRAPH_AUTH='{json.dumps(auth_config)}'")
1024
1087
 
1088
+ if (encryption_config := config.get("encryption")) is not None:
1089
+ env_vars.append(f"ENV LANGGRAPH_ENCRYPTION='{json.dumps(encryption_config)}'")
1090
+
1025
1091
  if (http_config := config.get("http")) is not None:
1026
1092
  env_vars.append(f"ENV LANGGRAPH_HTTP='{json.dumps(http_config)}'")
1027
1093
 
1094
+ # Inject webhooks configuration if provided
1095
+ if (webhooks_config := config.get("webhooks")) is not None:
1096
+ env_vars.append(f"ENV LANGGRAPH_WEBHOOKS='{json.dumps(webhooks_config)}'")
1097
+
1028
1098
  if (checkpointer_config := config.get("checkpointer")) is not None:
1029
1099
  env_vars.append(
1030
1100
  f"ENV LANGGRAPH_CHECKPOINTER='{json.dumps(checkpointer_config)}'"
@@ -233,6 +233,27 @@ class SecurityConfig(TypedDict, total=False):
233
233
  """
234
234
 
235
235
 
236
+ class CacheConfig(TypedDict, total=False):
237
+ cache_keys: list[str]
238
+ """Optional. List of header keys to use for caching.
239
+
240
+ Example:
241
+ ["user_id", "workspace_id"]
242
+ """
243
+ ttl_seconds: int
244
+ """Optional. Time-to-live in seconds for cached items.
245
+
246
+ Example:
247
+ 3600
248
+ """
249
+ max_size: int
250
+ """Optional. Maximum size of the cache.
251
+
252
+ Example:
253
+ 100
254
+ """
255
+
256
+
236
257
  class AuthConfig(TypedDict, total=False):
237
258
  """Configuration for custom authentication logic and how it integrates into the OpenAPI spec."""
238
259
 
@@ -269,6 +290,37 @@ class AuthConfig(TypedDict, total=False):
269
290
  ]
270
291
  }
271
292
  """
293
+ cache: CacheConfig
294
+ """Optional. Cache configuration for the server.
295
+
296
+ Example:
297
+ {
298
+ "cache_keys": ["user_id", "workspace_id"],
299
+ "ttl_seconds": 3600,
300
+ "max_size": 100
301
+ }
302
+ """
303
+
304
+
305
+ class EncryptionConfig(TypedDict, total=False):
306
+ """Configuration for custom at-rest encryption logic.
307
+
308
+ Allows you to implement custom encryption for sensitive data stored in the database,
309
+ including metadata fields and checkpoint blobs.
310
+ """
311
+
312
+ path: str
313
+ """Required. Path to an instance of the Encryption() class that implements custom encryption handlers.
314
+
315
+ Format: "path/to/file.py:my_encryption"
316
+
317
+ Example:
318
+ {
319
+ "encryption": {
320
+ "path": "./encryption.py:my_encryption"
321
+ }
322
+ }
323
+ """
272
324
 
273
325
 
274
326
  class CorsConfig(TypedDict, total=False):
@@ -310,7 +362,7 @@ class CorsConfig(TypedDict, total=False):
310
362
  """
311
363
 
312
364
 
313
- class ConfigurableHeaderConfig(TypedDict):
365
+ class ConfigurableHeaderConfig(TypedDict, total=False):
314
366
  """Customize which headers to include as configurable values in your runs.
315
367
 
316
368
  By default, omits x-api-key, x-tenant-id, and x-service-key.
@@ -321,7 +373,7 @@ class ConfigurableHeaderConfig(TypedDict):
321
373
  """
322
374
 
323
375
  includes: list[str] | None
324
- """Headers to include (if not also matches against an 'exludes' pattern.
376
+ """Headers to include (if not also matched against an 'excludes' pattern).
325
377
 
326
378
  Examples:
327
379
  - 'user-agent'
@@ -367,7 +419,12 @@ class HttpConfig(TypedDict, total=False):
367
419
  Default is False.
368
420
  """
369
421
  disable_mcp: bool
370
- """Optional. If `True`, /mcp routes are removed, disabling the MCP server.
422
+ """Optional. If `True`, /mcp routes are removed, disabling default support to expose the deployment as an MCP server.
423
+
424
+ Default is False.
425
+ """
426
+ disable_a2a: bool
427
+ """Optional. If `True`, /a2a routes are removed, disabling default support to expose the deployment as an agent-to-agent (A2A) server.
371
428
 
372
429
  Default is False.
373
430
  """
@@ -377,6 +434,17 @@ class HttpConfig(TypedDict, total=False):
377
434
  Set to True to disable the following endpoints: /openapi.json, /info, /metrics, /docs.
378
435
  This will also make the /ok endpoint skip any DB or other checks, always returning {"ok": True}.
379
436
 
437
+ Default is False.
438
+ """
439
+ disable_ui: bool
440
+ """Optional. If `True`, /ui routes are removed, disabling the UI server.
441
+
442
+ Default is False.
443
+ """
444
+ disable_webhooks: bool
445
+ """Optional. If `True`, webhooks are disabled. Runs created with an associated webhook will
446
+ still be executed, but the webhook event will not be sent.
447
+
380
448
  Default is False.
381
449
  """
382
450
  cors: CorsConfig | None
@@ -409,6 +477,52 @@ class HttpConfig(TypedDict, total=False):
409
477
  Default is False. This flag only affects authentication behavior
410
478
  if `app` is provided and contains custom routes.
411
479
  """
480
+ mount_prefix: str
481
+ """Optional. URL prefix to prepend to all the routes.
482
+
483
+ Example:
484
+ "/api"
485
+ """
486
+
487
+
488
+ class WebhookUrlPolicy(TypedDict, total=False):
489
+ require_https: bool
490
+ """Enforce HTTPS scheme for absolute URLs; reject `http://` when true."""
491
+ allowed_domains: list[str]
492
+ """Hostname allowlist. Supports exact hosts and wildcard subdomains.
493
+
494
+ Use entries like "hooks.example.com" or "*.mycorp.com". The wildcard only
495
+ matches subdomains ("foo.mycorp.com"), not the apex ("mycorp.com"). When
496
+ empty or omitted, any public host is allowed (subject to SSRF IP checks).
497
+ """
498
+ allowed_ports: list[int]
499
+ """Explicit port allowlist for absolute URLs.
500
+
501
+ If set, requests must use one of these ports. Defaults are respected when
502
+ a port is not present in the URL (443 for https, 80 for http).
503
+ """
504
+ max_url_length: int
505
+ """Maximum permitted URL length in characters; longer inputs are rejected early."""
506
+ disable_loopback: bool
507
+ """Disallow relative URLs (internal loopback calls) when true."""
508
+
509
+
510
+ class WebhooksConfig(TypedDict, total=False):
511
+ env_prefix: str
512
+ """Required prefix for environment variables referenced in header templates.
513
+
514
+ Acts as an allowlist boundary to prevent leaking arbitrary environment
515
+ variables. Defaults to "LG_WEBHOOK_" when omitted.
516
+ """
517
+ url: WebhookUrlPolicy
518
+ """URL validation policy for user-supplied webhook endpoints."""
519
+ headers: dict[str, str]
520
+ """Static headers to include with webhook requests.
521
+
522
+ Values may contain templates of the form "${{ env.VAR }}". On startup, these
523
+ are resolved via the process environment after verifying `VAR` starts with
524
+ `env_prefix`. Mixed literals and multiple templates are allowed.
525
+ """
412
526
 
413
527
 
414
528
  class Config(TypedDict, total=False):
@@ -524,15 +638,28 @@ class Config(TypedDict, total=False):
524
638
  """
525
639
 
526
640
  auth: AuthConfig | None
527
- """Optional. Custom authentication config, including the path to your Python auth logic and
641
+ """Optional. Custom authentication config, including the path to your Python auth logic and
528
642
  the OpenAPI security definitions it uses.
529
643
  """
530
644
 
645
+ encryption: EncryptionConfig | None
646
+ """Optional. Custom at-rest encryption config, including the path to your Python encryption logic.
647
+
648
+ Allows you to implement custom encryption for sensitive data stored in the database.
649
+ """
650
+
531
651
  http: HttpConfig | None
532
652
  """Optional. Configuration for the built-in HTTP server, controlling which custom routes are exposed
533
653
  and how cross-origin requests are handled.
534
654
  """
535
655
 
656
+ webhooks: WebhooksConfig | None
657
+ """Optional. Webhooks configuration for outbound event delivery.
658
+
659
+ Forwarded into the container as `LANGGRAPH_WEBHOOKS`. See `WebhooksConfig`
660
+ for URL policy and header templating details.
661
+ """
662
+
536
663
  ui: dict[str, str] | None
537
664
  """Optional. Named definitions of UI components emitted by the agent, each pointing to a JS/TS file.
538
665
  """
@@ -550,6 +677,7 @@ __all__ = [
550
677
  "StoreConfig",
551
678
  "CheckpointerConfig",
552
679
  "AuthConfig",
680
+ "EncryptionConfig",
553
681
  "HttpConfig",
554
682
  "MiddlewareOrders",
555
683
  "Distros",
@@ -25,7 +25,10 @@ inmem = [
25
25
  ]
26
26
 
27
27
  [project.urls]
28
- Repository = "https://www.github.com/langchain-ai/langgraph"
28
+ Source = "https://github.com/langchain-ai/langgraph/tree/main/libs/cli"
29
+ Twitter = "https://x.com/LangChainAI"
30
+ Slack = "https://www.langchain.com/join-community"
31
+ Reddit = "https://www.reddit.com/r/LangChain/"
29
32
 
30
33
  [project.scripts]
31
34
  langgraph = "langgraph_cli.cli:cli"
@@ -99,6 +99,17 @@
99
99
  },
100
100
  "description": "Optional. Additional Docker instructions that will be appended to your base Dockerfile.\n\nUseful for installing OS packages, setting environment variables, etc."
101
101
  },
102
+ "encryption": {
103
+ "anyOf": [
104
+ {
105
+ "$ref": "#/$defs/EncryptionConfig"
106
+ },
107
+ {
108
+ "type": "null"
109
+ }
110
+ ],
111
+ "description": "Optional. Custom at-rest encryption config, including the path to your Python encryption logic.\n\nAllows you to implement custom encryption for sensitive data stored in the database.\n"
112
+ },
102
113
  "env": {
103
114
  "anyOf": [
104
115
  {
@@ -199,6 +210,17 @@
199
210
  }
200
211
  ],
201
212
  "description": "Optional. Named definitions of UI components emitted by the agent, each pointing to a JS/TS file.\n"
213
+ },
214
+ "webhooks": {
215
+ "anyOf": [
216
+ {
217
+ "$ref": "#/$defs/WebhooksConfig"
218
+ },
219
+ {
220
+ "type": "null"
221
+ }
222
+ ],
223
+ "description": "Optional. Webhooks configuration for outbound event delivery.\n\nForwarded into the container as `LANGGRAPH_WEBHOOKS`. See `WebhooksConfig`\nfor URL policy and header templating details.\n"
202
224
  }
203
225
  },
204
226
  "required": [
@@ -292,6 +314,17 @@
292
314
  },
293
315
  "description": "Optional. Additional Docker instructions that will be appended to your base Dockerfile.\n\nUseful for installing OS packages, setting environment variables, etc."
294
316
  },
317
+ "encryption": {
318
+ "anyOf": [
319
+ {
320
+ "$ref": "#/$defs/EncryptionConfig"
321
+ },
322
+ {
323
+ "type": "null"
324
+ }
325
+ ],
326
+ "description": "Optional. Custom at-rest encryption config, including the path to your Python encryption logic.\n\nAllows you to implement custom encryption for sensitive data stored in the database.\n"
327
+ },
295
328
  "env": {
296
329
  "anyOf": [
297
330
  {
@@ -391,6 +424,17 @@
391
424
  }
392
425
  ],
393
426
  "description": "Optional. Named definitions of UI components emitted by the agent, each pointing to a JS/TS file.\n"
427
+ },
428
+ "webhooks": {
429
+ "anyOf": [
430
+ {
431
+ "$ref": "#/$defs/WebhooksConfig"
432
+ },
433
+ {
434
+ "type": "null"
435
+ }
436
+ ],
437
+ "description": "Optional. Webhooks configuration for outbound event delivery.\n\nForwarded into the container as `LANGGRAPH_WEBHOOKS`. See `WebhooksConfig`\nfor URL policy and header templating details.\n"
394
438
  }
395
439
  },
396
440
  "required": [
@@ -405,6 +449,10 @@
405
449
  "description": "Configuration for custom authentication logic and how it integrates into the OpenAPI spec.",
406
450
  "type": "object",
407
451
  "properties": {
452
+ "cache": {
453
+ "$ref": "#/$defs/CacheConfig",
454
+ "description": "Optional. Cache configuration for the server.\n"
455
+ },
408
456
  "disable_studio_auth": {
409
457
  "type": "boolean",
410
458
  "description": "Optional. Whether to disable LangSmith API-key authentication for requests originating the Studio.\n\nDefaults to False, meaning that if a particular header is set, the server will verify the `x-api-key` header\nvalue is a valid API key for the deployment's workspace. If `True`, all requests will go through your custom\nauthentication logic, regardless of origin of the request.\n"
@@ -420,6 +468,29 @@
420
468
  },
421
469
  "required": []
422
470
  },
471
+ "CacheConfig": {
472
+ "title": "CacheConfig",
473
+ "type": "object",
474
+ "properties": {
475
+ "cache_keys": {
476
+ "type": "array",
477
+ "items": {
478
+ "type": "string"
479
+ },
480
+ "description": "Optional. List of header keys to use for caching.\n"
481
+ },
482
+ "max_size": {
483
+ "type": "integer",
484
+ "description": "Optional. Maximum size of the cache.\n"
485
+ },
486
+ "ttl_seconds": {
487
+ "type": "integer",
488
+ "description": "Optional. Time-to-live in seconds for cached items.\n"
489
+ }
490
+ },
491
+ "required": [],
492
+ "description": "dict() -> new empty dictionary\ndict(mapping) -> new dictionary initialized from a mapping object's\n (key, value) pairs\ndict(iterable) -> new dictionary initialized as if via:\n d = {}\n for k, v in iterable:\n d[k] = v\ndict(**kwargs) -> new dictionary initialized with the name=value pairs\n in the keyword argument list. For example: dict(one=1, two=2)"
493
+ },
423
494
  "SecurityConfig": {
424
495
  "title": "SecurityConfig",
425
496
  "description": "Configuration for OpenAPI security definitions and requirements.\n\nUseful for specifying global or path-level authentication and authorization flows\n(e.g., OAuth2, API key headers, etc.).",
@@ -565,6 +636,17 @@
565
636
  },
566
637
  "required": []
567
638
  },
639
+ "EncryptionConfig": {
640
+ "title": "EncryptionConfig",
641
+ "description": "Configuration for custom at-rest encryption logic.\n\nAllows you to implement custom encryption for sensitive data stored in the database,\nincluding metadata fields and checkpoint blobs.",
642
+ "type": "object",
643
+ "properties": {
644
+ "path": {
645
+ "type": "string"
646
+ }
647
+ },
648
+ "required": []
649
+ },
568
650
  "HttpConfig": {
569
651
  "title": "HttpConfig",
570
652
  "description": "Configuration for the built-in HTTP server that powers your deployment's routes and endpoints.",
@@ -596,13 +678,17 @@
596
678
  ],
597
679
  "description": "Optional. Defines CORS restrictions. If omitted, no special rules are set and\ncross-origin behavior depends on default server settings.\n"
598
680
  },
681
+ "disable_a2a": {
682
+ "type": "boolean",
683
+ "description": "Optional. If `True`, /a2a routes are removed, disabling default support to expose the deployment as an agent-to-agent (A2A) server.\n\nDefault is False.\n"
684
+ },
599
685
  "disable_assistants": {
600
686
  "type": "boolean",
601
687
  "description": "Optional. If `True`, /assistants routes are removed from the server.\n\nDefault is False (meaning /assistants is enabled).\n"
602
688
  },
603
689
  "disable_mcp": {
604
690
  "type": "boolean",
605
- "description": "Optional. If `True`, /mcp routes are removed, disabling the MCP server.\n\nDefault is False.\n"
691
+ "description": "Optional. If `True`, /mcp routes are removed, disabling default support to expose the deployment as an MCP server.\n\nDefault is False.\n"
606
692
  },
607
693
  "disable_meta": {
608
694
  "type": "boolean",
@@ -620,6 +706,14 @@
620
706
  "type": "boolean",
621
707
  "description": "Optional. If `True`, /threads routes are removed.\n\nDefault is False.\n"
622
708
  },
709
+ "disable_ui": {
710
+ "type": "boolean",
711
+ "description": "Optional. If `True`, /ui routes are removed, disabling the UI server.\n\nDefault is False.\n"
712
+ },
713
+ "disable_webhooks": {
714
+ "type": "boolean",
715
+ "description": "Optional. If `True`, webhooks are disabled. Runs created with an associated webhook will\nstill be executed, but the webhook event will not be sent.\n\nDefault is False.\n"
716
+ },
623
717
  "enable_custom_route_auth": {
624
718
  "type": "boolean",
625
719
  "description": "Optional. If `True`, authentication is enabled for custom routes,\nnot just the routes that are protected by default.\n(Routes protected by default include /assistants, /threads, and /runs).\n\nDefault is False. This flag only affects authentication behavior\nif `app` is provided and contains custom routes.\n"
@@ -648,6 +742,10 @@
648
742
  }
649
743
  ],
650
744
  "description": "Optional. Defines the order in which to apply server customizations.\n"
745
+ },
746
+ "mount_prefix": {
747
+ "type": "string",
748
+ "description": "Optional. URL prefix to prepend to all the routes.\n"
651
749
  }
652
750
  },
653
751
  "required": []
@@ -683,13 +781,10 @@
683
781
  "type": "null"
684
782
  }
685
783
  ],
686
- "description": "Headers to include (if not also matches against an 'exludes' pattern.\n"
784
+ "description": "Headers to include (if not also matched against an 'excludes' pattern).\n"
687
785
  }
688
786
  },
689
- "required": [
690
- "excludes",
691
- "includes"
692
- ]
787
+ "required": []
693
788
  },
694
789
  "CorsConfig": {
695
790
  "title": "CorsConfig",
@@ -832,6 +927,63 @@
832
927
  }
833
928
  },
834
929
  "required": []
930
+ },
931
+ "WebhooksConfig": {
932
+ "title": "WebhooksConfig",
933
+ "type": "object",
934
+ "properties": {
935
+ "env_prefix": {
936
+ "type": "string",
937
+ "description": "Required prefix for environment variables referenced in header templates.\n\nActs as an allowlist boundary to prevent leaking arbitrary environment\nvariables. Defaults to \"LG_WEBHOOK_\" when omitted.\n"
938
+ },
939
+ "headers": {
940
+ "type": "object",
941
+ "additionalProperties": {
942
+ "type": "string"
943
+ },
944
+ "description": "Static headers to include with webhook requests.\n\nValues may contain templates of the form \"${{ env.VAR }}\". On startup, these\nare resolved via the process environment after verifying `VAR` starts with\n`env_prefix`. Mixed literals and multiple templates are allowed.\n"
945
+ },
946
+ "url": {
947
+ "$ref": "#/$defs/WebhookUrlPolicy",
948
+ "description": "URL validation policy for user-supplied webhook endpoints."
949
+ }
950
+ },
951
+ "required": [],
952
+ "description": "dict() -> new empty dictionary\ndict(mapping) -> new dictionary initialized from a mapping object's\n (key, value) pairs\ndict(iterable) -> new dictionary initialized as if via:\n d = {}\n for k, v in iterable:\n d[k] = v\ndict(**kwargs) -> new dictionary initialized with the name=value pairs\n in the keyword argument list. For example: dict(one=1, two=2)"
953
+ },
954
+ "WebhookUrlPolicy": {
955
+ "title": "WebhookUrlPolicy",
956
+ "type": "object",
957
+ "properties": {
958
+ "allowed_domains": {
959
+ "type": "array",
960
+ "items": {
961
+ "type": "string"
962
+ },
963
+ "description": "Hostname allowlist. Supports exact hosts and wildcard subdomains.\n\nUse entries like \"hooks.example.com\" or \"*.mycorp.com\". The wildcard only\nmatches subdomains (\"foo.mycorp.com\"), not the apex (\"mycorp.com\"). When\nempty or omitted, any public host is allowed (subject to SSRF IP checks).\n"
964
+ },
965
+ "allowed_ports": {
966
+ "type": "array",
967
+ "items": {
968
+ "type": "integer"
969
+ },
970
+ "description": "Explicit port allowlist for absolute URLs.\n\nIf set, requests must use one of these ports. Defaults are respected when\na port is not present in the URL (443 for https, 80 for http).\n"
971
+ },
972
+ "disable_loopback": {
973
+ "type": "boolean",
974
+ "description": "Disallow relative URLs (internal loopback calls) when true."
975
+ },
976
+ "max_url_length": {
977
+ "type": "integer",
978
+ "description": "Maximum permitted URL length in characters; longer inputs are rejected early."
979
+ },
980
+ "require_https": {
981
+ "type": "boolean",
982
+ "description": "Enforce HTTPS scheme for absolute URLs; reject `http://` when true."
983
+ }
984
+ },
985
+ "required": [],
986
+ "description": "dict() -> new empty dictionary\ndict(mapping) -> new dictionary initialized from a mapping object's\n (key, value) pairs\ndict(iterable) -> new dictionary initialized as if via:\n d = {}\n for k, v in iterable:\n d[k] = v\ndict(**kwargs) -> new dictionary initialized with the name=value pairs\n in the keyword argument list. For example: dict(one=1, two=2)"
835
987
  }
836
988
  },
837
989
  "title": "LangGraph CLI Configuration",