From ae1c9418b52eb0366118ccb564cf5b753bd1089b Mon Sep 17 00:00:00 2001 From: Mason Daugherty Date: Wed, 17 Jun 2026 16:29:08 -0400 Subject: [PATCH] fix(langchain): detect provider strategy for dated `gpt-5.2`/`gpt-5.4` snapshots (#38222) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Closes #38220 --- Users calling `create_agent(..., response_format=)` with an OpenAI model pinned to a dated snapshot (e.g. `gpt-5.4-2026-03-05`) were silently downgraded from native structured output (`ProviderStrategy`) to tool-calling (`ToolStrategy`). This changes runtime behavior: extra tool-call traces, different token usage, and no provider-side schema enforcement. The cause is in `_supports_provider_strategy`'s fallback patterns: the `gpt-5.2` and `gpt-5.4` base patterns terminated with `($|[/:])`, which — unlike their sibling families — rejected a trailing `-`, so OpenAI's `-YYYY-MM-DD` dated-snapshot suffix matched none of the patterns. The base patterns were deliberately strict to keep `gpt-5.2-pro`/`gpt-5.4-pro` blocked, so rather than allowing any trailing `-` (which would re-admit those `-pro` variants) this change adds an optional dated-snapshot group `(-\d{4}-\d{2}-\d{2})?`. Dated snapshots now resolve to `ProviderStrategy` while `-pro` variants stay blocked. Made by [Open SWE](https://openswe.vercel.app/agents/c5ebcb29-8ce5-dda0-73f6-198e49f0c36c) Co-authored-by: open-swe[bot] --- libs/langchain_v1/langchain/agents/factory.py | 4 ++-- .../tests/unit_tests/agents/test_response_format.py | 2 ++ libs/langchain_v1/uv.lock | 8 ++++---- 3 files changed, 8 insertions(+), 6 deletions(-) diff --git a/libs/langchain_v1/langchain/agents/factory.py b/libs/langchain_v1/langchain/agents/factory.py index 795dad15a30..be891cfafd4 100644 --- a/libs/langchain_v1/langchain/agents/factory.py +++ b/libs/langchain_v1/langchain/agents/factory.py @@ -158,10 +158,10 @@ FALLBACK_MODELS_WITH_STRUCTURED_OUTPUT = [ r"(^|[/:.])gpt-4o($|[-/:])", r"(^|[/:.])gpt-5($|[-/:])", r"(^|[/:.])gpt-5\.1($|[-/:])", - r"(^|[/:.])gpt-5\.2($|[/:])", + r"(^|[/:.])gpt-5\.2(-\d{4}-\d{2}-\d{2})?($|[/:])", r"(^|[/:.])gpt-5\.2-(chat|codex)($|[-/:])", r"(^|[/:.])gpt-5\.3($|[-/:])", - r"(^|[/:.])gpt-5\.4($|[/:])", + r"(^|[/:.])gpt-5\.4(-\d{4}-\d{2}-\d{2})?($|[/:])", r"(^|[/:.])gpt-5\.4-(mini|nano)($|[-/:])", r"(^|[/:.])gpt-5\.5($|[-/:])", r"(^|[/:.])claude-(fable|mythos)-5(?:-\d{8})?(?:-v\d(?::\d)?)?($|[/:])", diff --git a/libs/langchain_v1/tests/unit_tests/agents/test_response_format.py b/libs/langchain_v1/tests/unit_tests/agents/test_response_format.py index f2c237f0cf6..05358887887 100644 --- a/libs/langchain_v1/tests/unit_tests/agents/test_response_format.py +++ b/libs/langchain_v1/tests/unit_tests/agents/test_response_format.py @@ -953,11 +953,13 @@ class TestSupportsProviderStrategy: "gpt-5.1", "gpt-5.1-codex", "gpt-5.2", + "gpt-5.2-2025-12-01", "gpt-5.2-chat-latest", "gpt-5.2-codex", "gpt-5.3", "gpt-5.3-codex-spark", "gpt-5.4", + "gpt-5.4-2026-03-05", "gpt-5.4-mini", "gpt-5.4-nano", "gpt-5.5-pro", diff --git a/libs/langchain_v1/uv.lock b/libs/langchain_v1/uv.lock index 6a657f1ef6c..10a2c2b992e 100644 --- a/libs/langchain_v1/uv.lock +++ b/libs/langchain_v1/uv.lock @@ -2276,7 +2276,7 @@ dependencies = [ [package.metadata] requires-dist = [ { name = "jsonpatch", specifier = ">=1.33.0,<2.0.0" }, - { name = "langchain-protocol", specifier = ">=0.0.14" }, + { name = "langchain-protocol", specifier = ">=0.0.17" }, { name = "langsmith", specifier = ">=0.3.45,<1.0.0" }, { name = "packaging", specifier = ">=23.2.0" }, { name = "pydantic", specifier = ">=2.7.4,<3.0.0" }, @@ -2505,14 +2505,14 @@ wheels = [ [[package]] name = "langchain-protocol" -version = "0.0.15" +version = "0.0.17" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "typing-extensions" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/4f/24/9777489d6fbbee64af0c8f96d4f840239c408cf694f3394672807dafc490/langchain_protocol-0.0.15.tar.gz", hash = "sha256:9ab2d11ee73944754f10e037e717098d3a6796f0e58afa9cadda6154e7655ade", size = 5862, upload-time = "2026-05-01T22:30:04.748Z" } +sdist = { url = "https://files.pythonhosted.org/packages/44/b3/4e2429876c7a35585618caa2b9f9089f7162a6b50562b614ad82ac11c17e/langchain_protocol-0.0.17.tar.gz", hash = "sha256:e7cbe58c205df4b4fd87dc6d5bb23f10e13b236d0e2e1b0b9d05bc2b648f3eea", size = 6026, upload-time = "2026-06-12T18:39:51.923Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/1d/7a/9c97a7b9cbe4c5dc6a44cdb1545450c28f0c8ce89b9c1f0ee7fbad896263/langchain_protocol-0.0.15-py3-none-any.whl", hash = "sha256:461eb794358f83d5e42635a5797799ffec7b4702314e34edf73ac21e75d3ef79", size = 6982, upload-time = "2026-05-01T22:30:03.877Z" }, + { url = "https://files.pythonhosted.org/packages/13/0a/a1bfe72c6ec856e99773bbd96c8086421e554b3693d0142b9ea009c6ac92/langchain_protocol-0.0.17-py3-none-any.whl", hash = "sha256:982a08fe152586ed10d4ff3d538c2e0b5766e5f307cdea325e10be3f2c17cae6", size = 7096, upload-time = "2026-06-12T18:39:50.973Z" }, ] [[package]]