From f702729e04dd51b843d257a58f9f5b0181f0be2f Mon Sep 17 00:00:00 2001 From: Mason Daugherty Date: Sat, 21 Feb 2026 00:13:38 -0500 Subject: [PATCH 1/2] chore: add `make type` target for type checking (#6748) --- libs/checkpoint-postgres/Makefile | 5 ++++- libs/checkpoint-sqlite/Makefile | 5 ++++- libs/checkpoint/Makefile | 5 ++++- libs/cli/Makefile | 5 ++++- libs/langgraph/Makefile | 6 +++++- libs/prebuilt/Makefile | 6 +++++- libs/sdk-py/Makefile | 5 ++++- 7 files changed, 30 insertions(+), 7 deletions(-) diff --git a/libs/checkpoint-postgres/Makefile b/libs/checkpoint-postgres/Makefile index 1116d5daf..c4f560f0e 100644 --- a/libs/checkpoint-postgres/Makefile +++ b/libs/checkpoint-postgres/Makefile @@ -1,4 +1,4 @@ -.PHONY: test test_watch lint format +.PHONY: test test_watch lint type format ###################### # TESTING AND COVERAGE @@ -61,6 +61,9 @@ lint lint_diff lint_package lint_tests: [ "$(PYTHON_FILES)" = "" ] || mkdir -p $(MYPY_CACHE) [ "$(PYTHON_FILES)" = "" ] || uv run mypy $(PYTHON_FILES) --cache-dir $(MYPY_CACHE) +type: + mkdir -p $(MYPY_CACHE) && uv run mypy $(PYTHON_FILES) --cache-dir $(MYPY_CACHE) + format format_diff: uv run ruff format $(PYTHON_FILES) uv run ruff check --select I --fix $(PYTHON_FILES) diff --git a/libs/checkpoint-sqlite/Makefile b/libs/checkpoint-sqlite/Makefile index 376c05d74..66f7cf600 100644 --- a/libs/checkpoint-sqlite/Makefile +++ b/libs/checkpoint-sqlite/Makefile @@ -1,4 +1,4 @@ -.PHONY: test test_watch lint format +.PHONY: test test_watch lint type format ###################### # TESTING AND COVERAGE @@ -32,6 +32,9 @@ lint lint_diff lint_package lint_tests: [ "$(PYTHON_FILES)" = "" ] || mkdir -p $(MYPY_CACHE) [ "$(PYTHON_FILES)" = "" ] || uv run mypy $(PYTHON_FILES) --cache-dir $(MYPY_CACHE) +type: + mkdir -p $(MYPY_CACHE) && uv run mypy $(PYTHON_FILES) --cache-dir $(MYPY_CACHE) + format format_diff: uv run ruff format $(PYTHON_FILES) uv run ruff check --select I --fix $(PYTHON_FILES) diff --git a/libs/checkpoint/Makefile b/libs/checkpoint/Makefile index 376c05d74..66f7cf600 100644 --- a/libs/checkpoint/Makefile +++ b/libs/checkpoint/Makefile @@ -1,4 +1,4 @@ -.PHONY: test test_watch lint format +.PHONY: test test_watch lint type format ###################### # TESTING AND COVERAGE @@ -32,6 +32,9 @@ lint lint_diff lint_package lint_tests: [ "$(PYTHON_FILES)" = "" ] || mkdir -p $(MYPY_CACHE) [ "$(PYTHON_FILES)" = "" ] || uv run mypy $(PYTHON_FILES) --cache-dir $(MYPY_CACHE) +type: + mkdir -p $(MYPY_CACHE) && uv run mypy $(PYTHON_FILES) --cache-dir $(MYPY_CACHE) + format format_diff: uv run ruff format $(PYTHON_FILES) uv run ruff check --select I --fix $(PYTHON_FILES) diff --git a/libs/cli/Makefile b/libs/cli/Makefile index 60a781d8e..0de616fa7 100644 --- a/libs/cli/Makefile +++ b/libs/cli/Makefile @@ -1,4 +1,4 @@ -.PHONY: test lint format test-integration update-schema bump-version +.PHONY: test lint type format test-integration update-schema bump-version ###################### # TESTING AND COVERAGE @@ -29,6 +29,9 @@ lint lint_diff lint_package lint_tests: [ "$(PYTHON_FILES)" = "" ] || uv run ruff check --select I $(PYTHON_FILES) [ "$(PYTHON_FILES)" = "" ] || mkdir -p $(MYPY_CACHE) || uv run mypy $(PYTHON_FILES) --cache-dir $(MYPY_CACHE) +type: + mkdir -p $(MYPY_CACHE) && uv run mypy $(PYTHON_FILES) --cache-dir $(MYPY_CACHE) + format format_diff: uv run ruff format $(PYTHON_FILES) uv run ruff check --select I --fix $(PYTHON_FILES) diff --git a/libs/langgraph/Makefile b/libs/langgraph/Makefile index 86852414a..3b406baf4 100644 --- a/libs/langgraph/Makefile +++ b/libs/langgraph/Makefile @@ -1,4 +1,4 @@ -.PHONY: all format lint test test_watch integration_tests spell_check spell_fix benchmark profile start-dev-server integration_tests +.PHONY: all format lint type test test_watch integration_tests spell_check spell_fix benchmark profile start-dev-server integration_tests # Default target executed when no arguments are given to make. all: help @@ -125,6 +125,9 @@ lint lint_diff lint_package lint_tests: [ "$(PYTHON_FILES)" = "" ] || mkdir -p $(MYPY_CACHE) [ "$(PYTHON_FILES)" = "" ] || uv run mypy langgraph --cache-dir $(MYPY_CACHE) +type: + mkdir -p $(MYPY_CACHE) && uv run mypy langgraph --cache-dir $(MYPY_CACHE) + format format_diff: uv run ruff format $(PYTHON_FILES) uv run ruff check --select I --fix $(PYTHON_FILES) @@ -147,6 +150,7 @@ help: @echo '-- LINTING --' @echo 'format - run code formatters' @echo 'lint - run linters' + @echo 'type - run type checking' @echo 'spell_check - run codespell on the project' @echo 'spell_fix - run codespell on the project and fix the errors' @echo '-- TESTS --' diff --git a/libs/prebuilt/Makefile b/libs/prebuilt/Makefile index f737f4d81..d42454c2e 100644 --- a/libs/prebuilt/Makefile +++ b/libs/prebuilt/Makefile @@ -1,4 +1,4 @@ -.PHONY: all format lint test test-fast test_watch integration_tests spell_check spell_fix benchmark profile +.PHONY: all format lint type test test-fast test_watch integration_tests spell_check spell_fix benchmark profile # Default target executed when no arguments are given to make. all: help @@ -50,6 +50,9 @@ lint lint_diff lint_package lint_tests: [ "$(PYTHON_FILES)" = "" ] || mkdir -p $(MYPY_CACHE) [ "$(PYTHON_FILES)" = "" ] || uv run mypy langgraph --cache-dir $(MYPY_CACHE) +type: + mkdir -p $(MYPY_CACHE) && uv run mypy langgraph --cache-dir $(MYPY_CACHE) + format format_diff: uv run ruff format $(PYTHON_FILES) uv run ruff check --fix $(PYTHON_FILES) @@ -72,6 +75,7 @@ help: @echo '-- LINTING --' @echo 'format - run code formatters' @echo 'lint - run linters' + @echo 'type - run type checking' @echo 'spell_check - run codespell on the project' @echo 'spell_fix - run codespell on the project and fix the errors' @echo '-- TESTS --' diff --git a/libs/sdk-py/Makefile b/libs/sdk-py/Makefile index 59990054c..a1efa0bfd 100644 --- a/libs/sdk-py/Makefile +++ b/libs/sdk-py/Makefile @@ -1,4 +1,4 @@ -.PHONY: lint format test +.PHONY: lint type format test test: uv run pytest tests @@ -19,6 +19,9 @@ lint lint_diff: [ "$(PYTHON_FILES)" = "" ] || uv run ruff check --select I $(PYTHON_FILES) uv run ty check . +type: + uv run ty check . + format format_diff: uv run ruff check --select I --fix $(PYTHON_FILES) uv run ruff format $(PYTHON_FILES) From ed293f16d66ea6925dba95b4a763e050ac085322 Mon Sep 17 00:00:00 2001 From: William FH <13333726+hinthornw@users.noreply.github.com> Date: Sun, 22 Feb 2026 20:16:45 -0800 Subject: [PATCH 2/2] fix(cli): update graph config schema to support description field (#6895) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Summary - The config processing code in `config.py` already handles graphs defined as `{"path": "...", "description": "..."}` dicts, but the `Config` TypedDict and JSON schema only declared `dict[str, str]` - Added a `GraphDef` TypedDict with `path` and optional `description` fields - Updated `Config.graphs` to `dict[str, str | GraphDef]` and regenerated the JSON schemas - This makes the schema match the actual runtime behavior and fixes IDE/schema validation for users who use the dict format ## Test plan - [x] `make format` passes - [x] `make lint` passes - [x] `make test` passes (all 85 tests) - [x] Schema regeneration produces consistent output Release Notes: Update `langgraph.json` schema to support `{"path": "...", "description": "..."}` format for graph definitions. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-authored-by: Claude Opus 4.6 --- libs/cli/generate_schema.py | 2 ++ libs/cli/langgraph_cli/schemas.py | 30 +++++++++++++++++---- libs/cli/schemas/schema.json | 45 ++++++++++++++++++++++++++++--- libs/cli/schemas/schema.v0.json | 45 ++++++++++++++++++++++++++++--- 4 files changed, 109 insertions(+), 13 deletions(-) diff --git a/libs/cli/generate_schema.py b/libs/cli/generate_schema.py index 32543c037..3aa1ccd16 100644 --- a/libs/cli/generate_schema.py +++ b/libs/cli/generate_schema.py @@ -20,6 +20,7 @@ from langgraph_cli.schemas import ( Config, ConfigurableHeaderConfig, CorsConfig, + GraphDef, HttpConfig, IndexConfig, SecurityConfig, @@ -108,6 +109,7 @@ def add_descriptions_to_schema(schema, cls): # Find the class that corresponds to this definition for potential_cls in [ Config, + GraphDef, StoreConfig, IndexConfig, AuthConfig, diff --git a/libs/cli/langgraph_cli/schemas.py b/libs/cli/langgraph_cli/schemas.py index 63dcce4c1..011ce4752 100644 --- a/libs/cli/langgraph_cli/schemas.py +++ b/libs/cli/langgraph_cli/schemas.py @@ -529,6 +529,21 @@ class WebhookUrlPolicy(TypedDict, total=False): """Disallow relative URLs (internal loopback calls) when true.""" +class GraphDef(TypedDict, total=False): + """Definition of a graph with additional metadata.""" + + path: str + """Required. Import path to the graph object. + + Format: "path/to/file.py:object_name" + """ + description: str | None + """Optional. A description of the graph's purpose and functionality. + + This description is surfaced in the API and can help users understand what the graph does. + """ + + class WebhooksConfig(TypedDict, total=False): env_prefix: str """Required prefix for environment variables referenced in header templates. @@ -619,19 +634,23 @@ class Config(TypedDict, total=False): Defaults to an empty list, meaning no additional packages installed beyond your base environment. """ - graphs: dict[str, str] + graphs: dict[str, str | GraphDef] """Optional. Named definitions of graphs, each pointing to a Python object. - + Graphs can be StateGraph, @entrypoint, or any other Pregel object OR they can point to (async) context managers that accept a single configuration argument (of type RunnableConfig) and return a pregel object (instance of Stategraph, etc.). - - Keys are graph names, values are "path/to/file.py:object_name". + + Keys are graph names, values are either "path/to/file.py:object_name" strings + or objects with a "path" key and optional "description" key. Example: { "mygraph": "graphs/my_graph.py:graph_definition", - "anothergraph": "graphs/another.py:get_graph" + "anothergraph": { + "path": "graphs/another.py:get_graph", + "description": "A graph that does X" + } } """ @@ -696,6 +715,7 @@ class Config(TypedDict, total=False): __all__ = [ "Config", + "GraphDef", "StoreConfig", "CheckpointerConfig", "AuthConfig", diff --git a/libs/cli/schemas/schema.json b/libs/cli/schemas/schema.json index 7b1117811..4ba2700e8 100644 --- a/libs/cli/schemas/schema.json +++ b/libs/cli/schemas/schema.json @@ -127,9 +127,16 @@ "graphs": { "type": "object", "additionalProperties": { - "type": "string" + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/$defs/GraphDef" + } + ] }, - "description": "Optional. Named definitions of graphs, each pointing to a Python object.\n\n\nGraphs can be StateGraph, @entrypoint, or any other Pregel object OR they can point to (async) context\nmanagers that accept a single configuration argument (of type RunnableConfig) and return a pregel object\n(instance of Stategraph, etc.).\n" + "description": "Optional. Named definitions of graphs, each pointing to a Python object.\n\n\nGraphs can be StateGraph, @entrypoint, or any other Pregel object OR they can point to (async) context\nmanagers that accept a single configuration argument (of type RunnableConfig) and return a pregel object\n(instance of Stategraph, etc.).\n\nor objects with a \"path\" key and optional \"description\" key." }, "http": { "anyOf": [ @@ -341,9 +348,16 @@ "graphs": { "type": "object", "additionalProperties": { - "type": "string" + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/$defs/GraphDef" + } + ] }, - "description": "Optional. Named definitions of graphs, each pointing to a Python object.\n\n\nGraphs can be StateGraph, @entrypoint, or any other Pregel object OR they can point to (async) context\nmanagers that accept a single configuration argument (of type RunnableConfig) and return a pregel object\n(instance of Stategraph, etc.).\n" + "description": "Optional. Named definitions of graphs, each pointing to a Python object.\n\n\nGraphs can be StateGraph, @entrypoint, or any other Pregel object OR they can point to (async) context\nmanagers that accept a single configuration argument (of type RunnableConfig) and return a pregel object\n(instance of Stategraph, etc.).\n\nor objects with a \"path\" key and optional \"description\" key." }, "http": { "anyOf": [ @@ -662,6 +676,29 @@ }, "required": [] }, + "GraphDef": { + "title": "GraphDef", + "description": "Definition of a graph with additional metadata.", + "type": "object", + "properties": { + "description": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Optional. A description of the graph's purpose and functionality.\n\nThis description is surfaced in the API and can help users understand what the graph does.\n" + }, + "path": { + "type": "string", + "description": "Required. Import path to the graph object.\n" + } + }, + "required": [] + }, "HttpConfig": { "title": "HttpConfig", "description": "Configuration for the built-in HTTP server that powers your deployment's routes and endpoints.", diff --git a/libs/cli/schemas/schema.v0.json b/libs/cli/schemas/schema.v0.json index 7b1117811..4ba2700e8 100644 --- a/libs/cli/schemas/schema.v0.json +++ b/libs/cli/schemas/schema.v0.json @@ -127,9 +127,16 @@ "graphs": { "type": "object", "additionalProperties": { - "type": "string" + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/$defs/GraphDef" + } + ] }, - "description": "Optional. Named definitions of graphs, each pointing to a Python object.\n\n\nGraphs can be StateGraph, @entrypoint, or any other Pregel object OR they can point to (async) context\nmanagers that accept a single configuration argument (of type RunnableConfig) and return a pregel object\n(instance of Stategraph, etc.).\n" + "description": "Optional. Named definitions of graphs, each pointing to a Python object.\n\n\nGraphs can be StateGraph, @entrypoint, or any other Pregel object OR they can point to (async) context\nmanagers that accept a single configuration argument (of type RunnableConfig) and return a pregel object\n(instance of Stategraph, etc.).\n\nor objects with a \"path\" key and optional \"description\" key." }, "http": { "anyOf": [ @@ -341,9 +348,16 @@ "graphs": { "type": "object", "additionalProperties": { - "type": "string" + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/$defs/GraphDef" + } + ] }, - "description": "Optional. Named definitions of graphs, each pointing to a Python object.\n\n\nGraphs can be StateGraph, @entrypoint, or any other Pregel object OR they can point to (async) context\nmanagers that accept a single configuration argument (of type RunnableConfig) and return a pregel object\n(instance of Stategraph, etc.).\n" + "description": "Optional. Named definitions of graphs, each pointing to a Python object.\n\n\nGraphs can be StateGraph, @entrypoint, or any other Pregel object OR they can point to (async) context\nmanagers that accept a single configuration argument (of type RunnableConfig) and return a pregel object\n(instance of Stategraph, etc.).\n\nor objects with a \"path\" key and optional \"description\" key." }, "http": { "anyOf": [ @@ -662,6 +676,29 @@ }, "required": [] }, + "GraphDef": { + "title": "GraphDef", + "description": "Definition of a graph with additional metadata.", + "type": "object", + "properties": { + "description": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Optional. A description of the graph's purpose and functionality.\n\nThis description is surfaced in the API and can help users understand what the graph does.\n" + }, + "path": { + "type": "string", + "description": "Required. Import path to the graph object.\n" + } + }, + "required": [] + }, "HttpConfig": { "title": "HttpConfig", "description": "Configuration for the built-in HTTP server that powers your deployment's routes and endpoints.",