LangChain/Models
Intermediate14 min

Configurable Models

init_chat_model() lets you define a chain once and swap the underlying model at runtime via config — no redeploy needed. This article covers when that's worth the complexity, how config resolution actually works, what configurable_fields='any' silently exposes to attackers, and how to gate cost before your bill 50× overnight.

Quick Reference

  • init_chat_model() with no model = fully configurable; pass model name in config at invoke time
  • configurable_fields=("model", "temperature") exposes only those fields as runtime overrides
  • configurable_fields="any" also exposes api_key and base_url — never use in untrusted contexts
  • config_prefix="llm" scopes keys to llm_model, llm_temperature — required when chaining two configurable models
  • bind_tools() and with_structured_output() work on configurable models, but tool schemas vary by provider
  • Cost gate: validate the incoming model name against an allowlist before it reaches init_chat_model
  • with_fallbacks() wraps a configurable model to handle unavailable providers gracefully

When NOT to Use Configurable Models

Configurable models solve a real problem, but they add a resolution layer that makes debugging harder. Use them when the use case genuinely requires runtime model switching. Skip them when it doesn't.

ScenarioUse configurable model?Why
A/B testing models in productionYesSwap without redeploy; track per-model metrics
User-controlled model selectionYesConfig comes from request context, not code
Multi-tenant with different model tiersYesModel resolved per tenant at invoke time
Single internal service, model never changesNoHardcode it — adds zero value, adds indirection
Debug: try a different model locallyNoJust change the constant — no need for runtime config
Different models for different tasks in one chainYes, with config_prefixClassifier cheap, generator expensive
Configurable models obscure what model actually ran

When something goes wrong, you need to know which model was invoked. Always log config["configurable"] at the request layer — it won't appear in LangChain's default trace unless you explicitly capture it.