# ConfigurableModelMiddleware

> **Class** in `deepagents_code`

📖 [View in docs](https://reference.langchain.com/python/deepagents-code/configurable_model/ConfigurableModelMiddleware)

Swap the model or per-call settings from `runtime.context`.

Reads two optional keys from the runtime context dict:

- `'model'` — a `provider:model` spec (e.g. `"openai:gpt-5"`).
    When present and different from the current model, the request is
    re-routed to the new model.
- `'model_params'` — a dict of extra model settings (e.g.
    `{"temperature": 0}`) that are shallow-merged into the
    request's `model_settings`.

This middleware is typically the outermost layer so it intercepts every
model call before provider-specific middleware (like
`AnthropicPromptCachingMiddleware`) runs.

## Signature

```python
ConfigurableModelMiddleware(
    self,
    *,
    persist_model_state: bool = True,
    openai_prompt_cache_key: bool | None = None,
    cli_max_retries: int | None = None,
    strict_model_resolution: bool = False,
)
```

## Parameters

| Name | Type | Required | Description |
|------|------|----------|-------------|
| `persist_model_state` | `bool` | No | Whether completed calls should write private resume metadata. Subagent instances disable this because they do not own the parent thread's resume state. (default: `True`) |
| `openai_prompt_cache_key` | `bool \| None` | No | Whether to inject a per-thread OpenAI `prompt_cache_key`. Left as `None` (the default) it is resolved once here from `models.openai_prompt_cache_key` and cached, so no per-call read happens. The one-time `config.toml` read assumes current callers construct the middleware off the blockbuster-guarded server loop (the server path offloads `create_cli_agent` via `asyncio.to_thread`); if that assumption is ever broken the read would trip `BlockingError`, which `_resolve_openai_prompt_cache_key_enabled` re-raises rather than masks. Pass an explicit bool to bypass the config read (mainly for tests). (default: `None`) |
| `cli_max_retries` | `int \| None` | No | Explicit `--max-retries` value to retain across runtime model switches. (default: `None`) |
| `strict_model_resolution` | `bool` | No | Whether invalid runtime model overrides should fail the call instead of falling back to the construction-time model. (default: `False`) |

## Extends

- `AgentMiddleware`

## Constructors

```python
__init__(
    self,
    *,
    persist_model_state: bool = True,
    openai_prompt_cache_key: bool | None = None,
    cli_max_retries: int | None = None,
    strict_model_resolution: bool = False,
) -> None
```

| Name | Type |
|------|------|
| `persist_model_state` | `bool` |
| `openai_prompt_cache_key` | `bool \| None` |
| `cli_max_retries` | `int \| None` |
| `strict_model_resolution` | `bool` |


## Properties

- `trace_policy`

## Methods

- [`wrap_model_call()`](https://reference.langchain.com/python/deepagents-code/configurable_model/ConfigurableModelMiddleware/wrap_model_call)
- [`awrap_model_call()`](https://reference.langchain.com/python/deepagents-code/configurable_model/ConfigurableModelMiddleware/awrap_model_call)

---

[View source on GitHub](https://github.com/langchain-ai/deepagents/blob/3812967c84d90619848f3185f22470204fc88bd8/libs/code/deepagents_code/configurable_model.py#L815)