LangChain's June patch cadence has a small story buried in the version numbers: a yanked release, a four-minute gap, and two packages on different minor tracks that are supposed to look mismatched.
1.3.5 was yanked: what came after and why
On June 18, 2026, the LangChain team shipped two coordinated patch releases: langchain-core 1.4.8 and langchain 1.3.10. PyPI marks both as the latest on their lines . These are bug-and-performance patches under the 1.0 stability contract, with no API breaks and no migration required. The upgrade is low-risk but worth doing deliberately.
GitHub's release feed shows langchain-core==1.4.8 cut at 19:39 UTC and langchain==1.3.10 at 19:43 UTC, with core landing about four minutes first. That gap reflects how the monorepo sequences releases across the stack .
langchain 1.3.5, published June 10, was later yanked from PyPI over a compatibility regression . What yanking does in practice:
- Locked environments keep running it. An existing pinned install on 1.3.5 keeps working quietly; nothing breaks on its own.
- Fresh installs refuse it by default. A bare
pip install langchainskips yanked versions unless you request that exact string. - Anyone pinned to 1.3.5 should repin forward to 1.3.10 to clear the regression.
One detail trips people up: the two packages carry different minor numbers, 1.3 versus 1.4, by design rather than by mistake. LangChain's policy classifies patch releases as bug fixes, security updates, and performance work with no API changes, and the monorepo versions langchain and langchain-core on interlocking tracks . The gap is intentional.
The cost attribution hole in v3 events

The headline fix in langchain-core 1.4.8 is observability: the v3 streaming path now preserves input_token_details and output_token_details in usage metadata for stream_events and astream_events . Before the patch, both fields were silently dropped in v3 events, even though v2 events and astream aggregation preserved them correctly . If you adopted v3 for agent streaming, your token telemetry was quietly incomplete.
Why that field matters comes down to how providers count cached tokens. Anthropic and others fold cache reads into the top-level input_tokens figure and break the cached portion out under input_token_details . Drop that detail and you lose the only signal that separates fresh input from cache-read input. For any cached-prompt workload on v3 events, cost attribution was wrong: not by a rounding error, but by whatever fraction of your prompt was being served from cache.
The same gap affected reasoning tokens. output_token_details carries the reasoning-token breakdown, so any agent using extended thinking with v3 event observability had the same blind spot . Cache-creation, cache-read, and reasoning tokens all rolled up into opaque totals.
The maintainers verified the fix against a live claude-sonnet-4-6 cached-prompt call, confirming the detail fields survive the v3 path end to end . As the release notes put it, the change restores the per-call breakdown that v3 events had been discarding, a one-line summary that maps to what shows up in your traces.
The practical move before and after upgrading:
- Pull a LangSmith trace from a cached-prompt run on your current build and check whether
input_token_detailsis populated. If it is empty under v3, your cost dashboards have been undercounting cache reads. - Compare the same trace after moving to
langchain-core1.4.8 to quantify how far off your estimates were. - Re-baseline any extended-thinking agent that drives cost or budget logic off reasoning-token counts surfaced through v3 events.
No exception was raised and no warning appeared during this breakage. Your code kept running; the numbers were just wrong. Teams that switched to v3 for richer streaming, per the 1.3.x line that added version="v3" support, are the ones most affected .
23 schema conversions, 33 ms each, now memoized
The second core fix in langchain-core 1.4.8 is a pure performance optimization: BaseTool.tool_call_schema now memoizes its subset model and caches the result of model_json_schema. A warm conversion pass over roughly 23 tools dropped from about 33 ms to about 0.33 ms, roughly 100× off the schema-conversion path .
Before this patch, the same schema was recomputed from scratch on every iteration. Agentic loops that repeatedly bind tools or count tokens across a large toolset paid that conversion tax each pass. That is the workload the optimization targets . If your agent re-binds 20-plus tools per step, the overhead compounds across a long run.
| Path | Before 1.4.8 | After 1.4.8 | Delta |
|---|---|---|---|
| Warm pass, ~23 tool schemas | ~33 ms | ~0.33 ms | ~100× |
| Per-iteration recompute | Every loop | Memoized / cached | Eliminated |
Cache invalidation fires correctly when name, description, or args_schema is reassigned on a tool instance, so a tool you reconfigure at runtime still gets a fresh schema. Pickling safeguards were also added to keep tool instances serializable, which matters if you ship tools across process boundaries or persist agent state .
There is one caveat worth auditing before you upgrade. Mutating the returned subset class, or the dict produced by model_json_schema, is explicitly unsupported. Those objects are now shared, and review comments on the PR flagged cache-poisoning risk if downstream code edits them in place . Check for code that does this:
- Reads
tool.tool_call_schemaand then patches fields on the returned class. - Calls
model_json_schema()and edits the returned dict (adding descriptions, stripping keys) before passing it to a provider. - Relies on each access returning a fresh, independent object. That assumption no longer holds.
If any of those patterns exist, copy the object before mutating, or move the transformation upstream of the cached call. Otherwise this is a free speedup: no API change, no migration, just fewer milliseconds per agent step.
Silent misfires in the langchain layer

The top-level langchain package shipped 1.3.10 the same day, four minutes after core, and its two user-facing fixes share a theme: code that ran without error but quietly did the wrong thing . No exception was raised, no warning appeared. You would only catch it by inspecting traces.
The first fix is in SummarizationMiddleware. _create_summary and _acreate_summary now call get_buffer_string with XML formatting, so URL-backed multimodal blocks survive into the summarizer prompt instead of dumping raw message metadata . If your agent summarizes long conversations that carry image, audio, or video URLs, the previous behavior was feeding the summarizer serialized metadata rather than the referenced content. The summarizer was receiving mangled metadata instead of actual text.
The second fix is subtler and easy to miss. create_agent with response_format was falling back from native structured-output ProviderStrategy to ToolStrategy for dated OpenAI snapshots like gpt-5.2-2025-12-01 and gpt-5.4-2026-03-05, because the detection regex rejected the YYYY-MM-DD suffix . The PR adds an optional date group for gpt-5.2 and gpt-5.4 while keeping -pro variants blocked . If you pinned a dated snapshot for reproducibility and used structured output, you were silently routed to the less capable execution path the whole time.
As the LangChain team frames its release tiers, "patch releases are for bug fixes, security updates, documentation improvements, and performance optimizations, without API changes" (source: LangChain release policy, 2026). Both of these qualify: no migration, no signature change, just the correct behavior restored.
The release also lists dependency bumps in the langchain_v1 lock area. Before treating any as urgent, confirm whether it is a direct runtime dependency in your stack:
- cryptography 46.0.7 → 48.0.1
- aiohttp 3.14.0 → 3.14.1
- PyJWT 2.12.0 → 2.13.0
These read as monorepo lock maintenance, not a security mandate. A cryptography jump of two major versions is worth a glance if you depend on it directly, but check your own resolved tree rather than assuming urgency from the release notes alone.
How to pin both packages (and what to smoke-test)

Upgrade both packages on purpose. Run pip install -U 'langchain==1.3.10' 'langchain-core==1.4.8' , or regenerate your uv/poetry/pip-tools lock and confirm the resolver lands langchain-protocol at >=0.0.17 and langgraph at >=1.2.5 . The lockfile is what matters, not the install command you remember running.
The trap: langchain 1.3.10 only floors core at >=1.4.7,<2.0.0, not at 1.4.8 specifically . A locked environment already sitting on langchain-core 1.4.7 still satisfies langchain 1.3.10, so bumping the top-level package alone can leave you on 1.4.7 (without the token-detail and schema-cache fixes) unless you pin core explicitly or regenerate the lock.
Python 3.10 is now a hard floor: langchain-core 1.4.8 removed older compatibility shims . Any runner still on 3.9 needs to move before this upgrade resolves.
One more audit item if you call serialization helpers directly: 1.4.8 moved its tests to explicit deserialization allowlists such as allowed_objects='core' . If your own code calls load/loads, expect to pass the same argument rather than relying on a permissive default.
Scope your regression run to the four paths this patch actually touches:
| Smoke-test target | What to check |
|---|---|
v3 astream_events + LangSmith cost traces | Confirm input_token_details / output_token_details (cache-read, reasoning) reappear in usage metadata. |
| Summarization middleware | Summarize a conversation carrying URL-backed image/audio/video blocks; verify they survive into the summarizer prompt. |
create_agent structured output | Use dated snapshots like gpt-5.2-2025-12-01 or gpt-5.4-2026-03-05 and confirm native ProviderStrategy, not a ToolStrategy fallback. |
| Large-toolset agents | Exercise the warm schema-cache path on agents that bind or token-count many tools per loop. |
If your code mutates the class returned by tool_call_schema or the dict from model_json_schema, test it deliberately. The memoization PR treats shared mutation as unsupported, and reviewers flagged possible cache-poisoning .
The 2.0 horizon: why the 1.0 contract holds
The 1.0 stability contract is the reason none of these June fixes broke your imports. LangChain shipped its first stable major, 1.0, in late 2025 alongside LangGraph 1.0, with an explicit commitment of no breaking changes until 2.0 . The rapid recent cadence (langchain-core 1.4.0 on May 11, langchain 1.3.0 on May 12, and the 1.3.10/1.4.8 pair on June 18) is that contract working as intended: substantive patches and minors with stable public APIs intact .
Part of what makes the guarantee holdable is a deliberately narrowed surface. In 1.0 the core langchain namespace was trimmed to primary abstractions, and the legacy pieces moved out:
- Legacy chains, retrievers, indexing, hub, and community re-exports now live in
langchain-classic. - The old
Agent/AgentExecutorconstructs are deprecated in favor of defining agents in LangChain, with middleware as the extension concept .
Smaller stable surface means fewer ways for a patch to break you, which is why the two most consequential changes since 1.3.0 landed as non-breaking fixes: the v3 stream_events observability restoration that returns input_token_details/output_token_details to usage metadata, and the tool_call_schema memoization that cut a warm pass over ~23 tools from ~33 ms to ~0.33 ms . Both matter for production agentic workloads, and neither touched your API.
Treat monthly minor increments on both tracks as the working baseline. Pin langchain and langchain-core deliberately, and watch the GitHub releases feed for the next bump rather than the docs changelog, which lags on patch detail.
Frequently asked questions
Do I need to upgrade both packages, or is bumping langchain to 1.3.10 enough?
Pin both explicitly. langchain 1.3.10 floors langchain-core at >=1.4.7, not >=1.4.8 , so bumping langchain alone can leave a locked environment sitting on core 1.4.7, without the v3 token-detail and schema-memoization fixes. Run pip install -U 'langchain==1.3.10' 'langchain-core==1.4.8', or regenerate your uv/poetry/pip-tools lock and confirm langchain-protocol resolves to >=0.0.17 and langgraph to >=1.2.5 .
Is the tool_call_schema memoization safe if my code mutates the returned schema objects?
No. The performance PR explicitly states that mutating the returned subset class or the dict from model_json_schema is unsupported, and review comments flagged possible cache-poisoning behavior . The optimization memoizes BaseTool.tool_call_schema's subset model and caches the JSON schema, adding cache invalidation only on reassignment of name, description, or args_schema. If your code touches these objects after retrieval, audit and test before upgrading.
My environment is pinned to langchain 1.3.5. Will it break immediately?
No immediate break. Yanked packages keep running in environments that already have them installed; pip simply won't install langchain 1.3.5 fresh once it is yanked . But the underlying compatibility regression that triggered the yank is real, so repin forward to 1.3.10 before your next fresh deploy or lock regeneration. Otherwise CI and new builds will fail to resolve the pin.
What if I'm still on v0.3 and considering skipping straight to 1.3.10?
These patches only land once you are on the v1 line, so complete the v1 migration first. That means migrating to the reduced langchain namespace, installing langchain-classic for legacy chains, retrievers, indexing, hub, and community re-exports, upgrading to Python 3.10+, and updating to message content_blocks. All of those are required v1 breaking-change steps . Jumping a pin from 0.3 to 1.3.10 without that work will surface import and API errors, not the patch-level fixes.
Are the cryptography and PyJWT bumps security patches I should prioritize separately?
Maybe. It depends on your dependency graph. The 1.3.10 release lists cryptography 46.0.7→48.0.1, aiohttp 3.14.0→3.14.1, and PyJWT 2.12.0→2.13.0 in the langchain_v1 area, which read as monorepo lock and dependency maintenance rather than declared production runtime pins . Whether they are security-critical for you turns on whether each is a direct runtime dependency in your stack, so check your own dependency tree instead of assuming the bumps are urgent.