This episode widens the model range: getting to know provider packages like langchain-openai, langchain-anthropic, and langchain-groq, using the uniform BaseChatModel interface, then arranging cross-model fallbacks, retry policies, timeouts, and model profiles for resilient applications.

In episode 15 you secured your agent with a threat model and layered mitigations. There's one security aspect often forgotten in model selection: dependence on a single provider. If one API provider goes down, or its cost suddenly balloons, the entire application is affected. A healthy architecture doesn't stake its life on a single model vendor.
Episode 16 teaches that flexibility. We'll map the official LangChain provider packages, use the uniform BaseChatModel interface so one codebase can switch providers, then arrange cross-model fallbacks, retry policies and timeouts, and close with model profiles that simplify managing many models. By the end of the episode, your application can fail on one provider without failing entirely.
One of the most important designs in LangChain v1 is the core/integrations architecture you already know from episode 2: langchain-core holds the abstract primitives, while support for each provider lives in a separate package. This means you only install what you actually use, and integrations can release faster than waiting for a core release. The main provider packages:
langchain-openai — OpenAI, including the latest models and embeddings.langchain-anthropic — Claude from Anthropic.langchain-groq — fast access to open-weight models via Groq.langchain-mistralai — Mistral models (Mistral Large, Nemo, and others).langchain-fireworks — high-speed model hosting from Fireworks.langchain-xai — Grok models from xAI.langchain-perplexity — access to Perplexity's search-based models.langchain-openrouter — one API for hundreds of models from many vendors.pip install langchain-openai langchain-anthropic langchain-groq
pip install langchain-mistralai langchain-fireworks langchain-xai
pip install langchain-perplexity langchain-openrouterAll these packages return objects with the same interface — that's what makes provider switching feel light. Each package reads its credentials from the corresponding environment variable (OPENAI_API_KEY, ANTHROPIC_API_KEY, GROQ_API_KEY, and so on), following the secrets-via-env pattern from episode 15.
Even though the backends differ, all chat model classes in LangChain derive from BaseChatModel — a single contract guaranteeing the same behavior: invoke, ainvoke, stream, batch, bind_tools, even with_structured_output. Notice this uniformity across three different providers:
from langchain_openai import ChatOpenAI
from langchain_anthropic import ChatAnthropic
from langchain_groq import ChatGroq
openai_model = ChatOpenAI(model="gpt-5.2", temperature=0.3)
anthropic_model = ChatAnthropic(model="claude-opus-5", temperature=0.3)
groq_model = ChatGroq(model="llama-3.3-70b-versatile", temperature=0.3)
for model in [openai_model, anthropic_model, groq_model]:
jawaban = model.invoke("Sebutkan satu bahasa pemrograman.")
print(model.__class__.__name__, jawaban.content)The code above runs unchanged on three different providers. What differs on the surface: model parameter names, valid model names, and feature support (for example, not all models support tool calling or structured output). This is the main strength of LangChain's abstraction — you learn once, use it everywhere. To quickly test across providers, just swap one model object in the whole pipeline.
Info
"Uniform" doesn't mean "identical". Certain features (vision, tool calling, streaming events) exist on one provider but not necessarily another. Always check the package documentation and release notes before assuming a feature travels with the interface.
BaseChatModel supports fallbacks: a list of backup models used in sequence if the primary model errors. This is a direct defense against provider downtime. With with_fallbacks, one chain object can try the primary model, then automatically switch to the backup when the primary fails:
primary = ChatOpenAI(model="gpt-5.2", temperature=0.3)
backup = ChatAnthropic(model="claude-opus-5", temperature=0.3)
chat = primary.with_fallbacks([backup])
hasil = chat.invoke("Jelaskan cara kerja fallback model.")If gpt-5.2 errors (rate limit, timeout, service down), LangChain automatically tries claude-opus-5. Fallbacks can be more than one — the list order is the priority order. This is also useful as a cost strategy: an expensive model as primary, a cheap model as backup when the primary goes over budget. Fallbacks work at every level: from a single simple invoke to full LCEL chains and agents — because with_fallbacks returns an object that's still of type Runnable.
Provider errors are often transient: momentary rate limits, dropped connections, or brief overloads. Retries handle the transient ones; timeouts handle the hanging ones. The combination keeps your application from giving up too early, while also not waiting forever:
robust = primary.with_retry(
stop_after_attempt=3,
wait_exponential_jitter=True,
)
timeout_model = primary.with_timeout(seconds=30)
chain = (prompt | timeout_model | StrOutputParser())wait_exponential_jitter=True makes the pause between attempts grow exponentially with random variation — the variation prevents the "thundering herd" effect when many clients fail at once and then retry simultaneously. Reasonable standard values: three attempts with backoff, a 30-60 second timeout depending on model latency. Combine retry and timeout with fallback in sequence: retry a few times on the primary provider, then give up and move to the backup.
Warning
Unbounded retries are just as dangerous as timeouts without retries. Set an attempt limit and always include a timeout at the call layer. For non-idempotent requests, also consider the retry effect: a call that succeeded on the provider's side but failed on yours could be executed twice.
The more providers, the more parameter combinations to remember: the right temperature for each model, max tokens, valid model names, and so on. Model profiles (also known as harness profiles) centralize these settings: one profile name encodes all the parameters for one model variant.
from langchain import profiles
from langchain_openai import ChatOpenAI
from langchain_anthropic import ChatAnthropic
profile = profiles.get_harness_profile("openai.gpt-5.2")
model_a = ChatOpenAI(**profile)
profile_lain = profiles.get_harness_profile("anthropic.claude-opus-5")
model_b = ChatAnthropic(**profile_lain)get_harness_profile returns a dict of parameters ready to be spread into the model constructor with the unpacking operator. Moving to a new model only means changing one profile name string — the right parameters come along, and the team no longer keeps scattered model configs in every file. The most powerful production combination: model profiles for configuration, with_fallbacks for resilience, retries for transient disruptions, and LangSmith (episode 19) to monitor how each model behaves under real conditions.
Episode 16 freed you from dependence on a single model: understanding the provider package map (langchain-openai, langchain-anthropic, langchain-groq, up to langchain-openrouter), leveraging the uniform BaseChatModel interface so one codebase serves many backends, arranging cross-model fallbacks for resilience, installing retry policies and timeouts to handle transient disruptions, and tidying configuration with model profiles. Your application no longer puts all its eggs in one vendor's basket.
Key takeaways:
BaseChatModel guarantees invoke, stream, bind_tools, and with_structured_output work across all providers.with_fallbacks automatically shifts failures to backup models and can be chained.This solid per-model foundation will be used for something bigger. In episode 17 we go deep into Advanced LangGraph: typed states with reducers, checkpointing for time travel, subgraphs, and persistence with langgraph-checkpoint-postgres along with namespaces and TTL. See you there!