> ## Documentation Index
> Fetch the complete documentation index at: https://docs.qoder.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Model Selection

`query()` offers two model-selection modes:

* **Fixed model (default)**: the entire session uses one model.
* **Dynamic selection**: a callback is called before every LLM request to return the model. You can route by purpose (main conversation, sub-agent, context compaction, etc.) or return a BYOK credential to use your own API key.

The two modes are mutually exclusive: passing a callback switches to dynamic-selection mode and the fixed-model setting is ignored.

<div id="fixed-model" />

<div id="fixedmodel" />

## Fixed model

Specify it via the model option; omit to use the account default:

```python theme={null}
from qoder_agent_sdk import query, QoderAgentOptions

options = QoderAgentOptions(model="performance")

async for msg in query(prompt="Analyze this code", options=options):
    print(msg)
```

<div id="dynamic-selection" />

<div id="dynamicselection" />

## Dynamic selection

Provide a callback function that is invoked before every LLM request:

```python theme={null}
from qoder_agent_sdk import query, QoderAgentOptions
from qoder_agent_sdk.types import ModelPolicyContext, ModelPolicyResult, ModelPolicyProvider

resolve_model: ModelPolicyProvider = lambda context: {"model": "performance"}

options = QoderAgentOptions(resolve_model=resolve_model)

async for msg in query(prompt="Analyze this code", options=options):
    print(msg)
```

The callback receives the request's purpose, session info, and the list of currently available models.

<div id="routing-by-purpose" />

<div id="routingbypurpose" />

### Routing by purpose

Use a different model per purpose:

```python theme={null}
def resolve_model(context: ModelPolicyContext) -> ModelPolicyResult:
    match context.get("purpose"):
        case "main":     return {"model": "performance"}
        case "subagent": return {"model": "efficient"}
        case "compact":  return {"model": "lite"}
        case _:          return {"model": "auto"}
```

Purposes cover scenarios like main conversation, sub-agent, context compaction, WebFetch, and image generation. For the full list, see [SDK References](/en/cli/sdk/python/references).

<div id="timeout" />

### Timeout

The callback has a default timeout (in milliseconds). Increase it when the callback performs remote I/O:

```python theme={null}
options = QoderAgentOptions(
    resolve_model=resolve_model,
    resolve_model_timeout_ms=800,
)
```

<div id="byok-use-your-own-api-key" />

<div id="byokuseyourownapikey" />

### BYOK: use your own API key

The callback can also return a BYOK credential object — that request will be routed to a third-party provider:

```python theme={null}
import os

def resolve_model(context: ModelPolicyContext) -> ModelPolicyResult:
    return {
        "model": {
            "provider": "bailian",
            "model": "qwen3.5-plus-cp",
            "api_key": os.environ["MY_API_KEY"],
        },
    }
```

The available provider/model catalog can be fetched via runtime methods, so the front-end can render selectors and an API-key input.

<div id="runtime-operations" />

<div id="runtimeoperations" />

## Runtime operations

While a session is running you can fetch the account's currently available model list:

```python theme={null}
from qoder_agent_sdk import query, QoderAgentOptions

options = QoderAgentOptions(...)

async with QoderSDKClient(options=options) as client:
    models = await client.get_available_models()
    for m in models:
        print(f"{m['value']}\t{m['displayName']}\t{m.get('isEnabled', True)}")
```

You can also switch the current model in fixed-model mode, or fetch the BYOK provider catalog. For specific method signatures, see [SDK References](/en/cli/sdk/python/references).

<div id="error-handling" />

<div id="errorhandling" />

## Error handling

Dynamic-selection mode has **no automatic fallback** — a callback that times out, throws, or returns an empty model causes the query to fail. Handle errors inside the callback:

```python theme={null}
async def resolve_model(context: ModelPolicyContext) -> ModelPolicyResult:
    try:
        policy = await fetch_remote_policy(context)
        return {"model": policy["model"]}
    except Exception:
        return {"model": "auto"}  # fallback, must be non-empty
```

For full field and type definitions, see [SDK References](/en/cli/sdk/python/references).
