# langchain — corrections from the Stale Priors Index

<!--
     Stale Priors Index · Unattended Works · https://stalepriors.com/rules/langchain.md

     The Stale Priors Index, Unattended Works (https://stalepriors.com/rules/langchain.md), CC BY 4.0. Retrieved 2026-09-06.
     Licence: https://creativecommons.org/licenses/by/4.0/  ·  SPDX-License-Identifier: CC-BY-4.0
     Quotations from third-party changelogs remain their authors'; nothing here grants any
     right in the libraries described. Full map: https://stalepriors.com/data/LICENSE

     Changed since the 2026-09-06 sweep: none of the 38 entries below.

     GENERATED FILE — DO NOT EDIT BY HAND. Your edit will be destroyed by the next build.
     Rebuild:  node tools/build-rules.mjs
     Source:   data/langchain/facts.json
-->

For projects on **langchain>=1,<2 (Python)**. 38 corrections, 38 of them dated to the release that changed the behaviour; every entry links the primary source it was verified against. Latest langchain: 1.4.0, verified 2026-09-06. Do **not** use this if you are pinned to langchain 0.3 or earlier.

**This is the statements only** — no reproduced model failures, no code, no evidence. The full pack has all three: https://stalepriors.com/corrections/langchain.md

**Two dates, and this file needs only one.** The entries below were last checked against their primary sources on 2026-09-06. None of the 38 has had its own text change since that sweep.

**What was measured, and what this file is not.** The 2 benchmark runs so far measured the **prisma** and **zod** correction packs — not langchain's, and not this shorter file. There is no measurement of what either does for langchain. Every cell: https://stalepriors.com/benchmark

The corrections below are 27,352 characters. Read that as a cost: a rules file is added to requests, so it is a decision to make rather than a default to accept.

## Breaks the build, or throws at runtime

### `agent custom state`

**Stricter in langchain 1.0.0** (2025-10-17).

Custom agent state must be a `TypedDict`. The Pydantic state classes are gone: `AgentStatePydantic` and `AgentStateWithStructuredResponsePydantic` have no replacement beyond `langchain.agents.AgentState`.

*The stale belief:* That agent state can be declared as a Pydantic model.

*Verified against:* [LangChain v1 migration guide — Custom state](https://docs.langchain.com/oss/python/migrate/langchain-v1)

### `AIMessage(example=...)`

**Removed in langchain 1.0.0** (2025-10-17).

The `example` parameter was removed from `AIMessage`. Put that metadata in `additional_kwargs`.

*The stale belief:* That `AIMessage(content=..., example=True)` is valid.

*Verified against:* [LangChain v1 migration guide — example parameter removed from AIMessage](https://docs.langchain.com/oss/python/migrate/langchain-v1)

### `create_agent(pre_model_hook=...) / post_model_hook`

**Removed in langchain 1.0.0** (2025-10-17).

`pre_model_hook` and `post_model_hook` are not `create_agent` parameters. Their replacement is middleware: a `before_model` / `after_model` hook, or `wrap_model_call` when you want to change only what is sent to the model without editing stored state.

*The stale belief:* That message trimming or output validation is wired in with `pre_model_hook=` / `post_model_hook=` on the agent factory.

*Verified against:* [LangChain v1 migration guide — Pre-model hook](https://docs.langchain.com/oss/python/migrate/langchain-v1)

### `create_agent(response_format=...)`

**Removed in langchain 1.0.0** (2025-10-17).

Prompted structured output — passing a `(instruction_string, Schema)` tuple to `response_format` — was removed. A bare schema is still accepted, and the framework picks a strategy; to choose explicitly, pass `ToolStrategy(Schema)` (artificial tool call, works on any tool-calling model) or `ProviderStrategy(Schema)` (provider-native constrained decoding). The result lands in `result["structured_response"]`.

*The stale belief:* That you can steer structured output by handing `response_format` a prompt alongside the schema.

*Verified against:* [LangChain v1 migration guide — Prompted output removed](https://docs.langchain.com/oss/python/migrate/langchain-v1)

### `create_agent(system_prompt=...)`

**Renamed in langchain 1.0.0** (2025-10-17).

The static instruction parameter is `system_prompt`. `prompt=` was the `create_react_agent` name and is not accepted by `create_agent` — passing it raises `TypeError: unexpected keyword argument`.

*The stale belief:* That the agent factory takes `prompt=`.

*Verified against:* [LangChain v1 migration guide — Static prompt rename](https://docs.langchain.com/oss/python/migrate/langchain-v1)

### `langchain text splitters`

**Removed in langchain 1.0.0** (2025-10-17).

Text splitters are not part of the v1 `langchain` namespace. They live in their own distribution, `langchain-text-splitters`, imported as `langchain_text_splitters`.

*The stale belief:* That `from langchain.text_splitter import RecursiveCharacterTextSplitter` works.

*Verified against:* [What's new in LangChain v1 — Namespace](https://docs.langchain.com/oss/python/releases/langchain-v1)

### `langchain-classic`

**New requirement in langchain 1.0.0** (2025-10-17).

`langchain-classic` is a separate distribution. `pip install langchain` does not bring it in, so every legacy import above fails with `ModuleNotFoundError: No module named 'langchain_classic'` until it is installed. Any migration advice that only rewrites the import path is incomplete without the install line.

*The stale belief:* That legacy symbols are still reachable from whatever is installed alongside `langchain`.

*Verified against:* [LangChain v1 migration guide — Install with](https://docs.langchain.com/oss/python/migrate/langchain-v1)

### `langchain.agents.initialize_agent / AgentExecutor`

**Removed in langchain 1.0.0** (2025-10-17).

`initialize_agent`, `AgentExecutor` and `AgentType` are gone from `langchain.agents`, which now exports `create_agent` and `AgentState`. The old agent machinery is in `langchain-classic`.

*The stale belief:* That agents are built with `initialize_agent(tools, llm, agent=AgentType.OPENAI_FUNCTIONS)` or by wrapping a runnable in an `AgentExecutor`.

*Verified against:* [API reference — langchain_classic.agents.initialize.initialize_agent](https://reference.langchain.com/python/langchain-classic/agents/initialize/initialize_agent)

### `langchain.chains (LLMChain, ConversationChain, RetrievalQA)`

**Removed in langchain 1.0.0** (2025-10-17).

Legacy chains are not in the `langchain` package. They moved to `langchain-classic`, which `pip install langchain` does not install, so `from langchain.chains import LLMChain` is an `ImportError` on a fresh v1 environment. Either install `langchain-classic` and import from `langchain_classic.chains`, or write the pipeline directly — a prompt piped into a model, or a retrieve-then-answer function.

*The stale belief:* That `LLMChain`, `ConversationChain`, `RetrievalQA` and friends live in `langchain.chains`.

*Verified against:* [LangChain v1 migration guide — langchain-classic](https://docs.langchain.com/oss/python/migrate/langchain-v1)

### `langchain.hub`

**Removed in langchain 1.0.0** (2025-10-17).

`from langchain import hub` no longer works. The hub module moved to `langchain-classic`; the prompt registry is also reachable directly from the LangSmith SDK, which is the path the current docs use.

*The stale belief:* That the hosted prompt registry is reached with `from langchain import hub; hub.pull("owner/name")`, optionally after `pip install langchainhub`.

*Verified against:* [LangChain v1 migration guide — update your imports](https://docs.langchain.com/oss/python/migrate/langchain-v1)

### `langchain.memory (ConversationBufferMemory)`

**Removed in langchain 1.0.0** (2025-10-17).

The memory classes are not in `langchain`. Conversation memory in v1 is a LangGraph checkpointer keyed by `thread_id`, not an object hung off a chain; the old classes remain available only in `langchain-classic`.

*The stale belief:* That you attach `memory=ConversationBufferMemory(...)` to a chain.

*Verified against:* [API reference — langchain_classic.memory.buffer.ConversationBufferMemory](https://reference.langchain.com/python/langchain-classic/memory/buffer/ConversationBufferMemory)

### `langchain.retrievers / langchain.indexes`

**Removed in langchain 1.0.0** (2025-10-17).

Retrievers and the indexing API left the `langchain` namespace for `langchain-classic`. A vector store's own `.as_retriever()` is unaffected and is the normal way to retrieve in v1.

*The stale belief:* That `from langchain.retrievers import ...` and `from langchain.indexes import ...` resolve.

*Verified against:* [LangChain v1 migration guide — langchain-classic](https://docs.langchain.com/oss/python/migrate/langchain-v1)

### `pre-bound models`

**Removed in langchain 1.0.0** (2025-10-17).

`create_agent` does not accept a model that already has tools bound to it. Pass the model and the tools separately, and vary the model per call with middleware (`wrap_model_call` + `request.override(model=...)`) if you need dynamic selection.

*The stale belief:* That you can hand the agent factory `model.bind_tools([...])`.

*Verified against:* [LangChain v1 migration guide — Model](https://docs.langchain.com/oss/python/migrate/langchain-v1)

## Runs, but is silently wrong

### `tool extras`

**Added in langchain 1.2.0** (2025-12-15).

Provider-specific tool parameters go in `extras`, a flat `dict[str, Any]` on the tool — `@tool(extras={...})` or the `extras` attribute on a tool object. The keys are the provider's own field names (`defer_loading`, `cache_control`, `input_examples`), NOT a provider name wrapping them. There is no `provider_specific` attribute, and `metadata=` is a different field that goes to callback handlers and never reaches the provider payload.

*The stale belief:* That provider-specific tool configuration has no first-class home on a tool, so it must be smuggled in by binding raw provider-format tool dicts, or hung on whichever tool field looks closest.

*Verified against:* [LangChain changelog — langchain v1.2.0](https://docs.langchain.com/oss/python/releases/changelog)

### `create_agent recursion limit`

**Behaviour changed in langchain 1.1.0** (2025-11-24).

Since 1.1.0, `create_agent` stamps its own recursion limit onto the graph it compiles, so an agent built by the factory does not run under LangGraph's default. 1.1.0 ended `create_agent` with `.with_config({"recursion_limit": 10_000})`; the shipped release sets `{"recursion_limit": 9_999}`. The number to know is that it is four figures, not 25. A `GraphRecursionError` from a factory-built agent therefore means thousands of supersteps have actually run — a genuine non-terminating loop — and raising the ceiling is not the fix.

*The stale belief:* That a `create_agent` agent inherits LangGraph's 25-superstep default (about twelve tool rounds), so a step-limit error is normal for a long tool loop and the fix is `config={"recursion_limit": 100}`.

*Verified against:* [langchain 1.0.0 published wheel — langchain/agents/factory.py (no limit set)](https://files.pythonhosted.org/packages/c4/4d/2758a16ad01716c0fb3fe9ec205fd530eae4528b35a27ff44837c399e032/langchain-1.0.0-py3-none-any.whl)

### `ModelRetryMiddleware defaults`

**Added in langchain 1.1.0** (2025-11-24).

`ModelRetryMiddleware()` with no arguments does **not** re-raise when its retries run out. Its defaults are `max_retries=2` (three model calls in total) and `on_failure="continue"`, and `"continue"` means the middleware swallows the provider exception and returns a `ModelResponse` carrying a synthetic `AIMessage` whose text is `"Model call failed after N attempts with {ExcType}: {message}"`. The agent then proceeds as though the model had replied. Re-raising is opt-in: `on_failure="error"`. Every parameter is keyword-only; the rest of the defaults are `backoff_factor=2.0`, `initial_delay=1.0`, `max_delay=60.0`, `jitter=True` (±25%).

*The stale belief:* That a bounded-retry middleware re-raises the underlying provider exception once attempts are exhausted, so `agent.invoke(...)` fails loudly when the provider is down.

*Verified against:* [LangChain changelog — langchain v1.1.0](https://docs.langchain.com/oss/python/releases/changelog)

### `agent streaming node name`

**Renamed in langchain 1.0.0** (2025-10-17).

In a `create_agent` graph the model step is named `"model"`, not `"agent"`. Code that filters streamed events on `"agent"` imports, runs, and prints nothing — there is no error to tell you the filter never matched.

*The stale belief:* That the node emitting model output is called `"agent"`, as it was in `create_react_agent`.

*Verified against:* [LangChain v1 migration guide — Streaming node name rename](https://docs.langchain.com/oss/python/migrate/langchain-v1)

### `AgentMiddleware.modify_model_request`

**Removed in langchain 1.0.0** (2025-10-17).

`modify_model_request` is not a middleware hook in any released langchain 1.x. It existed in the 1.0 alpha line and was replaced before 1.0.0 GA by `wrap_model_call(request, handler)` — which receives the downstream handler and so can retry, short-circuit or post-process, none of which the old signature could do. The shipped hook set is `before_agent` / `before_model` / `wrap_model_call` / `after_model` / `after_agent` / `wrap_tool_call`, each with an `a`-prefixed async twin. Defining `modify_model_request` on an `AgentMiddleware` subclass raises nothing: the method is simply never called, and the middleware silently does nothing.

*The stale belief:* That middleware customises a model call by defining `modify_model_request(self, request, state, runtime)` and returning a modified request.

*Verified against:* [langchain 1.3.18 published wheel — langchain/agents/middleware/types.py (the shipped hook set)](https://files.pythonhosted.org/packages/f7/04/374f6014ed6959dbdab92962c2b09e4d0223ed6a82f65694870b46d2c13f/langchain-1.3.18-py3-none-any.whl)

### `ChatAnthropic(max_tokens=...)`

**Default changed in langchain 1.0.0** (2025-10-17).

`langchain-anthropic` no longer defaults `max_tokens` to a flat 1024; it picks a higher value based on the model. Advice built on the old number — "your answer is being cut off at 1024 tokens" — describes a default that no longer exists. If you actually relied on 1024, set it explicitly.

*The stale belief:* That `ChatAnthropic` caps output at 1024 tokens unless you override it.

*Verified against:* [LangChain v1 migration guide — Default max_tokens in langchain-anthropic](https://docs.langchain.com/oss/python/migrate/langchain-v1)

### `ChatOpenAI Responses API output format`

**Default changed in langchain 1.0.0** (2025-10-17).

Against the OpenAI Responses API, `langchain-openai` now stores response items in message `content` by default. Code that parsed the previous shape keeps running and reads the wrong structure; restore the old behaviour with `output_version="v0"` or `LC_OUTPUT_VERSION=v0`.

*The stale belief:* That the Responses API output lands in the pre-1.0 content shape.

*Verified against:* [LangChain v1 migration guide — Default message format for OpenAI responses API](https://docs.langchain.com/oss/python/migrate/langchain-v1)

## Deprecated, or a better API now exists

### `astream_events(version="v3") on a create_agent agent`

**Added in langchain 1.3.0** (2026-05-12).

`v2` is no longer the ceiling. From langchain 1.3.0 an agent built by `create_agent` accepts `version="v3"` in `stream_events` / `astream_events` - a content-block-centric protocol with typed, per-channel projections (`run.values`, `run.messages`, `run.lifecycle`, `run.subgraphs`), where `run.messages` yields one `ChatModelStream` per LLM call with sub-projections for text, reasoning, tool calls and usage. `v1` and `v2` are unchanged, so this is an addition rather than a migration. Scope matters: the claim is about the **agent**. The `langchain` package's own `_ConfigurableModel.astream_events` - what `init_chat_model(..., configurable_fields=...)` returns - still types `version: Literal["v1", "v2"] = "v2"` at 1.3.0 and 1.4.0.

*The stale belief:* That `v2` is the highest event-stream protocol version that exists, `v1` being the deprecated original - so a consumer that wants typed, per-channel event projections has to build them itself out of `v2` events.

*Verified against:* [LangChain changelog - langchain v1.3.0, May 12, 2026](https://docs.langchain.com/oss/python/releases/changelog)

### `create_agent(transformers=...)`

**Added in langchain 1.3.0** (2026-05-12).

`create_agent` takes a `transformers=` argument: a sequence of scope-aware `StreamTransformer` factories that are registered on the graph it compiles, in addition to the agent's own defaults. Each factory is invoked once per scope (`factory(scope)`), so a subgraph gets its own instance. The agent always registers `ToolCallTransformer` first and appends yours after it, so you keep the built-in behaviour instead of replacing it. This is the supported way to shape an agent's event stream at construction time: you do not have to abandon `create_agent` and hand-build the `StateGraph`, and you do not have to wrap `.astream()` on the consumer side.

*The stale belief:* That the compiled agent is a closed box: `create_agent` gives you no hook into the graph's stream machinery, so scope-aware transformation must be done either by dropping to a hand-built `StateGraph` or by wrapping `.astream()`/`.astream_events()` in your own generator and reconstructing scope from `subgraphs=True` namespace tuples.

*Verified against:* [langchain 1.3.0 published wheel - langchain/agents/factory.py](https://files.pythonhosted.org/packages/7b/6f/b9a9721c27fbb6d29a6a7cd89d6a41eeffc7c79b49b9a5cf5beb1d60952d/langchain-1.3.0-py3-none-any.whl)

### `model retry middleware`

**Added in langchain 1.1.0** (2025-11-24).

`ModelRetryMiddleware` ships in `langchain.agents.middleware` and retries the model call only, leaving tool calls alone. Its keyword-only parameters are `max_retries`, `retry_on`, `on_failure`, `backoff_factor`, `initial_delay`, `max_delay` and `jitter`. Do not hand-roll a `wrap_model_call` retry loop, and do not reach for the LCEL-era `Runnable.with_retry()` on the model — that predates this and wraps the model in a `RunnableRetry` before `create_agent` ever sees it.

*The stale belief:* That model-call retry has no first-class component, so it must be written as a custom `wrap_model_call` middleware, bolted on with `.with_retry()`, or wrapped in a `try/except` around the whole agent invocation.

*Verified against:* [LangChain changelog — langchain v1.1.0](https://docs.langchain.com/oss/python/releases/changelog)

### `ModelRequest attribute assignment`

**Deprecated in langchain 1.1.0** (2025-11-24).

Assigning to any attribute of a `ModelRequest` in middleware is deprecated: 1.1.0 added a `__setattr__` that emits a `DeprecationWarning` on every direct assignment and directs the caller to `request.override(...)`, which returns a new request rather than mutating the shared one. `override()` itself is not new — it existed at 1.0.0 — but until 1.1.0 in-place mutation was an equally supported idiom, and LangChain's own `ContextEditingMiddleware` used it.

*The stale belief:* That middleware modifies the request in place — `request.system_prompt = ...`, `request.messages.append(...)` — and returns it.

*Verified against:* [langchain 1.0.0 published wheel — middleware/types.py defines no __setattr__; context_editing.py mutates in place](https://files.pythonhosted.org/packages/c4/4d/2758a16ad01716c0fb3fe9ec205fd530eae4528b35a27ff44837c399e032/langchain-1.0.0-py3-none-any.whl)

### `ModelRequest.system_message`

**Renamed in langchain 1.1.0** (2025-11-24).

The system-instruction field on the `ModelRequest` object handed to middleware is `system_message: SystemMessage | None`. Until 1.1.0 it was `system_prompt: str | None`, a plain dataclass field. `system_prompt` survives as a read-only property returning `self.system_message.text`, and `override(system_prompt=...)` still converts, so pre-1.1 middleware keeps working — the shipped docstring labels the parameter "deprecated, converted to `SystemMessage`". Note the asymmetry that makes this easy to get wrong: `create_agent` itself still takes `system_prompt=`, so the public factory and the middleware-facing request now use different names for the same instruction.

*The stale belief:* That the middleware request carries the system instruction as a plain string field called `system_prompt`, the same name `create_agent` uses.

*Verified against:* [langchain 1.0.0 published wheel — langchain/agents/middleware/types.py (the pre-rename state)](https://files.pythonhosted.org/packages/c4/4d/2758a16ad01716c0fb3fe9ec205fd530eae4528b35a27ff44837c399e032/langchain-1.0.0-py3-none-any.whl)

### `SystemMessage as system_prompt`

**Added in langchain 1.1.0** (2025-11-24).

`create_agent`'s `system_prompt` accepts a `SystemMessage`, not only a `str`. That is how a fixed instruction carries provider metadata — content blocks with `cache_control` for prompt caching, for instance — without adding middleware and without hand-assembling the message list. The shipped signature is `system_prompt: str | SystemMessage | None`.

*The stale belief:* That `system_prompt` is string-only, so any provider metadata on the system block requires middleware, a custom message list, or binding the hint on the model instead.

*Verified against:* [LangChain changelog — langchain v1.1.0](https://docs.langchain.com/oss/python/releases/changelog)

### `bind_tools return type`

**Behaviour changed in langchain 1.0.0** (2025-10-17).

Chat model invocation is typed as returning `AIMessage`, not `BaseMessage`. Custom chat models implementing `bind_tools` should narrow their return signature to match.

*The stale belief:* That `bind_tools` is annotated `Runnable[LanguageModelInput, BaseMessage]`.

*Verified against:* [LangChain v1 migration guide — Updated return type for chat models](https://docs.langchain.com/oss/python/migrate/langchain-v1)

### `built-in agent middleware`

**Added in langchain 1.0.0** (2025-10-17).

Middleware is the extension point of `create_agent`: hooks `before_agent`, `before_model`, `wrap_model_call`, `wrap_tool_call`, `after_model`, `after_agent`, plus built-ins including `SummarizationMiddleware`, `HumanInTheLoopMiddleware`, `PIIMiddleware` and `TodoListMiddleware`. Hand-rolled graph surgery for summarisation, approval gates or redaction is the pre-1.0 answer.

*The stale belief:* That customising the agent loop means writing your own LangGraph `StateGraph`.

*Verified against:* [What's new in LangChain v1 — Middleware](https://docs.langchain.com/oss/python/releases/langchain-v1)

### `langchain.agents.create_agent`

**Renamed in langchain 1.0.0** (2025-10-17).

`create_agent` from `langchain.agents` is the way to build an agent. `langgraph.prebuilt.create_react_agent` is deprecated as of LangGraph v1 in its favour; it still imports and runs, so this is not an immediate breakage, but every other v1 change below assumes you are on `create_agent` — the parameter names, the middleware hooks and the streaming node name all differ between the two.

*The stale belief:* That `from langgraph.prebuilt import create_react_agent` is the current recommended way to build a tool-calling agent, which it was throughout the 0.2/0.3 era.

*Verified against:* [LangGraph v1 migration guide — Deprecations](https://docs.langchain.com/oss/python/migrate/langgraph-v1)

### `message.content_blocks`

**Added in langchain 1.0.0** (2025-10-17).

Messages carry a provider-agnostic `content_blocks` property: typed blocks for text, reasoning, tool calls and citations that read the same across Anthropic, OpenAI, AWS, Google GenAI and Ollama. `content` is unchanged, so nothing breaks; per-provider branching on `content` is simply no longer necessary. Standard blocks are not serialised into `content` unless you opt in with `output_version="v1"` or `LC_OUTPUT_VERSION=v1`.

*The stale belief:* That normalising reasoning/text/tool-call output requires hand-written per-provider branches.

*Verified against:* [What's new in LangChain v1 — Standard content blocks](https://docs.langchain.com/oss/python/releases/langchain-v1)

### `message.text`

**Deprecated in langchain 1.0.0** (2025-10-17).

`.text` is a property on message objects. The `.text()` method form still works but emits a warning and is scheduled for removal in v2.

*The stale belief:* That `response.text()` is the way to get a message's text.

*Verified against:* [LangChain v1 migration guide — Text property](https://docs.langchain.com/oss/python/migrate/langchain-v1)

### `multimodal message input`

**Added in langchain 1.0.0** (2025-10-17).

Multimodal input has a standard form: `HumanMessage(content_blocks=[{"type": "image", "url": ...}])`. The provider-native `{"type": "image_url", "image_url": {"url": ...}}` shape inside `content` is the old spelling.

*The stale belief:* That images must be passed in each provider's own content shape.

*Verified against:* [LangChain v1 migration guide — Create multimodal messages](https://docs.langchain.com/oss/python/migrate/langchain-v1)

### `run-scoped context (context= / context_schema=)`

**Added in langchain 1.0.0** (2025-10-17).

Static per-run data (a user id, a tenant) is passed with `context=` against a declared `context_schema`, and read inside a tool through a `ToolRuntime` parameter, which is stripped from the schema the model sees. The older `config={"configurable": {...}}` route still works and the migration guide says so explicitly — this is a better-idiom change, not a breakage.

*The stale belief:* That `config["configurable"]` is the only way to get request-scoped data into a tool.

*Verified against:* [LangChain v1 migration guide — Runtime context](https://docs.langchain.com/oss/python/migrate/langchain-v1)

## Wrong facts about the library

### `ProviderStrategy strict`

**Added in langchain 1.2.0** (2025-12-15).

`ProviderStrategy` takes a `strict` flag that asks the provider to enforce the schema server-side; when set, the strategy puts `"strict": True` into the JSON schema it sends. `ProviderStrategy(Schema)` alone is correct 1.0-era code and still routes to provider-native structured output — `strict=True` is the 1.2.0 addition on top of it.

*The stale belief:* That `ProviderStrategy` has no strictness control, so provider-side schema enforcement is all-or-nothing.

*Verified against:* [LangChain changelog — langchain v1.2.0](https://docs.langchain.com/oss/python/releases/changelog)

### `model profiles (.profile)`

**Added in langchain 1.1.0** (2025-11-21).

Chat models carry a `.profile` attribute — a `ModelProfile` TypedDict describing what the model supports, loaded from the provider package. Ask the model object instead of keeping a table of model names: `image_inputs`, `pdf_inputs`, `audio_inputs`, `max_input_tokens`, `structured_output` and `tool_calling` are among its keys. It is `total=False`, so read every key with `.get()`. `create_agent` reads it internally to decide whether a model can do provider-native structured output.

*The stale belief:* That model capabilities must be hard-coded in a name-to-capability table, discovered by trial, or fetched from an external catalogue over HTTP.

*Verified against:* [LangChain changelog — langchain v1.1.0](https://docs.langchain.com/oss/python/releases/changelog)

### `langchain package namespace`

**Removed in langchain 1.0.0** (2025-10-17).

The v1 `langchain` package exports five modules and nothing else: `langchain.agents`, `langchain.messages`, `langchain.tools`, `langchain.chat_models`, `langchain.embeddings`. Most are re-exports from `langchain-core`. Describing `langchain` as a kitchen sink of chains, retrievers and integrations describes 0.3.

*The stale belief:* That `langchain` is a large package containing chains, retrievers, memory, the hub and integration code.

*Verified against:* [What's new in LangChain v1 — Namespace](https://docs.langchain.com/oss/python/releases/langchain-v1)

### `langchain release timeline`

**New requirement in langchain 1.0.0** (2025-10-17).

langchain 1.0.0 was published to PyPI on 2025-10-17, together with langchain-core 1.0.0 and langchain-openai 1.0.0. 1.1.0 followed on 2025-11-24, 1.2.0 on 2025-12-15, 1.3.0 on 2026-05-12. The latest release as of 2026-08-31 is 1.3.18 (2026-08-27), with langchain-core at 1.6.1. The last 0.3 release before the 1.0 alpha line was 0.3.27 on 2025-07-24.

*The stale belief:* That 0.3.x is the current line, or that 1.0 is unreleased or upcoming.

*Verified against:* [PyPI JSON API — langchain release timestamps](https://pypi.org/pypi/langchain/json)

### `Python version requirement`

**New requirement in langchain 1.0.0** (2025-10-17).

All LangChain packages require Python 3.10 or higher. Python 3.9 support was dropped in v1.

*The stale belief:* That LangChain still supports Python 3.9.

*Verified against:* [LangChain v1 migration guide — Dropped Python 3.9 support](https://docs.langchain.com/oss/python/migrate/langchain-v1)

---

*The Stale Priors Index, Unattended Works (https://stalepriors.com/rules/langchain.md), CC BY 4.0. Retrieved 2026-09-06. Licence: <https://creativecommons.org/licenses/by/4.0/> (`SPDX-License-Identifier: CC-BY-4.0`).*
*Quoted changelog text belongs to its authors; nothing here grants any right in the libraries described.*
*Terms in full: <https://stalepriors.com/data/LICENSE>.*
