Mistral provider
Standalone — usable in any Node project, no
@warlock.js/corerequired.
@warlock.js/ai-mistral is the Mistral AI provider adapter for
@warlock.js/ai. Mistral exposes an OpenAI-compatible
API, so MistralSDK is a thin wrapper over
@warlock.js/ai-openai — it does not
re-implement the wire protocol, streaming, tool calls, structured output,
error wrapping, or token accounting. It builds one internal OpenAISDK
pointed at Mistral’s baseURL (https://api.mistral.ai/v1) with
provider: "mistral", then layers on Mistral-aware capability inference and
default pricing.
Install
Section titled “Install”npm install @warlock.js/ai @warlock.js/ai-mistralyarn add @warlock.js/ai @warlock.js/ai-mistralpnpm add @warlock.js/ai @warlock.js/ai-mistralConstruct
Section titled “Construct”import { MistralSDK } from "@warlock.js/ai-mistral";
const mistral = new MistralSDK({ apiKey: process.env.MISTRAL_API_KEY!,});baseURL defaults to https://api.mistral.ai/v1 (the OpenAI-compatible
endpoint serving /chat/completions and /embeddings). provider defaults
to "mistral" and flows through to ModelContract.provider,
AgentReport.model.provider, and logs. Override baseURL only to reach a
Mistral-compatible gateway or proxy — every other upstream OpenAI
ClientOptions value (timeout, maxRetries, defaultHeaders, fetch, …)
is forwarded verbatim.
Use as a model
Section titled “Use as a model”const model = mistral.model({ name: "mistral-large-latest" });// Pass to any @warlock.js/ai agent / workflow / supervisor.The headline -latest aliases are exported as MISTRAL_MODELS
({ chat, vision, reasoning, embedding }) for convenience, but mistral.model()
also accepts any version-pinned id (mistral-large-2512, magistral-medium-2509):
mistral.model({ name: "mistral-large-latest" }); // multimodal flagshipmistral.model({ name: "magistral-medium-latest" }); // reasoningmistral.model({ name: "pixtral-large-latest" }); // visionUse as an embedder
Section titled “Use as an embedder”const embedder = mistral.embedder({ name: "mistral-embed" });
const { vector, dimensions, usage } = await embedder.embed("Hello world");const { vectors } = await embedder.embedMany(["doc 1", "doc 2"]);mistral-embed is reachable through the OpenAI-compatible /v1/embeddings
endpoint; the embedder delegates straight to the wrapped OpenAI embedder.
Capabilities
Section titled “Capabilities”The wrapper injects Mistral-aware inference before delegating to the OpenAI adapter (the OpenAI prefix lists never match Mistral names):
- Vision — auto-inferred
truefor thepixtralfamily and the recent multimodal generations (mistral-large,mistral-medium,ministral-3);falseotherwise. - Reasoning — auto-inferred
truefor themagistralfamily and the hybridmistral-smallgeneration;falseotherwise. Drives whetherreasoning_effortis forwarded. - Structured output —
trueby default, unlessresponseFormatis forced to"json_object"or"text". - Prompt caching —
true, inherited from the OpenAI adapter (read-sidecachedTokensaccounting). - PDF / audio —
falseby default; opt in with.model({ pdf: true })or{ audio: true }.
An explicit flag always wins over inference:
const model = mistral.model({ name: "some-fine-tune", vision: true });Pricing and usage
Section titled “Pricing and usage”The adapter ships a default registry (MISTRAL_DEFAULT_PRICING, USD per
1,000,000 tokens, with the prompt-cache rate as cachedInput) so cost
truth works out of the box. The rates come from
Mistral’s pricing and the
model pages (API ids and aliases), fetched 2026-10-17: Large 3, Medium
3.5, Small 4, Ministral 14B, Codestral and mistral-embed, under their
-latest aliases and pinned ids. Mistral Large 4 (preview, temporary
sale price) and the retired Pixtral / Magistral models are not included.
Pass your own pricing — keyed by model id — to win per model:
import { MistralSDK } from "@warlock.js/ai-mistral";
const mistral = new MistralSDK({ apiKey: process.env.MISTRAL_API_KEY ?? "", pricing: { // USD per 1M tokens — contract rates win over the defaults. "mistral-large-latest": { input: 0.45, output: 1.35, cachedInput: 0.045 }, },});
// Or per model, overriding the SDK entry:const model = mistral.model({ name: "mistral-small-latest", pricing: { input: 0.15, output: 0.6, cachedInput: 0.015 },});Resolution at model() time: per-model pricing > SDK-level pricing >
MISTRAL_DEFAULT_PRICING > undefined.
Every response reports token usage (input, output, cachedTokens,
reasoningTokens) — on model.complete() and the streaming done chunk
too, with usage.cost when priced. prompt_tokens contains the cached
tokens (inputIncludesCache: true). Need an offline estimate before a
call? mistral.count(text) returns a fast character-heuristic
approximation — good for budgeting and quota guards, not for billing.
Prompt caching. Mistral documents a prompt_cache_key request field
(prompt caching).
Set promptCacheKey on the model — sent while the SDK keeps its default
"mistral" provider label — to route related requests to the same cache:
const cached = mistral.model({ name: "mistral-large-latest", promptCacheKey: "conversation:42" });An overloaded endpoint (HTTP 503) surfaces as ProviderOverloadedError
(code: "PROVIDER_OVERLOADED", retryable: true); every provider error
carries status, retryable and billed (false for 401 / 402 / 403,
otherwise "unknown").
OpenAI-compatible wire behavior
Section titled “OpenAI-compatible wire behavior”Because Mistral speaks the OpenAI Chat Completions + Embeddings protocol,
everything the OpenAI adapter does applies unchanged here: streaming deltas
with consolidated tool calls, response_format: json_schema structured
output (override per model with responseFormat), reasoning_effort for
reasoning models, multipart image input, and the neutral Usage breakdown.
Raw errors are wrapped into the typed @warlock.js/ai AIError hierarchy by
the wrapped adapter (dispatch keys on APIError.status + code).
For the full wire-level surface — it is identical here — see the
OpenAI provider page and the warlock-js-ai-mistral
skill.
See also
Section titled “See also”- OpenAI provider — the wrapped adapter; identical wire behavior.
- Groq provider — another OpenAI-compatible wrapper, for Groq-hosted open models.
@warlock.js/ai— passing the model intoai.agent({ ... }).
Provider body options and token estimates
Section titled “Provider body options and token estimates”This adapter delegates Chat Completions to the OpenAI adapter, so
providerOptions.openai.body adds native Chat request fields. Other provider
keys are ignored. Plain-object fields merge one level deep with neutral options;
caller-provided keys win, while arrays, scalars and null replace the field.
The OpenAI adapter’s protected conversation, tool and transport fields remain
protected here too. Send only fields supported by this provider; do not reuse
OpenAI-only bodies across a mixed-provider fallback chain.
Models from this adapter have no native countTokens method. Check
model.countTokens before using an optional native counting capability;
sdk.count(text) is a separate offline estimate.