Plumb an explicit resource-lifecycle contract through `BaseChatModel`, `RunnableWithFallbacks`, and the two largest partner integrations. Adds an opt-in `FallbackLatch` so `with_fallbacks(...)` can short-circuit the primary after a failure. Motivation: provider SDKs (`anthropic`, `openai`) back their clients with httpx connection pools that the SDKs only release best-effort from `__del__` — `asyncio.get_running_loop().create_task(self.aclose())` with a bare `except Exception: pass`. Long-lived workers that construct chat models per request (multi-tenant LangGraph deployments, agents-as-services) silently accumulate pools and leak memory + file descriptors. The fix today requires reaching into private attributes (`_async_client`, `root_async_client`, ...) on each provider. This PR makes teardown a first-class part of the chat-model API. ## langchain-core - `BaseChatModel.close()` / `aclose()` — default no-ops that subclasses override. `aclose()` dispatches to `close()` so async teardown works for sync-only subclasses. Adds `__enter__`/`__exit__`/`__aenter__`/ `__aexit__` so models can be used as context managers. - `RunnableWithFallbacks.close()` / `aclose()` — walks `runnable` and `fallbacks`, calling each one's lifecycle method. Per-runnable failures are suppressed so one bad close doesn't prevent the others from running. - `FallbackLatch` + `with_fallbacks(..., latch=...)` — opt-in circuit-breaker: once the primary raises a handled exception, latch trips and subsequent calls (on this wrapper, or any wrapper sharing the same latch instance) skip the primary. Useful when a primary failure is unlikely to recover within the wrapper's lifetime — wrong API key, sustained outage — so the default `try-primary-on-every-call` doesn't waste a round-trip on every retry. `latch.reset()` re-enables the primary. The latch propagates through `__getattr__` rebinds (e.g. `wrapper.bind_tools([...])`) so tool-bound and bare wrappers share one circuit. - Default-latch behaviour is unchanged: passing no `latch` retains the existing "retry primary on every call" semantics. ## langchain-anthropic - `ChatAnthropic.close()` / `aclose()` — closes `_client` (sync) and `_async_client` (async). Both are `cached_property` slots; guarded via `__dict__` so we don't materialize an uninstantiated cached client just to immediately close it. Idempotent. ## langchain-openai - `BaseChatOpenAI.close()` / `aclose()` — closes `root_client` and `root_async_client`, then clears the corresponding `client` / `async_client` attributes so the model can't be used after teardown. Idempotent. Tolerates the API-key-missing case where one client is `None`. Note: `BaseChatOpenAI`'s eager construction of both sync + async clients in its `model_validator` (even for async-only use) is a related inefficiency but not addressed here — it's a fixed per-instance cost rather than the per-request leak that `aclose()` solves. ## Tests - 7 new latch + propagation tests in `test_fallbacks.py` - 4 new lifecycle tests in `test_base.py` for `BaseChatModel` - 5 new tests in `test_chat_models.py` for `ChatAnthropic` - 5 new tests in `test_base.py` for `BaseChatOpenAI` Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
🦜🍎️ LangChain Core
Looking for the JS/TS version? Check out LangChain.js.
To help you ship LangChain apps to production faster, check out LangSmith. LangSmith is a unified developer platform for building, testing, and monitoring LLM applications.
Quick Install
pip install langchain-core
🤔 What is this?
LangChain Core contains the base abstractions that power the LangChain ecosystem.
These abstractions are designed to be as modular and simple as possible.
The benefit of having these abstractions is that any provider can implement the required interface and then easily be used in the rest of the LangChain ecosystem.
⛰️ Why build on top of LangChain Core?
The LangChain ecosystem is built on top of langchain-core. Some of the benefits:
- Modularity: We've designed Core around abstractions that are independent of each other, and not tied to any specific model provider.
- Stability: We are committed to a stable versioning scheme, and will communicate any breaking changes with advance notice and version bumps.
- Battle-tested: Core components have the largest install base in the LLM ecosystem, and are used in production by many companies.
📖 Documentation
For full documentation, see the API reference. For conceptual guides, tutorials, and examples on using LangChain, see the LangChain Docs. You can also chat with the docs using Chat LangChain.
📕 Releases & Versioning
See our Releases and Versioning policies.
💁 Contributing
As an open-source project in a rapidly developing field, we are extremely open to contributions, whether it be in the form of a new feature, improved infrastructure, or better documentation.
For detailed information on how to contribute, see the Contributing Guide.