Skip to main content
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 the callback switches to dynamic-selection mode and the fixed-model setting is ignored.

Fixed model

Specify it via the model option; omit to use the account default:
import { qodercliAuth, query } from '@qoder-ai/qoder-agent-sdk';

const q = query({
  prompt: 'Analyze this code',
  options: {
    auth: qodercliAuth(),
    model: 'performance',
  },
});

Dynamic selection

Provide a callback function that is invoked before every LLM request:
import { qodercliAuth, query, type ModelPolicyProvider } from '@qoder-ai/qoder-agent-sdk';

const resolveModel: ModelPolicyProvider = (context) => {
  return { model: 'performance' };
};

const q = query({
  prompt: 'Analyze this code',
  options: {
    auth: qodercliAuth(),
    resolveModel,
  },
});
The callback receives the request’s purpose, session info, and the list of currently available models.

Routing by purpose

Use a different model per purpose:
const resolveModel: ModelPolicyProvider = (context) => {
  switch (context.purpose) {
    case 'main':       return { model: 'performance' };
    case 'subagent':   return { model: 'efficient' };
    case 'compact':    return { model: 'lite' };
    default:           return { model: 'auto' };
  }
};
Purposes cover scenarios like main conversation, sub-agent, context compaction, WebFetch, and image generation. For the full list, see SDK References.

Returning model parameters

Return parameters with the selected model to override the context window and thinking depth for that LLM request. These keys are camelCase at the SDK control boundary:
const resolveModel: ModelPolicyProvider = (context) => {
  return {
    model: 'ultimate',
    parameters: {
      contextWindow: 200000,
      reasoningEffort: 'high',
    },
  };
};
Choose values supported by the selected model. The available context-window and thinking-effort metadata is exposed on context.availableModels through ModelInfo.context_config and ModelInfo.thinking_config.

Timeout

The callback has a default timeout (in milliseconds). Increase it when the callback performs remote I/O:
{ resolveModel, resolveModelTimeoutMs: 800 }

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:
const resolveModel: ModelPolicyProvider = () => ({
  model: {
    provider: 'bailian',
    model: 'qwen3.5-plus-cp',
    api_key: process.env.MY_API_KEY!,
  },
});
The available provider/model catalog can be fetched at runtime, so the front-end can render selectors and an API-key input.

Runtime operations

While a session is running you can fetch the account’s currently available model list:
import { qodercliAuth, query } from '@qoder-ai/qoder-agent-sdk';

const q = query({
  prompt: '...',
  options: { auth: qodercliAuth() },
});

const models = await q.getAvailableModels();
for (const m of models) {
  console.log(`${m.value}\t${m.displayName}\t${m.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.

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:
const resolveModel: ModelPolicyProvider = async (context) => {
  try {
    const policy = await fetchRemotePolicy(context);
    return { model: policy.model };
  } catch {
    return { model: 'auto' };   // fallback, must be non-empty
  }
};
For full field and type definitions, see SDK References.