From 9cb6365914d11ca33909d1d3c5f56565c91fc16b Mon Sep 17 00:00:00 2001 From: Michael Li Date: Wed, 9 Jul 2025 04:58:04 +1000 Subject: [PATCH 1/8] docs: update file paths to make the examples more robust (#5382) * cli: update file paths to make the examples more robust * fix: fix the prompt path --- libs/cli/examples/graphs_reqs_a/graphs_submod/agent.py | 2 +- libs/cli/examples/graphs_reqs_b/graphs_submod/agent.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/libs/cli/examples/graphs_reqs_a/graphs_submod/agent.py b/libs/cli/examples/graphs_reqs_a/graphs_submod/agent.py index 5ab615871..1073110cb 100644 --- a/libs/cli/examples/graphs_reqs_a/graphs_submod/agent.py +++ b/libs/cli/examples/graphs_reqs_a/graphs_submod/agent.py @@ -17,7 +17,7 @@ model_oai = ChatOpenAI(temperature=0) model_anth = model_anth.bind_tools(tools) model_oai = model_oai.bind_tools(tools) -prompt = open("prompt.txt").read() +prompt = open(Path(__file__).parent.parent / "prompt.txt").read() subprompt = open(Path(__file__).parent / "subprompt.txt").read() diff --git a/libs/cli/examples/graphs_reqs_b/graphs_submod/agent.py b/libs/cli/examples/graphs_reqs_b/graphs_submod/agent.py index 5ab615871..1073110cb 100644 --- a/libs/cli/examples/graphs_reqs_b/graphs_submod/agent.py +++ b/libs/cli/examples/graphs_reqs_b/graphs_submod/agent.py @@ -17,7 +17,7 @@ model_oai = ChatOpenAI(temperature=0) model_anth = model_anth.bind_tools(tools) model_oai = model_oai.bind_tools(tools) -prompt = open("prompt.txt").read() +prompt = open(Path(__file__).parent.parent / "prompt.txt").read() subprompt = open(Path(__file__).parent / "subprompt.txt").read() From 0d8a8c5847703e78b88b3b2e3fb224a4d3adff63 Mon Sep 17 00:00:00 2001 From: William FH <13333726+hinthornw@users.noreply.github.com> Date: Tue, 8 Jul 2025 12:41:47 -0700 Subject: [PATCH 2/8] feat: [CLI] Add arg to retain build deps (setuptools, pip, wheel) (#5404) --- docs/docs/cloud/reference/cli.md | 1 + libs/cli/examples/langgraph.json | 1 + libs/cli/langgraph_cli/config.py | 124 ++++++++++++++++++---- libs/cli/pyproject.toml | 2 +- libs/cli/schemas/schema.json | 36 ++++++- libs/cli/schemas/schema.v0.json | 36 ++++++- libs/cli/schemas/version.schema.json | 46 ++++++++ libs/cli/tests/unit_tests/cli/test_cli.py | 7 +- libs/cli/tests/unit_tests/test_config.py | 57 +++++++++- libs/cli/uv.lock | 2 +- 10 files changed, 280 insertions(+), 32 deletions(-) create mode 100644 libs/cli/schemas/version.schema.json diff --git a/docs/docs/cloud/reference/cli.md b/docs/docs/cloud/reference/cli.md index b43be5485..2181f59e2 100644 --- a/docs/docs/cloud/reference/cli.md +++ b/docs/docs/cloud/reference/cli.md @@ -51,6 +51,7 @@ The LangGraph CLI requires a JSON configuration file that follows this [schema]( | `node_version` | Specify `node_version: 20` to use LangGraph.js. | | `pip_config_file` | Path to `pip` config file. | | `pip_installer` | _(Added in v0.3)_ Optional. Python package installer selector. It can be set to `"auto"`, `"pip"`, or `"uv"`. From version 0.3 onward the default strategy is to run `uv pip`, which typically delivers faster builds while remaining a drop-in replacement. In the uncommon situation where `uv` cannot handle your dependency graph or the structure of your `pyproject.toml`, specify `"pip"` here to revert to the earlier behaviour. | + | `keep_pkg_tools` | _(Added in v0.3.4)_ Optional. Control whether to retain Python packaging tools (`pip`, `setuptools`, `wheel`) in the final image. Accepted values: . By default, all three tools are uninstalled. | | `dockerfile_lines` | Array of additional lines to add to Dockerfile following the import from parent image. | | `checkpointer` | Configuration for the checkpointer. Contains a `ttl` field which is an object with the following keys: | | `http` | HTTP server configuration with the following fields: | diff --git a/libs/cli/examples/langgraph.json b/libs/cli/examples/langgraph.json index 51eb14be9..0d8563e55 100644 --- a/libs/cli/examples/langgraph.json +++ b/libs/cli/examples/langgraph.json @@ -8,6 +8,7 @@ "scikit-learn", "./graphs" ], + "keep_pkg_tools": false, "graphs": { "agent": "./graphs/agent.py:graph", "storm": "./graphs/storm.py:graph" diff --git a/libs/cli/langgraph_cli/config.py b/libs/cli/langgraph_cli/config.py index cd0356350..ce1c6e8b9 100644 --- a/libs/cli/langgraph_cli/config.py +++ b/libs/cli/langgraph_cli/config.py @@ -338,7 +338,7 @@ class HttpConfig(TypedDict, total=False): Default is False. """ disable_meta: bool - """Optional. If True, all meta endpoints (/ok, /info, /metrics, /docs) are disabled. + """Optional. If True, all meta endpoints (/openapi.json, /info, /metrics, /docs) are disabled. Default is False. """ @@ -471,21 +471,61 @@ class Config(TypedDict, total=False): """Optional. Named definitions of UI components emitted by the agent, each pointing to a JS/TS file. """ + keep_pkg_tools: Optional[Union[bool, list[str]]] + """Optional. Control whether to retain Python packaging tools in the final image. + + Allowed tools are: "pip", "setuptools", "wheel". + You can also set to true to include all packaging tools. + """ -PIP_CLEANUP_LINES = """# -- Ensure user deps didn't inadvertently overwrite langgraph-api + +_BUILD_TOOLS = ("pip", "setuptools", "wheel") + + +def _get_pip_cleanup_lines( + install_cmd: str, + to_uninstall: Optional[tuple[str]], + pip_installer: Literal["uv", "pip"], +) -> str: + commands = [ + f"""# -- Ensure user deps didn't inadvertently overwrite langgraph-api RUN mkdir -p /api/langgraph_api /api/langgraph_runtime /api/langgraph_license && \ - touch /api/langgraph_api/__init__.py /api/langgraph_runtime/__init__.py /api/langgraph_license/__init__.py +touch /api/langgraph_api/__init__.py /api/langgraph_runtime/__init__.py /api/langgraph_license/__init__.py RUN PYTHONDONTWRITEBYTECODE=1 {install_cmd} --no-cache-dir --no-deps -e /api # -- End of ensuring user deps didn't inadvertently overwrite langgraph-api -- -# -- Removing pip from the final image ~<:===~~~ -- -RUN pip uninstall -y pip setuptools wheel && \ - rm -rf /usr/local/lib/python*/site-packages/pip* /usr/local/lib/python*/site-packages/setuptools* /usr/local/lib/python*/site-packages/wheel* && \ - find /usr/local/bin -name "pip*" -delete || true -# pip removal for wolfi -RUN rm -rf /usr/lib/python*/site-packages/pip* /usr/lib/python*/site-packages/setuptools* /usr/lib/python*/site-packages/wheel* && \ - find /usr/bin -name "pip*" -delete || true -{uv_removal} -# -- End of pip removal --""" +# -- Removing build deps from the final image ~<:===~~~ --""" + ] + if to_uninstall: + for pack in to_uninstall: + if pack not in _BUILD_TOOLS: + raise ValueError( + f"Invalid build tool: {pack}; must be one of {', '.join(_BUILD_TOOLS)}" + ) + packs_str = " ".join(sorted(to_uninstall)) + commands.append(f"RUN pip uninstall -y {packs_str}") + # Ensure the directories are removed entirely + packages_rm = " ".join( + f"/usr/local/lib/python*/site-packages/{pack}*" for pack in to_uninstall + ) + if "pip" in to_uninstall: + packages_rm += ' && find /usr/local/bin -name "pip*" -delete || true' + commands.append(f"RUN rm -rf {packages_rm}") + wolfi_packages_rm = " ".join( + f"/usr/lib/python*/site-packages/{pack}*" for pack in to_uninstall + ) + if "pip" in to_uninstall: + wolfi_packages_rm += ' && find /usr/bin -name "pip*" -delete || true' + commands.append(f"RUN rm -rf {wolfi_packages_rm}") + if pip_installer == "uv": + commands.append( + f"RUN uv pip uninstall --system {packs_str} && rm /usr/bin/uv /usr/bin/uvx" + ) + else: + if pip_installer == "uv": + commands.append( + "RUN rm /usr/bin/uv /usr/bin/uvx\n# -- End of build deps removal --" + ) + return "\n".join(commands) def _parse_version(version_str: str) -> tuple[int, int]: @@ -563,6 +603,7 @@ def validate_config(config: Config) -> Config: "checkpointer": config.get("checkpointer"), "ui": config.get("ui"), "ui_config": config.get("ui_config"), + "keep_pkg_tools": config.get("keep_pkg_tools"), } if config.get("node_version"): @@ -635,6 +676,22 @@ def validate_config(config: Config) -> Config: f"Invalid http.app format: '{http_conf['app']}'. " "Must be in format './path/to/file.py:attribute_name'" ) + if keep_pkg_tools := config.get("keep_pkg_tools"): + if isinstance(keep_pkg_tools, list): + for tool in keep_pkg_tools: + if tool not in _BUILD_TOOLS: + raise ValueError( + f"Invalid keep_pkg_tools: '{tool}'. " + "Must be one of 'pip', 'setuptools', 'wheel'." + ) + elif keep_pkg_tools is True: + pass + else: + raise ValueError( + f"Invalid keep_pkg_tools: '{keep_pkg_tools}'. " + "Must be bool or list[str] (with values" + " 'pip', 'setuptools', and/or 'wheel')." + ) return config @@ -1128,6 +1185,27 @@ def _image_supports_uv(base_image: str) -> bool: return version >= min_uv +def get_build_tools_to_uninstall(config: Config) -> tuple[str]: + keep_pkg_tools = config.get("keep_pkg_tools") + if not keep_pkg_tools: + return _BUILD_TOOLS + if keep_pkg_tools is True: + return () + expected = _BUILD_TOOLS + if isinstance(keep_pkg_tools, list): + for tool in keep_pkg_tools: + if tool not in expected: + raise ValueError( + f"Invalid build tool to uninstall: {tool}. Expected one of {expected}" + ) + return tuple(sorted(set(_BUILD_TOOLS) - set(keep_pkg_tools))) + else: + raise ValueError( + f"Invalid value for keep_pkg_tools: {keep_pkg_tools}." + " Expected True or a list containing any of {expected}." + ) + + def python_config_to_docker( config_path: pathlib.Path, config: Config, @@ -1135,20 +1213,18 @@ def python_config_to_docker( ) -> tuple[str, dict[str, str]]: """Generate a Dockerfile from the configuration.""" pip_installer = config.get("pip_installer", "auto") - + build_tools_to_uninstall = get_build_tools_to_uninstall(config) + if pip_installer == "auto": + if _image_supports_uv(base_image): + pip_installer = "uv" + else: + pip_installer = "pip" if pip_installer == "uv": install_cmd = "uv pip install --system" - uv_removal = "RUN uv pip uninstall --system pip setuptools wheel && rm /usr/bin/uv /usr/bin/uvx" elif pip_installer == "pip": install_cmd = "pip install" - uv_removal = "" else: - if _image_supports_uv(base_image): - install_cmd = "uv pip install --system" - uv_removal = "RUN uv pip uninstall --system pip setuptools wheel && rm /usr/bin/uv /usr/bin/uvx" - else: - install_cmd = "pip install" - uv_removal = "" + raise ValueError(f"Invalid pip_installer: {pip_installer}") # configure pip pip_install = f"PYTHONDONTWRITEBYTECODE=1 {install_cmd} --no-cache-dir -c /api/constraints.txt" @@ -1297,7 +1373,11 @@ ADD {relpath} /deps/{name} js_inst_str, "", # Add pip cleanup after all installations are complete - PIP_CLEANUP_LINES.format(install_cmd=install_cmd, uv_removal=uv_removal), + _get_pip_cleanup_lines( + install_cmd=install_cmd, + to_uninstall=build_tools_to_uninstall, + pip_installer=pip_installer, + ), "", f"WORKDIR {local_deps.working_dir}" if local_deps.working_dir else "", ] diff --git a/libs/cli/pyproject.toml b/libs/cli/pyproject.toml index 1a781e6f2..8c959ccab 100644 --- a/libs/cli/pyproject.toml +++ b/libs/cli/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "hatchling.build" [project] name = "langgraph-cli" -version = "0.3.3" +version = "0.3.4" description = "CLI for interacting with LangGraph API" authors = [] requires-python = ">=3.9" diff --git a/libs/cli/schemas/schema.json b/libs/cli/schemas/schema.json index c069f7e9e..19d8893a4 100644 --- a/libs/cli/schemas/schema.json +++ b/libs/cli/schemas/schema.json @@ -134,6 +134,23 @@ ], "description": "Optional. Linux distribution for the base image.\n\nMust be either 'debian' or 'wolfi'. If omitted, defaults to 'debian'.\n" }, + "keep_pkg_tools": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "array", + "items": { + "type": "string" + } + }, + { + "type": "null" + } + ], + "description": "Optional. Control whether to retain Python packaging tools in the final image.\n\nYou can also set to true to include all packaging tools.\n" + }, "pip_installer": { "anyOf": [ { @@ -298,6 +315,23 @@ ], "description": "Optional. Linux distribution for the base image.\n\nMust be either 'debian' or 'wolfi'. If omitted, defaults to 'debian'.\n" }, + "keep_pkg_tools": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "array", + "items": { + "type": "string" + } + }, + { + "type": "null" + } + ], + "description": "Optional. Control whether to retain Python packaging tools in the final image.\n\nYou can also set to true to include all packaging tools.\n" + }, "pip_installer": { "anyOf": [ { @@ -505,7 +539,7 @@ }, "disable_meta": { "type": "boolean", - "description": "Optional. If True, all meta endpoints (/ok, /info, /metrics, /docs) are disabled.\n\nDefault is False.\n" + "description": "Optional. If True, all meta endpoints (/openapi.json, /info, /metrics, /docs) are disabled.\n\nDefault is False.\n" }, "disable_runs": { "type": "boolean", diff --git a/libs/cli/schemas/schema.v0.json b/libs/cli/schemas/schema.v0.json index c069f7e9e..19d8893a4 100644 --- a/libs/cli/schemas/schema.v0.json +++ b/libs/cli/schemas/schema.v0.json @@ -134,6 +134,23 @@ ], "description": "Optional. Linux distribution for the base image.\n\nMust be either 'debian' or 'wolfi'. If omitted, defaults to 'debian'.\n" }, + "keep_pkg_tools": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "array", + "items": { + "type": "string" + } + }, + { + "type": "null" + } + ], + "description": "Optional. Control whether to retain Python packaging tools in the final image.\n\nYou can also set to true to include all packaging tools.\n" + }, "pip_installer": { "anyOf": [ { @@ -298,6 +315,23 @@ ], "description": "Optional. Linux distribution for the base image.\n\nMust be either 'debian' or 'wolfi'. If omitted, defaults to 'debian'.\n" }, + "keep_pkg_tools": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "array", + "items": { + "type": "string" + } + }, + { + "type": "null" + } + ], + "description": "Optional. Control whether to retain Python packaging tools in the final image.\n\nYou can also set to true to include all packaging tools.\n" + }, "pip_installer": { "anyOf": [ { @@ -505,7 +539,7 @@ }, "disable_meta": { "type": "boolean", - "description": "Optional. If True, all meta endpoints (/ok, /info, /metrics, /docs) are disabled.\n\nDefault is False.\n" + "description": "Optional. If True, all meta endpoints (/openapi.json, /info, /metrics, /docs) are disabled.\n\nDefault is False.\n" }, "disable_runs": { "type": "boolean", diff --git a/libs/cli/schemas/version.schema.json b/libs/cli/schemas/version.schema.json new file mode 100644 index 000000000..041b130c1 --- /dev/null +++ b/libs/cli/schemas/version.schema.json @@ -0,0 +1,46 @@ +{ + "$id": "https://github.com/langchain-ai/langgraph/libs/cli/schemas/version.schema.json", + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "LangGraph Platform configuration (when building via the langgraph-cli).", + "type": "object", + "oneOf": [ + { + "allOf": [ + { + "oneOf": [ + { + "properties": { + "version": { + "type": "string", + "maxLength": 0 + } + }, + "required": ["version"] + }, + { + "not": { + "required": ["version"] + } + } + ] + }, + { + "$ref": "https://raw.githubusercontent.com/langchain-ai/langgraph/main/libs/cli/schemas/schema.json" + } + ] + }, + { + "allOf": [ + { + "properties": { + "version": { "const": "v0" } + }, + "required": ["version"] + }, + { + "$ref": "https://raw.githubusercontent.com/langchain-ai/langgraph/main/libs/cli/schemas/schema.v0.json" + } + ] + } + ] +} diff --git a/libs/cli/tests/unit_tests/cli/test_cli.py b/libs/cli/tests/unit_tests/cli/test_cli.py index 268f44e00..e6d0a17b4 100644 --- a/libs/cli/tests/unit_tests/cli/test_cli.py +++ b/libs/cli/tests/unit_tests/cli/test_cli.py @@ -10,13 +10,14 @@ from pathlib import Path from click.testing import CliRunner from langgraph_cli.cli import cli, prepare_args_and_stdin -from langgraph_cli.config import PIP_CLEANUP_LINES, Config, validate_config +from langgraph_cli.config import Config, _get_pip_cleanup_lines, validate_config from langgraph_cli.docker import DEFAULT_POSTGRES_URI, DockerCapabilities, Version from langgraph_cli.util import clean_empty_lines -FORMATTED_CLEANUP_LINES = PIP_CLEANUP_LINES.format( +FORMATTED_CLEANUP_LINES = _get_pip_cleanup_lines( install_cmd="uv pip install --system", - uv_removal="RUN uv pip uninstall --system pip setuptools wheel && rm /usr/bin/uv /usr/bin/uvx", + to_uninstall=("pip", "setuptools", "wheel"), + pip_installer="uv", ) DEFAULT_DOCKER_CAPABILITIES = DockerCapabilities( version_docker=Version(26, 1, 1), diff --git a/libs/cli/tests/unit_tests/test_config.py b/libs/cli/tests/unit_tests/test_config.py index 3971b60e2..691c1e888 100644 --- a/libs/cli/tests/unit_tests/test_config.py +++ b/libs/cli/tests/unit_tests/test_config.py @@ -9,7 +9,8 @@ import click import pytest from langgraph_cli.config import ( - PIP_CLEANUP_LINES, + _BUILD_TOOLS, + _get_pip_cleanup_lines, config_to_compose, config_to_docker, docker_tag, @@ -18,9 +19,10 @@ from langgraph_cli.config import ( ) from langgraph_cli.util import clean_empty_lines -FORMATTED_CLEANUP_LINES = PIP_CLEANUP_LINES.format( +FORMATTED_CLEANUP_LINES = _get_pip_cleanup_lines( install_cmd="uv pip install --system", - uv_removal="RUN uv pip uninstall --system pip setuptools wheel && rm /usr/bin/uv /usr/bin/uvx", + to_uninstall=("pip", "setuptools", "wheel"), + pip_installer="uv", ) PATH_TO_CONFIG = pathlib.Path(__file__).parent / "test_config.json" @@ -51,6 +53,7 @@ def test_validate_config(): "http": None, "ui": None, "ui_config": None, + "keep_pkg_tools": None, **expected_config, } assert actual_config == expected_config @@ -77,6 +80,7 @@ def test_validate_config(): "http": None, "ui": None, "ui_config": None, + "keep_pkg_tools": None, } actual_config = validate_config(expected_config) assert actual_config == expected_config @@ -925,6 +929,53 @@ def test_config_to_docker_pip_installer(): assert "uv pip install --system" in docker_default +def test_config_retain_build_tools(): + graphs = {"agent": "./graphs/agent.py:graph"} + base_config = { + "python_version": "3.11", + "dependencies": ["."], + "graphs": graphs, + } + config_true = validate_config( + {**copy.deepcopy(base_config), "keep_pkg_tools": True} + ) + docker_true, _ = config_to_docker( + PATH_TO_CONFIG, config_true, "langchain/langgraph-api:0.2.47" + ) + assert not any( + "/usr/local/lib/python*/site-packages/" + pckg + "*" in docker_true + for pckg in _BUILD_TOOLS + ) + assert "RUN pip uninstall -y pip setuptools wheel" not in docker_true + config_false = validate_config( + {**copy.deepcopy(base_config), "keep_pkg_tools": False} + ) + docker_false, _ = config_to_docker( + PATH_TO_CONFIG, config_false, "langchain/langgraph-api:0.2.47" + ) + assert all( + "/usr/local/lib/python*/site-packages/" + pckg + "*" in docker_false + for pckg in _BUILD_TOOLS + ) + assert "RUN pip uninstall -y pip setuptools wheel" in docker_false + config_list = validate_config( + {**copy.deepcopy(base_config), "keep_pkg_tools": ["pip", "setuptools"]} + ) + docker_list, _ = config_to_docker( + PATH_TO_CONFIG, config_list, "langchain/langgraph-api:0.2.47" + ) + assert all( + "/usr/local/lib/python*/site-packages/" + pckg + "*" in docker_list + for pckg in ("wheel",) + ) + assert not any( + "/usr/local/lib/python*/site-packages/" + pckg + "*" in docker_list + for pckg in ("pip", "setuptools") + ) + assert "RUN pip uninstall -y wheel" in docker_list + assert "RUN pip uninstall -y pip setuptools" not in docker_list + + # config_to_compose def test_config_to_compose_simple_config(): graphs = {"agent": "./agent.py:graph"} diff --git a/libs/cli/uv.lock b/libs/cli/uv.lock index a6a0d0270..b312f2e06 100644 --- a/libs/cli/uv.lock +++ b/libs/cli/uv.lock @@ -522,7 +522,7 @@ wheels = [ [[package]] name = "langgraph-cli" -version = "0.3.3" +version = "0.3.4" source = { editable = "." } dependencies = [ { name = "click", version = "8.1.8", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, From 2fee6499809cafa5cc19b21b60d54ad6a0a169ee Mon Sep 17 00:00:00 2001 From: William FH <13333726+hinthornw@users.noreply.github.com> Date: Tue, 8 Jul 2025 12:55:10 -0700 Subject: [PATCH 3/8] chore: (cli) Update description of disable_meta (#5406) --- libs/cli/langgraph_cli/config.py | 5 ++++- libs/cli/schemas/schema.json | 2 +- libs/cli/schemas/schema.v0.json | 2 +- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/libs/cli/langgraph_cli/config.py b/libs/cli/langgraph_cli/config.py index ce1c6e8b9..9030c3ba2 100644 --- a/libs/cli/langgraph_cli/config.py +++ b/libs/cli/langgraph_cli/config.py @@ -338,7 +338,10 @@ class HttpConfig(TypedDict, total=False): Default is False. """ disable_meta: bool - """Optional. If True, all meta endpoints (/openapi.json, /info, /metrics, /docs) are disabled. + """Optional. Remove meta endpoints. + + Set to True to disable the following endpoints: /openapi.json, /info, /metrics, /docs. + This will also make the /ok endpoint skip any DB or other checks, always returning {"ok": True}. Default is False. """ diff --git a/libs/cli/schemas/schema.json b/libs/cli/schemas/schema.json index 19d8893a4..e76e69826 100644 --- a/libs/cli/schemas/schema.json +++ b/libs/cli/schemas/schema.json @@ -539,7 +539,7 @@ }, "disable_meta": { "type": "boolean", - "description": "Optional. If True, all meta endpoints (/openapi.json, /info, /metrics, /docs) are disabled.\n\nDefault is False.\n" + "description": "Optional. Remove meta endpoints.\n\n\nDefault is False.\n" }, "disable_runs": { "type": "boolean", diff --git a/libs/cli/schemas/schema.v0.json b/libs/cli/schemas/schema.v0.json index 19d8893a4..e76e69826 100644 --- a/libs/cli/schemas/schema.v0.json +++ b/libs/cli/schemas/schema.v0.json @@ -539,7 +539,7 @@ }, "disable_meta": { "type": "boolean", - "description": "Optional. If True, all meta endpoints (/openapi.json, /info, /metrics, /docs) are disabled.\n\nDefault is False.\n" + "description": "Optional. Remove meta endpoints.\n\n\nDefault is False.\n" }, "disable_runs": { "type": "boolean", From c8d32f104de42df833950076d638c0061b4dacc4 Mon Sep 17 00:00:00 2001 From: nlimpid Date: Wed, 9 Jul 2025 04:09:57 +0800 Subject: [PATCH 4/8] fix(doc): remove incorrect navigation title overrides for mobile (#5399) --- .../navigation_title_ovverides.css | 29 ------------------- docs/mkdocs.yml | 1 - 2 files changed, 30 deletions(-) delete mode 100644 docs/docs/stylesheets/navigation_title_ovverides.css diff --git a/docs/docs/stylesheets/navigation_title_ovverides.css b/docs/docs/stylesheets/navigation_title_ovverides.css deleted file mode 100644 index 4e7c937d7..000000000 --- a/docs/docs/stylesheets/navigation_title_ovverides.css +++ /dev/null @@ -1,29 +0,0 @@ -/* - * This file is used to override the navigation title for the LangGraph documentation. - * It is used to change the title of the first and second items in the navigation menu. - * The first item is the Guides page, and the second item is the Reference page. - */ - -.md-nav--primary > .md-nav__list > .md-nav__item:nth-child(1) > .md-nav__link .md-ellipsis { - visibility: hidden !important; - position: relative; -} - -.md-nav--primary > .md-nav__list > .md-nav__item:nth-child(1) > .md-nav__link .md-ellipsis::after { - content: "Home"; - visibility: visible; - position: absolute; - left: 0; -} - -.md-nav--primary > .md-nav__list > .md-nav__item:nth-child(2) > .md-nav__link .md-ellipsis { - visibility: hidden !important; - position: relative; -} - -.md-nav--primary > .md-nav__list > .md-nav__item:nth-child(2) > .md-nav__link .md-ellipsis::after { - content: "Home"; - visibility: visible; - position: absolute; - left: 0; -} \ No newline at end of file diff --git a/docs/mkdocs.yml b/docs/mkdocs.yml index a66966905..f11c007ec 100644 --- a/docs/mkdocs.yml +++ b/docs/mkdocs.yml @@ -381,7 +381,6 @@ validation: copyright: > Copyright © 2025 LangChain, Inc | Consent Preferences extra_css: - - stylesheets/navigation_title_ovverides.css - stylesheets/version_admonitions.css - stylesheets/logos.css - stylesheets/sticky_navigation.css From 7a662135353eaf72a98cb78f757a5c0cd1d60ae2 Mon Sep 17 00:00:00 2001 From: Kai-Wendel <125994309+Kai-Wendel@users.noreply.github.com> Date: Tue, 8 Jul 2025 22:49:04 +0200 Subject: [PATCH 5/8] Fix typo in types.py in the interrupt example (#5407) Update types.py This example still lacked to include `Command`. --- libs/langgraph/langgraph/types.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/langgraph/langgraph/types.py b/libs/langgraph/langgraph/types.py index 095e73c24..8a653c0b9 100644 --- a/libs/langgraph/langgraph/types.py +++ b/libs/langgraph/langgraph/types.py @@ -428,7 +428,7 @@ def interrupt(value: Any) -> Any: from langgraph.checkpoint.memory import MemorySaver from langgraph.constants import START from langgraph.graph import StateGraph - from langgraph.types import interrupt + from langgraph.types import interrupt, Command class State(TypedDict): From 7a4fd2518509d587bc4c32809f786fa62c687733 Mon Sep 17 00:00:00 2001 From: Andrew Nguonly Date: Wed, 9 Jul 2025 10:53:21 -0400 Subject: [PATCH 6/8] docs: Add `RESUMABLE_STREAM_TTL_SECONDS` to env vars list (#5413) * Add RESUMABLE_STREAM_TTL_SECONDS to env vars list. * Update default value for BG_JOB_SHUTDOWN_GRACE_PERIOD_SECS. * Update LANGGRAPH_POSTGRES_POOL_MAX_SIZE description. --- docs/docs/cloud/reference/env_var.md | 60 +++++++++++++++++----------- 1 file changed, 37 insertions(+), 23 deletions(-) diff --git a/docs/docs/cloud/reference/env_var.md b/docs/docs/cloud/reference/env_var.md index 563cec2a1..333508d96 100644 --- a/docs/docs/cloud/reference/env_var.md +++ b/docs/docs/cloud/reference/env_var.md @@ -10,6 +10,10 @@ This environment variable should be set to `True` if the implementation of a gra Defaults to `False`. +## `BG_JOB_SHUTDOWN_GRACE_PERIOD_SECS` + +Specifies, in seconds, how long the server will wait for background jobs to finish after the queue receives a shutdown signal. After this period, the server will force termination. Defaults to `180` seconds. Set this to ensure jobs have enough time to complete cleanly during shutdown. Added in `langgraph-api==0.2.16`. + ## `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. @@ -18,10 +22,6 @@ A background run can execute for longer than 1 hour, but a client must reconnect Defaults to `3600`. -## `BG_JOB_SHUTDOWN_GRACE_PERIOD_SECS` - -Specifies, in seconds, how long the server will wait for background jobs to finish after the queue receives a shutdown signal. After this period, the server will force termination. Defaults to `3600` seconds. Set this to ensure jobs have enough time to complete cleanly during shutdown. Added in `langgraph-api==0.2.16`. - ## `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. @@ -40,6 +40,14 @@ Type of authentication for the LangGraph Server deployment. Valid values: `langs For deployments to LangGraph Platform, this environment variable is set automatically. For local development or deployments where authentication is handled externally (e.g. self-hosted), set this environment variable to `noop`. +## `LANGGRAPH_POSTGRES_POOL_MAX_SIZE` + +Beginning with langgraph-api version `0.2.12`, the maximum size of the Postgres connection pool (per replica) can be controlled using the `LANGGRAPH_POSTGRES_POOL_MAX_SIZE` environment variable. By setting this variable, you can determine the upper bound on the number of simultaneous connections the server will establish with the Postgres database. + +For example, if a deployment is scaled up to 10 replicas and `LANGGRAPH_POSTGRES_POOL_MAX_SIZE` is configured to `150`, then up to `1500` connections to Postgres can be established. This is particularly useful for deployments where database resources are limited (or more available) or where you need to tune connection behavior for performance or scaling reasons. + +Defaults to `150` connections. + ## `LANGSMITH_RUNS_ENDPOINTS` For deployments with [self-hosted LangSmith](https://docs.smith.langchain.com/self_hosting) only. @@ -54,6 +62,10 @@ Set `LANGSMITH_TRACING` to `false` to disable tracing to LangSmith. Defaults to `true`. +## `LOG_COLOR` + +This is mainly relevant in the context of using the dev server via the `langgraph dev` command. Set `LOG_COLOR` to `true` to enable ANSI-colored console output when using the default console renderer. Disabling color output by setting this variable to `false` produces monochrome logs. Defaults to `true`. + ## `LOG_LEVEL` Configure [log level](https://docs.python.org/3/library/logging.html#logging-levels). Defaults to `INFO`. @@ -62,9 +74,14 @@ Configure [log level](https://docs.python.org/3/library/logging.html#logging-lev Set `LOG_JSON` to `true` to render all log messages as JSON objects using the configured `JSONRenderer`. This produces structured logs that can be easily parsed or ingested by log management systems. Defaults to `false`. -## `LOG_COLOR` +## `MOUNT_PREFIX` -This is mainly relevant in the context of using the dev server via the `langgraph dev` command. Set `LOG_COLOR` to `true` to enable ANSI-colored console output when using the default console renderer. Disabling color output by setting this variable to `false` produces monochrome logs. Defaults to `true`. +!!! info "Only Allowed in Self-Hosted Deployments" + The `MOUNT_PREFIX` environment variable is only allowed in Self-Hosted Deployment models, LangGraph Platform SaaS will not allow this environment variable. + +Set `MOUNT_PREFIX` to serve the LangGraph Server under a specific path prefix. This is useful for deployments where the server is behind a reverse proxy or load balancer that requires a specific path prefix. + +For example, if the server is to be served under `https://example.com/langgraph`, set `MOUNT_PREFIX` to `/langgraph`. ## `N_JOBS_PER_WORKER` @@ -94,16 +111,14 @@ Database Connectivity: - The custom Postgres instance must be accessible by the LangGraph Server. The user is responsible for ensuring connectivity. -## `LANGGRAPH_POSTGRES_POOL_MAX_SIZE` +## `REDIS_CLUSTER` -Beginning with langgraph-api version `0.2.12`, the maximum size of the Postgres connection pool can be controlled using the `LANGGRAPH_POSTGRES_POOL_MAX_SIZE` environment variable. By setting this variable, you can determine the upper bound on the number of simultaneous connections the server will establish with the Postgres database. This is particularly useful for deployments where database resources are limited (or more available) or where you need to tune connection behavior for performance or scaling reasons. If not specified, the pool size defaults to 150 connections. +!!! info "Only Allowed in Self-Hosted Deployments" + Redis Cluster mode is only available in Self-Hosted Deployment models, LangGraph Platform SaaS will provision a redis instance for you by default. -## `REDIS_URI_CUSTOM` +Set `REDIS_CLUSTER` to `True` to enable Redis Cluster mode. When enabled, the system will connect to Redis using cluster mode. This is useful when connecting to a Redis Cluster deployment. -!!! info "Only for Self-Hosted Data Plane and Self-Hosted Control Plane" - Custom Redis instances are only available for [Self-Hosted Data Plane](../../concepts/langgraph_self_hosted_data_plane.md) and [Self-Hosted Control Plane](../../concepts/langgraph_self_hosted_control_plane.md) deployments. - -Specify `REDIS_URI_CUSTOM` to use a custom Redis instance. The value of `REDIS_URI_CUSTOM` must be a valid [Redis connection URI](https://redis-py.readthedocs.io/en/stable/connections.html#redis.Redis.from_url). +Defaults to `False`. ## `REDIS_KEY_PREFIX` @@ -114,20 +129,19 @@ Specify a prefix for Redis keys. This allows multiple LangGraph Server instances Defaults to `''`. -## `REDIS_CLUSTER` +## `REDIS_URI_CUSTOM` -!!! info "Only Allowed in Self-Hosted Deployments" - Redis Cluster mode is only available in Self-Hosted Deployment models, LangGraph Platform SaaS will provision a redis instance for you by default. +!!! info "Only for Self-Hosted Data Plane and Self-Hosted Control Plane" + Custom Redis instances are only available for [Self-Hosted Data Plane](../../concepts/langgraph_self_hosted_data_plane.md) and [Self-Hosted Control Plane](../../concepts/langgraph_self_hosted_control_plane.md) deployments. -Set `REDIS_CLUSTER` to `True` to enable Redis Cluster mode. When enabled, the system will connect to Redis using cluster mode. This is useful when connecting to a Redis Cluster deployment. +Specify `REDIS_URI_CUSTOM` to use a custom Redis instance. The value of `REDIS_URI_CUSTOM` must be a valid [Redis connection URI](https://redis-py.readthedocs.io/en/stable/connections.html#redis.Redis.from_url). -Defaults to `False`. +## `RESUMABLE_STREAM_TTL_SECONDS` -## `MOUNT_PREFIX` +Time-to-live in seconds for resumable stream data in Redis. -!!! info "Only Allowed in Self-Hosted Deployments" - The `MOUNT_PREFIX` environment variable is only allowed in Self-Hosted Deployment models, LangGraph Platform SaaS will not allow this environment variable. +When a run is created and the output is streamed, the stream can be configured to be resumable (e.g. `stream_resumable=True`). If a stream is resumable, output from the stream is temporarily stored in Redis. The TTL for this data can be configured by setting `RESUMABLE_STREAM_TTL_SECONDS`. -Set `MOUNT_PREFIX` to serve the LangGraph Server under a specific path prefix. This is useful for deployments where the server is behind a reverse proxy or load balancer that requires a specific path prefix. +See the [Python](https://langchain-ai.github.io/langgraph/cloud/reference/sdk/python_sdk_ref/#langgraph_sdk.client.RunsClient.stream) and [JS/TS](https://langchain-ai.github.io/langgraphjs/reference/classes/sdk_client.RunsClient.html#stream) SDKs for more details on how to implement resumable streams. -For example, if the server is to be served under `https://example.com/langgraph`, set `MOUNT_PREFIX` to `/langgraph`. +Defaults to `120` seconds. From 4d7c107bb8ad824a199e62b6547dc789cd8ecce9 Mon Sep 17 00:00:00 2001 From: Eugene Yurtsev Date: Wed, 9 Jul 2025 12:19:49 -0400 Subject: [PATCH 7/8] Update config.yml (#5412) --- .github/ISSUE_TEMPLATE/config.yml | 7 ------- 1 file changed, 7 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml index c2d2f70e0..fe68aea78 100644 --- a/.github/ISSUE_TEMPLATE/config.yml +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -1,15 +1,8 @@ -blank_issues_enabled: true version: 2.1 contact_links: - - name: 🤔 Question or Problem - about: Ask a question or ask about a problem in GitHub Discussions. - url: https://github.com/langchain-ai/langgraph/discussions/categories/q-a - name: Feature Request url: https://github.com/langchain-ai/langgraph/discussions/categories/ideas about: Suggest a feature or an idea - - name: Show and tell - about: Show what you built with LangChain - url: https://github.com/langchain-ai/langgraph/discussions/categories/show-and-tell - name: LangChain Forum url: https://forum.langchain.com/ about: General community discussions and support From 1240f8bdca3eecac0d6e6bc152d4fd70a7c1d168 Mon Sep 17 00:00:00 2001 From: jito Date: Thu, 10 Jul 2025 01:20:33 +0900 Subject: [PATCH 8/8] fix: correct troubleshooting link path (#5411) fix: correct troubleshooting link path from index.md.md to index.md Signed-off-by: jitokim --- docs/docs/additional-resources/index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/docs/additional-resources/index.md b/docs/docs/additional-resources/index.md index 6e4e7a93b..33e52e805 100644 --- a/docs/docs/additional-resources/index.md +++ b/docs/docs/additional-resources/index.md @@ -8,4 +8,4 @@ This section contains additional resources for LangGraph. - [FAQ](../concepts/faq.md): A collection of frequently asked questions about LangGraph. - [llms.txt](../llms-txt-overview.md): A list of documentation files in the `llms.txt` format that allow LLMs and agents to access our documentation. - [LangChain Forum](https://forum.langchain.com/): A place to ask questions and get help from other LangGraph users. -- [Troubleshooting](../troubleshooting/errors/index.md.md): A collection of troubleshooting guides for common issues. \ No newline at end of file +- [Troubleshooting](../troubleshooting/errors/index.md): A collection of troubleshooting guides for common issues. \ No newline at end of file