Compare commits

..
Author SHA1 Message Date
Sydney RunkleandGitHub 7b9ff6129b release: langgraph and prebuilt 1.0.7 (#6712) 2026-01-22 11:28:22 -05:00
Sydney RunkleandGitHub c1b3598ca8 feat: support dynamic tool calling via tool override in wrap_model_call (#6711)
Allow overriding `tool` impl in `wrap_tool_call` in order to support
dynamically registered tools via middleware
2026-01-22 15:53:43 +00:00
6 changed files with 310 additions and 83 deletions
+2 -2
View File
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
[project]
name = "langgraph"
version = "1.0.6"
version = "1.0.7"
description = "Building stateful, multi-actor applications with LLMs"
authors = []
requires-python = ">=3.10"
@@ -27,7 +27,7 @@ dependencies = [
"langchain-core>=0.1",
"langgraph-checkpoint>=2.1.0,<5.0.0",
"langgraph-sdk>=0.3.0,<0.4.0",
"langgraph-prebuilt>=1.0.2,<1.1.0",
"langgraph-prebuilt>=1.0.7,<1.1.0",
"xxhash>=3.5.0",
"pydantic>=2.7.4",
]
+77 -77
View File
@@ -192,7 +192,7 @@ name = "blockbuster"
version = "1.5.26"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "forbiddenfruit", marker = "python_full_version >= '3.11' and implementation_name == 'cpython'" },
{ name = "forbiddenfruit", marker = "python_full_version >= '3.11' and python_full_version < '3.14' and implementation_name == 'cpython'" },
]
sdist = { url = "https://files.pythonhosted.org/packages/55/e0/dcbab602790a576b0b94108c07e2c048e5897df7cc83722a89582d733987/blockbuster-1.5.26.tar.gz", hash = "sha256:cc3ce8c70fa852a97ee3411155f31e4ad2665cd1c6c7d2f8bb1851dab61dc629", size = 36085, upload-time = "2025-12-05T10:43:47.735Z" }
wheels = [
@@ -384,7 +384,7 @@ name = "click"
version = "8.3.1"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "colorama", marker = "sys_platform == 'win32'" },
{ name = "colorama", marker = "python_full_version < '3.14' and sys_platform == 'win32'" },
]
sdist = { url = "https://files.pythonhosted.org/packages/3d/fa/656b739db8587d7b5dfa22e22ed02566950fbfbcdc20311993483657a5c0/click-8.3.1.tar.gz", hash = "sha256:12ff4785d337a1bb490bb7e9c2b1ee5da3112e94a8622f26a6c77f5d2fc6842a", size = 295065, upload-time = "2025-11-15T20:45:42.706Z" }
wheels = [
@@ -527,7 +527,7 @@ name = "cryptography"
version = "46.0.3"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "cffi", marker = "python_full_version >= '3.11' and platform_python_implementation != 'PyPy'" },
{ name = "cffi", marker = "python_full_version >= '3.11' and python_full_version < '3.14' and platform_python_implementation != 'PyPy'" },
]
sdist = { url = "https://files.pythonhosted.org/packages/9f/33/c00162f49c0e2fe8064a62cb92b93e50c74a72bc370ab92f86112b33ff62/cryptography-46.0.3.tar.gz", hash = "sha256:a8b17438104fed022ce745b362294d9ce35b4c2e45c1d958ad4a4b019285f4a1", size = 749258, upload-time = "2025-10-15T23:18:31.74Z" }
wheels = [
@@ -692,7 +692,7 @@ name = "googleapis-common-protos"
version = "1.72.0"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "protobuf", marker = "python_full_version >= '3.11'" },
{ name = "protobuf", marker = "python_full_version >= '3.11' and python_full_version < '3.14'" },
]
sdist = { url = "https://files.pythonhosted.org/packages/e5/7b/adfd75544c415c487b33061fe7ae526165241c1ea133f9a9125a56b39fd8/googleapis_common_protos-1.72.0.tar.gz", hash = "sha256:e55a601c1b32b52d7a3e65f43563e2aa61bcd737998ee672ac9b951cd49319f5", size = 147433, upload-time = "2025-11-06T18:29:24.087Z" }
wheels = [
@@ -704,7 +704,7 @@ name = "grpcio"
version = "1.76.0"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "typing-extensions", marker = "python_full_version >= '3.11'" },
{ name = "typing-extensions", marker = "python_full_version >= '3.11' and python_full_version < '3.14'" },
]
sdist = { url = "https://files.pythonhosted.org/packages/b6/e0/318c1ce3ae5a17894d5791e87aea147587c9e702f24122cc7a5c8bbaeeb1/grpcio-1.76.0.tar.gz", hash = "sha256:7be78388d6da1a25c0d5ec506523db58b18be22d9c37d8d3a32c08be4987bd73", size = 12785182, upload-time = "2025-10-21T16:23:12.106Z" }
wheels = [
@@ -765,8 +765,8 @@ name = "grpcio-health-checking"
version = "1.76.0"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "grpcio", marker = "python_full_version >= '3.11'" },
{ name = "protobuf", marker = "python_full_version >= '3.11'" },
{ name = "grpcio", marker = "python_full_version >= '3.11' and python_full_version < '3.14'" },
{ name = "protobuf", marker = "python_full_version >= '3.11' and python_full_version < '3.14'" },
]
sdist = { url = "https://files.pythonhosted.org/packages/3e/96/5a52dcf21078b47ffa0c2ed613c3153a06f138edb6133792bace5f1ccc1d/grpcio_health_checking-1.76.0.tar.gz", hash = "sha256:b7a99d74096b3ab3a59987fc02374068e1c180a352e8d1f79f10e5a23727098d", size = 16784, upload-time = "2025-10-21T16:28:55.204Z" }
wheels = [
@@ -778,9 +778,9 @@ name = "grpcio-tools"
version = "1.75.1"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "grpcio", marker = "python_full_version >= '3.11'" },
{ name = "protobuf", marker = "python_full_version >= '3.11'" },
{ name = "setuptools", marker = "python_full_version >= '3.11'" },
{ name = "grpcio", marker = "python_full_version >= '3.11' and python_full_version < '3.14'" },
{ name = "protobuf", marker = "python_full_version >= '3.11' and python_full_version < '3.14'" },
{ name = "setuptools", marker = "python_full_version >= '3.11' and python_full_version < '3.14'" },
]
sdist = { url = "https://files.pythonhosted.org/packages/7d/76/0cd2a2bb379275c319544a3ab613dc3cea7a167503908c1b4de55f82bd9e/grpcio_tools-1.75.1.tar.gz", hash = "sha256:bb78960cf3d58941e1fec70cbdaccf255918beed13c34112a6915a6d8facebd1", size = 5390470, upload-time = "2025-09-26T09:10:11.948Z" }
wheels = [
@@ -887,7 +887,7 @@ name = "importlib-metadata"
version = "8.7.1"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "zipp", marker = "python_full_version >= '3.11'" },
{ name = "zipp", marker = "python_full_version >= '3.11' and python_full_version < '3.14'" },
]
sdist = { url = "https://files.pythonhosted.org/packages/f3/49/3b30cad09e7771a4982d9975a8cbf64f00d4a1ececb53297f1d9a7be1b10/importlib_metadata-8.7.1.tar.gz", hash = "sha256:49fef1ae6440c182052f407c8d34a68f72efc36db9ca90dc0113398f2fdde8bb", size = 57107, upload-time = "2025-12-21T10:00:19.278Z" }
wheels = [
@@ -1372,7 +1372,7 @@ wheels = [
[[package]]
name = "langgraph"
version = "1.0.6"
version = "1.0.7"
source = { editable = "." }
dependencies = [
{ name = "langchain-core" },
@@ -1518,33 +1518,33 @@ name = "langgraph-api"
version = "0.6.39"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "cloudpickle", marker = "python_full_version >= '3.11'" },
{ name = "cryptography", marker = "python_full_version >= '3.11'" },
{ name = "grpcio", marker = "python_full_version >= '3.11'" },
{ name = "grpcio-health-checking", marker = "python_full_version >= '3.11'" },
{ name = "grpcio-tools", marker = "python_full_version >= '3.11'" },
{ name = "httpx", marker = "python_full_version >= '3.11'" },
{ name = "jsonschema-rs", marker = "python_full_version >= '3.11'" },
{ name = "langchain-core", marker = "python_full_version >= '3.11'" },
{ name = "langgraph", marker = "python_full_version >= '3.11'" },
{ name = "langgraph-checkpoint", marker = "python_full_version >= '3.11'" },
{ name = "langgraph-runtime-inmem", marker = "python_full_version >= '3.11'" },
{ name = "langgraph-sdk", marker = "python_full_version >= '3.11'" },
{ name = "langsmith", extra = ["otel"], marker = "python_full_version >= '3.11'" },
{ name = "opentelemetry-api", marker = "python_full_version >= '3.11'" },
{ name = "opentelemetry-exporter-otlp-proto-http", marker = "python_full_version >= '3.11'" },
{ name = "opentelemetry-sdk", marker = "python_full_version >= '3.11'" },
{ name = "orjson", marker = "python_full_version >= '3.11'" },
{ name = "protobuf", marker = "python_full_version >= '3.11'" },
{ name = "pyjwt", marker = "python_full_version >= '3.11'" },
{ name = "sse-starlette", marker = "python_full_version >= '3.11'" },
{ name = "starlette", marker = "python_full_version >= '3.11'" },
{ name = "structlog", marker = "python_full_version >= '3.11'" },
{ name = "tenacity", marker = "python_full_version >= '3.11'" },
{ name = "truststore", marker = "python_full_version >= '3.11'" },
{ name = "uuid-utils", marker = "python_full_version >= '3.11'" },
{ name = "uvicorn", marker = "python_full_version >= '3.11'" },
{ name = "watchfiles", marker = "python_full_version >= '3.11'" },
{ name = "cloudpickle", marker = "python_full_version >= '3.11' and python_full_version < '3.14'" },
{ name = "cryptography", marker = "python_full_version >= '3.11' and python_full_version < '3.14'" },
{ name = "grpcio", marker = "python_full_version >= '3.11' and python_full_version < '3.14'" },
{ name = "grpcio-health-checking", marker = "python_full_version >= '3.11' and python_full_version < '3.14'" },
{ name = "grpcio-tools", marker = "python_full_version >= '3.11' and python_full_version < '3.14'" },
{ name = "httpx", marker = "python_full_version >= '3.11' and python_full_version < '3.14'" },
{ name = "jsonschema-rs", marker = "python_full_version >= '3.11' and python_full_version < '3.14'" },
{ name = "langchain-core", marker = "python_full_version >= '3.11' and python_full_version < '3.14'" },
{ name = "langgraph", marker = "python_full_version >= '3.11' and python_full_version < '3.14'" },
{ name = "langgraph-checkpoint", marker = "python_full_version >= '3.11' and python_full_version < '3.14'" },
{ name = "langgraph-runtime-inmem", marker = "python_full_version >= '3.11' and python_full_version < '3.14'" },
{ name = "langgraph-sdk", marker = "python_full_version >= '3.11' and python_full_version < '3.14'" },
{ name = "langsmith", extra = ["otel"], marker = "python_full_version >= '3.11' and python_full_version < '3.14'" },
{ name = "opentelemetry-api", marker = "python_full_version >= '3.11' and python_full_version < '3.14'" },
{ name = "opentelemetry-exporter-otlp-proto-http", marker = "python_full_version >= '3.11' and python_full_version < '3.14'" },
{ name = "opentelemetry-sdk", marker = "python_full_version >= '3.11' and python_full_version < '3.14'" },
{ name = "orjson", marker = "python_full_version >= '3.11' and python_full_version < '3.14'" },
{ name = "protobuf", marker = "python_full_version >= '3.11' and python_full_version < '3.14'" },
{ name = "pyjwt", marker = "python_full_version >= '3.11' and python_full_version < '3.14'" },
{ name = "sse-starlette", marker = "python_full_version >= '3.11' and python_full_version < '3.14'" },
{ name = "starlette", marker = "python_full_version >= '3.11' and python_full_version < '3.14'" },
{ name = "structlog", marker = "python_full_version >= '3.11' and python_full_version < '3.14'" },
{ name = "tenacity", marker = "python_full_version >= '3.11' and python_full_version < '3.14'" },
{ name = "truststore", marker = "python_full_version >= '3.11' and python_full_version < '3.14'" },
{ name = "uuid-utils", marker = "python_full_version >= '3.11' and python_full_version < '3.14'" },
{ name = "uvicorn", marker = "python_full_version >= '3.11' and python_full_version < '3.14'" },
{ name = "watchfiles", marker = "python_full_version >= '3.11' and python_full_version < '3.14'" },
]
sdist = { url = "https://files.pythonhosted.org/packages/b2/52/f7d25b475768e5e0748d4725c64909fc7e56a714e064976a32e7c68f6d9e/langgraph_api-0.6.39.tar.gz", hash = "sha256:052191ec9c49d76b0d5592a60fe6324eafde40e7a1afba65d1ce11a6a074674b", size = 447880, upload-time = "2026-01-16T19:54:07.475Z" }
wheels = [
@@ -1692,15 +1692,15 @@ test = [
name = "langgraph-cli"
source = { editable = "../cli" }
dependencies = [
{ name = "click" },
{ name = "langgraph-sdk", marker = "python_full_version >= '3.11'" },
{ name = "click", marker = "python_full_version < '3.14'" },
{ name = "langgraph-sdk", marker = "python_full_version >= '3.11' and python_full_version < '3.14'" },
]
[package.optional-dependencies]
inmem = [
{ name = "langgraph-api", marker = "python_full_version >= '3.11'" },
{ name = "langgraph-runtime-inmem", marker = "python_full_version >= '3.11'" },
{ name = "python-dotenv" },
{ name = "langgraph-api", marker = "python_full_version >= '3.11' and python_full_version < '3.14'" },
{ name = "langgraph-runtime-inmem", marker = "python_full_version >= '3.11' and python_full_version < '3.14'" },
{ name = "python-dotenv", marker = "python_full_version < '3.14'" },
]
[package.metadata]
@@ -1740,7 +1740,7 @@ test = [
[[package]]
name = "langgraph-prebuilt"
version = "1.0.6"
version = "1.0.7"
source = { editable = "../prebuilt" }
dependencies = [
{ name = "langchain-core" },
@@ -1794,12 +1794,12 @@ name = "langgraph-runtime-inmem"
version = "0.22.1"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "blockbuster", marker = "python_full_version >= '3.11'" },
{ name = "langgraph", marker = "python_full_version >= '3.11'" },
{ name = "langgraph-checkpoint", marker = "python_full_version >= '3.11'" },
{ name = "sse-starlette", marker = "python_full_version >= '3.11'" },
{ name = "starlette", marker = "python_full_version >= '3.11'" },
{ name = "structlog", marker = "python_full_version >= '3.11'" },
{ name = "blockbuster", marker = "python_full_version >= '3.11' and python_full_version < '3.14'" },
{ name = "langgraph", marker = "python_full_version >= '3.11' and python_full_version < '3.14'" },
{ name = "langgraph-checkpoint", marker = "python_full_version >= '3.11' and python_full_version < '3.14'" },
{ name = "sse-starlette", marker = "python_full_version >= '3.11' and python_full_version < '3.14'" },
{ name = "starlette", marker = "python_full_version >= '3.11' and python_full_version < '3.14'" },
{ name = "structlog", marker = "python_full_version >= '3.11' and python_full_version < '3.14'" },
]
sdist = { url = "https://files.pythonhosted.org/packages/cb/8d/4b42a852a869c6a60aceae4e6157030c427ae9c07bf28769cc8e2fcec16b/langgraph_runtime_inmem-0.22.1.tar.gz", hash = "sha256:bbd983975dc372ad5cd5288263d3471732b0dff2bab3c6f41e5fe5b3a38ea1ee", size = 104172, upload-time = "2026-01-16T15:17:23.381Z" }
wheels = [
@@ -1868,9 +1868,9 @@ wheels = [
[package.optional-dependencies]
otel = [
{ name = "opentelemetry-api", marker = "python_full_version >= '3.11'" },
{ name = "opentelemetry-exporter-otlp-proto-http", marker = "python_full_version >= '3.11'" },
{ name = "opentelemetry-sdk", marker = "python_full_version >= '3.11'" },
{ name = "opentelemetry-api", marker = "python_full_version >= '3.11' and python_full_version < '3.14'" },
{ name = "opentelemetry-exporter-otlp-proto-http", marker = "python_full_version >= '3.11' and python_full_version < '3.14'" },
{ name = "opentelemetry-sdk", marker = "python_full_version >= '3.11' and python_full_version < '3.14'" },
]
[[package]]
@@ -2216,8 +2216,8 @@ name = "opentelemetry-api"
version = "1.39.1"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "importlib-metadata", marker = "python_full_version >= '3.11'" },
{ name = "typing-extensions", marker = "python_full_version >= '3.11'" },
{ name = "importlib-metadata", marker = "python_full_version >= '3.11' and python_full_version < '3.14'" },
{ name = "typing-extensions", marker = "python_full_version >= '3.11' and python_full_version < '3.14'" },
]
sdist = { url = "https://files.pythonhosted.org/packages/97/b9/3161be15bb8e3ad01be8be5a968a9237c3027c5be504362ff800fca3e442/opentelemetry_api-1.39.1.tar.gz", hash = "sha256:fbde8c80e1b937a2c61f20347e91c0c18a1940cecf012d62e65a7caf08967c9c", size = 65767, upload-time = "2025-12-11T13:32:39.182Z" }
wheels = [
@@ -2229,7 +2229,7 @@ name = "opentelemetry-exporter-otlp-proto-common"
version = "1.39.1"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "opentelemetry-proto", marker = "python_full_version >= '3.11'" },
{ name = "opentelemetry-proto", marker = "python_full_version >= '3.11' and python_full_version < '3.14'" },
]
sdist = { url = "https://files.pythonhosted.org/packages/e9/9d/22d241b66f7bbde88a3bfa6847a351d2c46b84de23e71222c6aae25c7050/opentelemetry_exporter_otlp_proto_common-1.39.1.tar.gz", hash = "sha256:763370d4737a59741c89a67b50f9e39271639ee4afc999dadfe768541c027464", size = 20409, upload-time = "2025-12-11T13:32:40.885Z" }
wheels = [
@@ -2241,13 +2241,13 @@ name = "opentelemetry-exporter-otlp-proto-http"
version = "1.39.1"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "googleapis-common-protos", marker = "python_full_version >= '3.11'" },
{ name = "opentelemetry-api", marker = "python_full_version >= '3.11'" },
{ name = "opentelemetry-exporter-otlp-proto-common", marker = "python_full_version >= '3.11'" },
{ name = "opentelemetry-proto", marker = "python_full_version >= '3.11'" },
{ name = "opentelemetry-sdk", marker = "python_full_version >= '3.11'" },
{ name = "requests", marker = "python_full_version >= '3.11'" },
{ name = "typing-extensions", marker = "python_full_version >= '3.11'" },
{ name = "googleapis-common-protos", marker = "python_full_version >= '3.11' and python_full_version < '3.14'" },
{ name = "opentelemetry-api", marker = "python_full_version >= '3.11' and python_full_version < '3.14'" },
{ name = "opentelemetry-exporter-otlp-proto-common", marker = "python_full_version >= '3.11' and python_full_version < '3.14'" },
{ name = "opentelemetry-proto", marker = "python_full_version >= '3.11' and python_full_version < '3.14'" },
{ name = "opentelemetry-sdk", marker = "python_full_version >= '3.11' and python_full_version < '3.14'" },
{ name = "requests", marker = "python_full_version >= '3.11' and python_full_version < '3.14'" },
{ name = "typing-extensions", marker = "python_full_version >= '3.11' and python_full_version < '3.14'" },
]
sdist = { url = "https://files.pythonhosted.org/packages/80/04/2a08fa9c0214ae38880df01e8bfae12b067ec0793446578575e5080d6545/opentelemetry_exporter_otlp_proto_http-1.39.1.tar.gz", hash = "sha256:31bdab9745c709ce90a49a0624c2bd445d31a28ba34275951a6a362d16a0b9cb", size = 17288, upload-time = "2025-12-11T13:32:42.029Z" }
wheels = [
@@ -2259,7 +2259,7 @@ name = "opentelemetry-proto"
version = "1.39.1"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "protobuf", marker = "python_full_version >= '3.11'" },
{ name = "protobuf", marker = "python_full_version >= '3.11' and python_full_version < '3.14'" },
]
sdist = { url = "https://files.pythonhosted.org/packages/49/1d/f25d76d8260c156c40c97c9ed4511ec0f9ce353f8108ca6e7561f82a06b2/opentelemetry_proto-1.39.1.tar.gz", hash = "sha256:6c8e05144fc0d3ed4d22c2289c6b126e03bcd0e6a7da0f16cedd2e1c2772e2c8", size = 46152, upload-time = "2025-12-11T13:32:48.681Z" }
wheels = [
@@ -2271,9 +2271,9 @@ name = "opentelemetry-sdk"
version = "1.39.1"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "opentelemetry-api", marker = "python_full_version >= '3.11'" },
{ name = "opentelemetry-semantic-conventions", marker = "python_full_version >= '3.11'" },
{ name = "typing-extensions", marker = "python_full_version >= '3.11'" },
{ name = "opentelemetry-api", marker = "python_full_version >= '3.11' and python_full_version < '3.14'" },
{ name = "opentelemetry-semantic-conventions", marker = "python_full_version >= '3.11' and python_full_version < '3.14'" },
{ name = "typing-extensions", marker = "python_full_version >= '3.11' and python_full_version < '3.14'" },
]
sdist = { url = "https://files.pythonhosted.org/packages/eb/fb/c76080c9ba07e1e8235d24cdcc4d125ef7aa3edf23eb4e497c2e50889adc/opentelemetry_sdk-1.39.1.tar.gz", hash = "sha256:cf4d4563caf7bff906c9f7967e2be22d0d6b349b908be0d90fb21c8e9c995cc6", size = 171460, upload-time = "2025-12-11T13:32:49.369Z" }
wheels = [
@@ -2285,8 +2285,8 @@ name = "opentelemetry-semantic-conventions"
version = "0.60b1"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "opentelemetry-api", marker = "python_full_version >= '3.11'" },
{ name = "typing-extensions", marker = "python_full_version >= '3.11'" },
{ name = "opentelemetry-api", marker = "python_full_version >= '3.11' and python_full_version < '3.14'" },
{ name = "typing-extensions", marker = "python_full_version >= '3.11' and python_full_version < '3.14'" },
]
sdist = { url = "https://files.pythonhosted.org/packages/91/df/553f93ed38bf22f4b999d9be9c185adb558982214f33eae539d3b5cd0858/opentelemetry_semantic_conventions-0.60b1.tar.gz", hash = "sha256:87c228b5a0669b748c76d76df6c364c369c28f1c465e50f661e39737e84bc953", size = 137935, upload-time = "2025-12-11T13:32:50.487Z" }
wheels = [
@@ -3469,9 +3469,9 @@ name = "sse-starlette"
version = "2.1.3"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "anyio", marker = "python_full_version >= '3.11'" },
{ name = "starlette", marker = "python_full_version >= '3.11'" },
{ name = "uvicorn", marker = "python_full_version >= '3.11'" },
{ name = "anyio", marker = "python_full_version >= '3.11' and python_full_version < '3.14'" },
{ name = "starlette", marker = "python_full_version >= '3.11' and python_full_version < '3.14'" },
{ name = "uvicorn", marker = "python_full_version >= '3.11' and python_full_version < '3.14'" },
]
sdist = { url = "https://files.pythonhosted.org/packages/72/fc/56ab9f116b2133521f532fce8d03194cf04dcac25f583cf3d839be4c0496/sse_starlette-2.1.3.tar.gz", hash = "sha256:9cd27eb35319e1414e3d2558ee7414487f9529ce3b3cf9b21434fd110e017169", size = 19678, upload-time = "2024-08-01T08:52:50.248Z" }
wheels = [
@@ -3497,7 +3497,7 @@ name = "starlette"
version = "0.51.0"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "anyio", marker = "python_full_version >= '3.11'" },
{ name = "anyio", marker = "python_full_version >= '3.11' and python_full_version < '3.14'" },
{ name = "typing-extensions", marker = "python_full_version >= '3.11' and python_full_version < '3.13'" },
]
sdist = { url = "https://files.pythonhosted.org/packages/e7/65/5a1fadcc40c5fdc7df421a7506b79633af8f5d5e3a95c3e72acacec644b9/starlette-0.51.0.tar.gz", hash = "sha256:4c4fda9b1bc67f84037d3d14a5112e523509c369d9d47b111b2f984b0cc5ba6c", size = 2647658, upload-time = "2026-01-10T20:23:15.043Z" }
@@ -3746,8 +3746,8 @@ name = "uvicorn"
version = "0.40.0"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "click", marker = "python_full_version >= '3.11'" },
{ name = "h11", marker = "python_full_version >= '3.11'" },
{ name = "click", marker = "python_full_version >= '3.11' and python_full_version < '3.14'" },
{ name = "h11", marker = "python_full_version >= '3.11' and python_full_version < '3.14'" },
]
sdist = { url = "https://files.pythonhosted.org/packages/c3/d1/8f3c683c9561a4e6689dd3b1d345c815f10f86acd044ee1fb9a4dcd0b8c5/uvicorn-0.40.0.tar.gz", hash = "sha256:839676675e87e73694518b5574fd0f24c9d97b46bea16df7b8c05ea1a51071ea", size = 81761, upload-time = "2025-12-21T14:16:22.45Z" }
wheels = [
@@ -3823,7 +3823,7 @@ name = "watchfiles"
version = "1.1.1"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "anyio", marker = "python_full_version >= '3.11'" },
{ name = "anyio", marker = "python_full_version >= '3.11' and python_full_version < '3.14'" },
]
sdist = { url = "https://files.pythonhosted.org/packages/c2/c9/8869df9b2a2d6c59d79220a4db37679e74f807c559ffe5265e08b227a210/watchfiles-1.1.1.tar.gz", hash = "sha256:a173cb5c16c4f40ab19cecf48a534c409f7ea983ab8fed0741304a1c0a31b3f2", size = 94440, upload-time = "2025-10-14T15:06:21.08Z" }
wheels = [
@@ -121,6 +121,7 @@ class _ToolCallRequestOverrides(TypedDict, total=False):
"""Possible overrides for ToolCallRequest.override() method."""
tool_call: ToolCall
tool: BaseTool
state: Any
+1 -1
View File
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
[project]
name = "langgraph-prebuilt"
version = "1.0.6"
version = "1.0.7"
description = "Library with high-level APIs for creating and executing LangGraph agents and tools."
authors = []
requires-python = ">=3.10"
@@ -220,7 +220,10 @@ def test_unregistered_tool_error_when_interceptor_calls_execute() -> None:
)
# Should get validation error message
assert result[0].status == "error"
assert "is not a valid tool" in result[0].content
assert (
result[0].content
== "Error: unregistered_tool is not a valid tool, try one of [registered_tool]."
)
assert result[0].tool_call_id == "2"
@@ -576,3 +579,226 @@ def test_interceptor_verifies_tool_is_none_for_unregistered() -> None:
assert len(captured_requests) == 1
assert captured_requests[0].tool is not None
assert captured_requests[0].tool.name == "registered_tool"
def test_wrap_tool_call_override_unregistered_tool_with_custom_impl() -> None:
"""Test that wrap_tool_call can provide custom implementation for unregistered tool."""
called = False
@dec_tool
def custom_tool_impl() -> str:
"""Custom tool implementation."""
nonlocal called
called = True
return "custom result"
def hook(
request: ToolCallRequest,
execute: Callable[[ToolCallRequest], ToolMessage | Command],
) -> ToolMessage | Command:
if request.tool_call["name"] == "custom_tool":
assert request.tool is None # Unregistered tools have tool=None
return execute(request.override(tool=custom_tool_impl))
return execute(request)
node = ToolNode([registered_tool], wrap_tool_call=hook)
result = node.invoke(
[
AIMessage(
"",
tool_calls=[
{"name": "custom_tool", "args": {}, "id": "1", "type": "tool_call"}
],
)
],
config=_create_config_with_runtime(),
)
assert called
assert result[0].content == "custom result"
assert result[0].tool_call_id == "1"
async def test_awrap_tool_call_override_unregistered_tool_with_custom_impl() -> None:
"""Test that awrap_tool_call can provide custom implementation for unregistered tool."""
called = False
@dec_tool
def custom_async_tool_impl() -> str:
"""Custom async tool implementation."""
nonlocal called
called = True
return "async custom result"
async def hook(
request: ToolCallRequest,
execute: Callable[[ToolCallRequest], Awaitable[ToolMessage | Command]],
) -> ToolMessage | Command:
if request.tool_call["name"] == "custom_async_tool":
assert request.tool is None # Unregistered tools have tool=None
return await execute(request.override(tool=custom_async_tool_impl))
return await execute(request)
node = ToolNode([registered_tool], awrap_tool_call=hook)
result = await node.ainvoke(
[
AIMessage(
"",
tool_calls=[
{
"name": "custom_async_tool",
"args": {},
"id": "1",
"type": "tool_call",
}
],
)
],
config=_create_config_with_runtime(),
)
assert called
assert result[0].content == "async custom result"
assert result[0].tool_call_id == "1"
def test_graceful_failure_when_hook_does_not_override_unregistered_tool_sync() -> None:
"""Test graceful failure when hook doesn't override unregistered tool."""
def passthrough_hook(
request: ToolCallRequest,
execute: Callable[[ToolCallRequest], ToolMessage | Command],
) -> ToolMessage | Command:
return execute(request)
node = ToolNode(
[registered_tool],
wrap_tool_call=passthrough_hook,
handle_tool_errors=True,
)
result = node.invoke(
[
AIMessage(
"",
tool_calls=[
{"name": "nonexistent", "args": {}, "id": "1", "type": "tool_call"}
],
)
],
config=_create_config_with_runtime(),
)
assert result[0].status == "error"
assert result[0].tool_call_id == "1"
assert (
result[0].content
== "Error: nonexistent is not a valid tool, try one of [registered_tool]."
)
def test_graceful_failure_even_when_handle_errors_disabled_sync() -> None:
"""Test that unregistered tool validation returns error even with handle_tool_errors=False."""
def passthrough_hook(
request: ToolCallRequest,
execute: Callable[[ToolCallRequest], ToolMessage | Command],
) -> ToolMessage | Command:
return execute(request)
node = ToolNode(
[registered_tool],
wrap_tool_call=passthrough_hook,
handle_tool_errors=False,
)
result = node.invoke(
[
AIMessage(
"",
tool_calls=[
{"name": "missing", "args": {}, "id": "1", "type": "tool_call"}
],
)
],
config=_create_config_with_runtime(),
)
assert result[0].status == "error"
assert (
result[0].content
== "Error: missing is not a valid tool, try one of [registered_tool]."
)
async def test_graceful_failure_when_hook_does_not_override_unregistered_tool_async() -> (
None
):
"""Test graceful failure when async hook doesn't override unregistered tool."""
async def passthrough_hook(
request: ToolCallRequest,
execute: Callable[[ToolCallRequest], Awaitable[ToolMessage | Command]],
) -> ToolMessage | Command:
return await execute(request)
node = ToolNode(
[registered_tool],
awrap_tool_call=passthrough_hook,
handle_tool_errors=True,
)
result = await node.ainvoke(
[
AIMessage(
"",
tool_calls=[
{"name": "unknown", "args": {}, "id": "1", "type": "tool_call"}
],
)
],
config=_create_config_with_runtime(),
)
assert result[0].status == "error"
assert result[0].tool_call_id == "1"
assert (
result[0].content
== "Error: unknown is not a valid tool, try one of [registered_tool]."
)
async def test_graceful_failure_even_when_handle_errors_disabled_async() -> None:
"""Test that async unregistered tool validation returns error even with handle_tool_errors=False."""
async def passthrough_hook(
request: ToolCallRequest,
execute: Callable[[ToolCallRequest], Awaitable[ToolMessage | Command]],
) -> ToolMessage | Command:
return await execute(request)
node = ToolNode(
[registered_tool],
awrap_tool_call=passthrough_hook,
handle_tool_errors=False,
)
result = await node.ainvoke(
[
AIMessage(
"",
tool_calls=[
{"name": "missing", "args": {}, "id": "1", "type": "tool_call"}
],
)
],
config=_create_config_with_runtime(),
)
assert result[0].status == "error"
assert (
result[0].content
== "Error: missing is not a valid tool, try one of [registered_tool]."
)
+2 -2
View File
@@ -268,7 +268,7 @@ wheels = [
[[package]]
name = "langgraph"
version = "1.0.6"
version = "1.0.7"
source = { editable = "../langgraph" }
dependencies = [
{ name = "langchain-core" },
@@ -489,7 +489,7 @@ test = [
[[package]]
name = "langgraph-prebuilt"
version = "1.0.6"
version = "1.0.7"
source = { editable = "." }
dependencies = [
{ name = "langchain-core" },