Codex integration tests need to be skipped in CI whenever VCR is not in
playback mode, but the setup-time skip ran too late: `pytest-recording`
could already try to open a cassette and hit the missing on-disk OAuth
token first. Moving the skip to collection time marks the matching Codex
tests before cassette setup while keeping the existing VCR-token fake
for playback runs.
## Changes
- Add a `pytest_collection_modifyitems` hook that marks Codex chat-model
integration tests as skipped in CI unless VCR is replaying existing
cassettes.
- Scope collection-time matching to the local chat-model
integration-test directory so same-named modules collected elsewhere are
not skipped accidentally.
- Keep the OAuth-token fake path active for VCR playback by preserving
`_fake_codex_oauth_token` behavior when `record_mode` is `none`.
Clarifies why the async callable API-key integration test intentionally
creates a failed `ChatOpenAI` run in scheduled LangSmith traces. The
sync invocation is expected to fail because async API-key callables are
only valid for async model methods.
This clarifies that the strict Responses API schema in
`test_parsed_strict` is intentionally made invalid before asserting
OpenAI raises `BadRequestError`.
The scheduled integration traces for this test can otherwise look like
real product regressions because OpenAI reports that `punchline` is
missing from `required`. The comment now makes the test intent explicit
for future readers and issue triage tooling.
The raw OpenAI embeddings equivalence checks were comparing live
responses from two requests, which made them vulnerable to upstream
numerical drift even when LangChain behavior had not changed. Recording
those interactions keeps the regression coverage while preventing
scheduled integration runs from failing due to backend variance.
- Mark the Codex OAuth model/token helper classes private with leading
underscores
- Remove `_ChatOpenAICodex` from package-level public exports
- Keep a once-per-process runtime warning that use is
experimental/unofficial and must comply with applicable OpenAI account,
workspace, plan, terms, policies, rate limits, and safeguards
[Docs](https://github.com/langchain-ai/docs/pull/4115)
Adds a new `ChatOpenAICodex` chat model and a small `chatgpt_oauth`
module so users can authenticate with their ChatGPT subscription (OAuth
2.0 Authorization Code Flow with PKCE) and route Responses-API requests
to the ChatGPT Codex backend at `https://chatgpt.com/backend-api/codex`.
Login and token persistence live behind a refresh-aware
`ChatGPTOAuthTokenProvider` protocol so they stay decoupled from model
invocation. The existing API-key `ChatOpenAI` behavior is untouched. By
default the file-backed provider writes to
`~/.langchain/chatgpt-auth.json` to avoid stomping on Codex CLI / VS
Code sessions at `~/.codex/auth.json`. No new required dependencies are
introduced (uses stdlib + `httpx`).
```python
from langchain_openai import ChatOpenAICodex
from langchain_openai.chatgpt_oauth import login_chatgpt
login_chatgpt()
model = ChatOpenAICodex(model="gpt-5.5")
response = model.invoke("hello")
```
_Opened collaboratively by Mason Daugherty and open-swe._
---------
Co-authored-by: open-swe[bot] <open-swe@users.noreply.github.com>
Co-authored-by: Mason Daugherty <61371264+mdrxy@users.noreply.github.com>
Co-authored-by: Mason Daugherty <github@mdrxy.com>
Co-authored-by: Mason Daugherty <mason@langchain.dev>
Standardizes inline code markup in Python docstrings and comments by
replacing Sphinx-style double backticks with single-backtick Markdown.
The cleanup keeps existing code fences intact while aligning inline
references with the repo's docstring convention.
## Changes
- Converted inline code references in core prompt-loading docs and
LangSmith tracer comments, including `..`, `allow_dangerous_paths`, and
inheritable metadata keys.
- Normalized agent-related docstrings and comments around
`wrap_model_call`, `ExtendedModelResponse`, `Command`,
`create_structured_chat_agent`, and `DockerExecutionPolicy`.
- Updated partner package docstrings for inline references such as
`json_schema`, `ToolCall`, `apply_patch_call_output`, OpenRouter content
block keys, and Perplexity tool-call serialization.
- Cleaned test and helper docstrings that referenced command separators,
fake `resource` modules, stream event names, and xdist rate-limit
environment variables.
Image token counting integration coverage is pinned back to `gpt-4o`,
whose usage metadata matches the local vision token estimator. A recent
model refresh moved these checks to `gpt-4.1-mini`, which reports
different live image token usage and broke the exact equality
assertions.
Provider-native structured output fallback detection now uses bounded
model-name patterns instead of broad substring checks, reducing false
positives for unrelated model IDs. The model examples and test fixtures
across OpenAI/OpenRouter-facing code were refreshed around current
OpenAI model families while preserving shipped defaults.
## Changes
- Tightened `FALLBACK_MODELS_WITH_STRUCTURED_OUTPUT` from loose string
fragments to regex patterns, with `_supports_provider_strategy` matching
full model-name segments instead of arbitrary substrings.
- Expanded structured-output fallback coverage for newer OpenAI,
Anthropic, and xAI/Grok model families, including `gpt-5.x`, newer
Claude 4/5-style names, and `grok-build`.
- Reused `_attempt_infer_model_provider` in provider tool search routing
so `_provider_from_model_name` follows the same provider inference
behavior as `init_chat_model`.
- Suppressed irrelevant provider-inference deprecation warnings during
provider tool search registry lookup.
- Refreshed OpenAI, Azure OpenAI, OpenRouter, core metadata, and example
model references from older fixtures like `gpt-4`, `gpt-4o`, `o1`, and
`o4-mini` to current test/profile models such as `gpt-5.5`,
`gpt-5-nano`, and `gpt-4.1-mini`.
- Removed outdated OpenAI test assumptions around legacy `o1` behavior
and narrowed legacy structured-output checks to explicitly legacy model
names.
Two unrelated nightly-CI failures rooted in upstream API drift. OpenAI
retired `gpt-4o-audio-preview` (now 404) and Azure embedding deployments
running `text-embedding-3-*` with truncated `dimensions` no longer
return unit-norm vectors.
CVE-2025-71176 (medium severity)
All are dev-only (test dependency group) — no impact on published
packages.
### Why syrupy was also bumped
syrupy 4.x (`<5.0.0`) constrains pytest to `<9.0.0`, blocking the CVE
fix. Widening to `<6.0.0` allows syrupy 5.x which supports pytest 9.x.
Fix broken VCR cassette playback in `langchain-openai` integration tests
and add a CI job to prevent regressions. Two independent bugs made all
VCR-backed tests fail: `before_record_request` redacts URIs to
`**REDACTED**` but `match_on` still included `uri` (so playback never
matched), and a typo-fix commit (`c9f51aef85`) changed test input
strings without re-recording cassettes (so `json_body` matching also
failed).
During an automated code review of .github/scripts/get_min_versions.py,
the following issue was identified. Set a timeout on get min versions
HTTP calls. Network calls without a timeout can hang a worker
indefinitely. I kept the patch small and re-ran syntax checks after
applying it.
Issues with combining flex and nano
```shell
FAILED tests/integration_tests/chat_models/test_base.py::test_openai_invoke - openai.InternalServerError: Error code: 500 - {'error': {'message': 'The server had an error while processing your request. Sorry about that!', 'type': 'server_error', 'param': None, 'code': None}}
FAILED tests/integration_tests/chat_models/test_base.py::test_stream - openai.InternalServerError: Error code: 500 - {'error': {'message': 'The server had an error processing your request. Sorry about that! You can retry your request, or contact us through our help center at help.openai.com if you keep seeing this error. (Please include the request ID req_e726769d95994fd4bccbe55680a35f59 in your email.)', 'type': 'server_error', 'param': None, 'code': None}}
FAILED tests/integration_tests/chat_models/test_base.py::test_flex_usage_responses[False] - openai.InternalServerError: Error code: 500 - {'error': {'message': 'An error occurred while processing your request. You can retry your request, or contact us through our help center at help.openai.com if the error persists. Please include the request ID req_935316418319494d8682e4adcd67ab47 in your message.', 'type': 'server_error', 'param': None, 'code': 'server_error'}}
FAILED tests/integration_tests/chat_models/test_base.py::test_flex_usage_responses[True] - openai.APIError: An error occurred while processing your request. You can retry your request, or contact us through our help center at help.openai.com if the error persists. Please include the request ID req_f3c164d0d1f045a5a0f5965ab5c253bf in your message.
```
Removed:
- `libs/core/langchain_core/chat_history.py`: `add_user_message` and
`add_ai_message` in favor of `add_messages` and `aadd_messages`
- `libs/core/langchain_core/language_models/base.py`: `predict`,
`predict_messages`, and async versions in favor of `invoke`. removed
`_all_required_field_names` since it was a wrapper on
`get_pydantic_field_names`
- `libs/core/langchain_core/language_models/chat_models.py`:
`callback_manager` param in favor of `callbacks`. `__call__` and
`call_as_llm` method in favor of `invoke`
- `libs/core/langchain_core/language_models/llms.py`: `callback_manager`
param in favor of `callbacks`. `__call__`, `predict`, `apredict`, and
`apredict_messages` methods in favor of `invoke`
- `libs/core/langchain_core/prompts/chat.py`: `from_role_strings` and
`from_strings` in favor of `from_messages`
- `libs/core/langchain_core/prompts/pipeline.py`: removed
`PipelinePromptTemplate`
- `libs/core/langchain_core/prompts/prompt.py`: `input_variables` param
on `from_file` as it wasn't used
- `libs/core/langchain_core/tools/base.py`: `callback_manager` param in
favor of `callbacks`
- `libs/core/langchain_core/tracers/context.py`: `tracing_enabled` in
favor of `tracing_enabled_v2`
- `libs/core/langchain_core/tracers/langchain_v1.py`: entire module
- `libs/core/langchain_core/utils/loading.py`: entire module,
`try_load_from_hub`
- `libs/core/langchain_core/vectorstores/in_memory.py`: `upsert` in
favor of `add_documents`
- `libs/standard-tests/langchain_tests/integration_tests/chat_models.py`
and `libs/standard-tests/langchain_tests/unit_tests/chat_models.py`:
`tool_choice_value` as models should accept `tool_choice="any"`
- `langchain` will consequently no longer expose these items if it was
previously
---------
Co-authored-by: Mohammad Mohtashim <45242107+keenborder786@users.noreply.github.com>
Co-authored-by: Caspar Broekhuizen <caspar@langchain.dev>
Co-authored-by: ccurme <chester.curme@gmail.com>
Co-authored-by: Christophe Bornet <cbornet@hotmail.com>
Co-authored-by: Eugene Yurtsev <eyurtsev@gmail.com>
Co-authored-by: Sadra Barikbin <sadraqazvin1@yahoo.com>
Co-authored-by: Vadym Barda <vadim.barda@gmail.com>