Per-call Overrides
Using different models, temperatures, or token limits for individual calls
A VernLLM instance is configured once with a default model (and other options like
defaultMaxTokens), but almost every generation-related field on CallParams can be overridden
for an individual call() without creating a second instance.
const llm = new VernLLM({
client: openai,
model: 'gpt-4o-mini', // cheap default for most calls
});
// Uses gpt-4o-mini, the instance default
const summary = await llm.call({
userContent: 'Summarize this in one sentence.',
});
// Overrides the model for just this call
const analysis = await llm.call({
model: 'gpt-4o',
temperature: 0.2,
userContent: 'Do a careful multi-step analysis of this contract.',
});What can be overridden per call
| Field | Falls back to |
|---|---|
model | The instance's model option |
maxTokens | The instance's defaultMaxTokens (1000) |
temperature | 0.2, used only when both the per-call value and defaultTemperature are undefined. Either one set to null omits temperature instead. |
reasoningEffort | The per-call value, then the fallback target's own defaultReasoningEffort (if this call lands on a fallback target), then the instance's defaultReasoningEffort. Omitted from the request only when none of those is set, in which case the provider's own default applies. |
budgetTokens | The per-call value, then the fallback target's own defaultBudgetTokens (if this call lands on a fallback target), then the instance's defaultBudgetTokens. Omitted from the request only when none of those is set. |
chunkIdleTimeoutMs | The instance's chunkIdleTimeoutMs (30000). Only applies when stream: true. See Per-chunk idle timeout. |
temperature isn't left unset when you don't pass it — VernLLM defaults it to 0.2 itself.
Pass temperature: null on a call, or defaultTemperature: null on the instance, to omit
temperature from the request entirely and let the provider apply its own default instead.
Claude Opus 4.7 and later, Claude Opus 5, and every Claude 5 tier model (Sonnet 5, Fable 5, Mythos
5) reject temperature on a non-default value with a 400 error. Use temperature: null for those
models, or defaultTemperature: null on the instance if you route calls to one, and describe the
desired behavior in the prompt instead. Separately, fromAnthropic/fromBedrock omit
temperature automatically whenever budgetTokens/reasoningEffort is set, on any model, since
Anthropic rejects temperature alongside any thinking mode, manual or adaptive.
reasoningEffort and budgetTokens each resolve through the same three layers every other
per-call option does: the per-call value, then the fallback target's own default, then the
instance-level default, first one set wins. See
Call Params for the full conversion table
between the two, and per-provider behavior.
jsonMode, jsonSchema, and schema aren't instance-level
options at all — they only ever exist per call, so there's nothing to "override" at the
instance level, you just set them on the calls that need them.
Getting Started has a quick-start version of this same pattern, including switching to a reasoning model for a single call:
const llm = new VernLLM({ client: openai, model: 'gpt-4o-mini' });
await llm.call({
systemPrompt: '...',
userContent: '...',
model: 'o3',
reasoningEffort: 'high', // passed through as `reasoning_effort` for supported models
});This page goes into more depth on when and how to reach for overrides.
Retry/timeout/circuit-breaker behavior (maxRetries, timeoutMs, baseDelayMs,
nonRetryableStatus, circuitBreaker) is instance-level only and cannot be changed per call. If
different calls need different resilience settings (a different threshold or cooldownMs
per model), use separate VernLLM instances that share the same underlying client.
chunkIdleTimeoutMs is the one exception, it's overridable per call since stream: true calls
often need a different idle allowance than the instance default, see Per-chunk idle timeout. If instead you
just want one model's failures not to open the circuit for another model on the same instance,
without different threshold/cooldown values, circuitBreaker: { isolateByModel: true } does that
without a second instance, see Per-model isolation.
Common pattern: cheap default, expensive escalation
A typical setup uses a fast/cheap model by default and escalates to a stronger model only for calls that need it, rather than paying for the expensive model on every request:
async function extractCandidate(resumeText: string) {
return llm.call({
model: 'gpt-4o-mini',
userContent: resumeText,
schema: CandidateSchema,
});
}
async function reviewFlaggedResume(resumeText: string) {
// Harder task, worth the stronger model
return llm.call({
model: 'gpt-4o',
temperature: 0.1,
userContent: resumeText,
schema: CandidateSchema,
});
}Per-user or per-tenant model selection
Because model is just a string on CallParams, it can come from anywhere at call time — a
config lookup, a feature flag, a per-tenant setting:
async function callForTenant(tenantId: string, userContent: string) {
const model = await getTenantModelPreference(tenantId); // e.g. 'gpt-4o' or 'gpt-4o-mini'
return llm.call({ model, userContent });
}Interaction with usage tracking
onUsage reports the model that actually served the request, including a per-call override, not
the instance's default. This matters if you bill different models at different rates. The same
applies to onUsageFailure, since both share the same TokenUsage shape:
const llm = new VernLLM({
client: openai,
model: 'gpt-4o-mini',
onUsage: ({ model, promptTokens, completionTokens }) => {
// `model` reflects the override, e.g. 'gpt-4o', not 'gpt-4o-mini'
billing.record({ model, promptTokens, completionTokens });
},
});See Usage Tracking for the full onUsage shape.
Interaction with caching
If you cache calls that use different model or temperature overrides under the same
cacheKey, you'll get a cached result from whichever call happened to populate the cache first,
regardless of which override the current call is using. Fold all inputs that affect the output into
the key:
const cacheKey = `analysis:${docId}:${documentHash}:${model}:${temperature}:schema-v2`;Include a stable document revision/content hash and any generation settings that affect the output, such as model, temperature, and schema version.
See Caching for more on choosing cache keys.