Mistral AI provides high-performance European LLMs — new Mistral({ apiKey }) initializes the client. mistral.chat.complete({ model: "mistral-large-latest", messages }) generates completions. stream: true with mistral.chat.stream(...) enables async iteration over chunks. Tool calling: tools: [{ type: "function", function: { name, description, parameters } }] with toolChoice: "auto". JSON mode: responseFormat: { type: "json_object" } with instructed JSON output. Models: mistral-large-latest (most capable), mistral-small-latest (fast and cheap), open-mistral-nemo (open weight, 128k context), codestral-latest (code specialist). Fill-in-the-middle: mistral.fim.complete({ model: "codestral-latest", prompt: code_prefix, suffix: code_suffix }). Embeddings: mistral.embeddings.create({ model: "mistral-embed", inputs: texts }) returns 1024-dim vectors. Vision: pixtral-large-latest with image URLs in message content. safePropmt: true adds a safety system prompt. Claude Code generates Mistral chat, tool agents, embeddings, and code completion APIs.
CLAUDE.md for Mistral AI
## Mistral AI Stack
- Version: @mistralai/mistralai >= 1.3
- Init: const mistral = new Mistral({ apiKey: process.env.MISTRAL_API_KEY! })
- Chat: const res = await mistral.chat.complete({ model: "mistral-large-latest", messages: [{ role: "user", content: prompt }] })
- Answer: res.choices?.[0].message.content
- Stream: const stream = await mistral.chat.stream({ model: "mistral-small-latest", messages }); for await (const chunk of stream) console.log(chunk.data.choices[0]?.delta?.content)
- JSON: responseFormat: { type: "json_object" } + system: "Always respond with valid JSON"
- Embed: const res = await mistral.embeddings.create({ model: "mistral-embed", inputs: ["text"] })
- FIM: await mistral.fim.complete({ model: "codestral-latest", prompt, suffix })
Mistral Client
// lib/mistral/client.ts — Mistral SDK with chat and embeddings helpers
import { Mistral } from "@mistralai/mistralai"
import type { Messages } from "@mistralai/mistralai/models/components"
const mistral = new Mistral({ apiKey: process.env.MISTRAL_API_KEY! })
export const MODELS = {
LARGE: "mistral-large-latest",
SMALL: "mistral-small-latest",
NEMO: "open-mistral-nemo", // 128k context, open weight
CODE: "codestral-latest", // Code specialist
EMBED: "mistral-embed", // 1024-dim embeddings
VISION: "pixtral-large-latest", // Vision + text
} as const
export type MistralModel = (typeof MODELS)[keyof Omit<typeof MODELS, "EMBED" | "VISION" | "CODE">]
/** Chat completion — returns content string */
export async function chat(
prompt: string,
options: {
systemPrompt?: string
model?: MistralModel
temperature?: number
maxTokens?: number
jsonMode?: boolean
} = {},
): Promise<string> {
const { systemPrompt, model = MODELS.SMALL, temperature = 0.7, maxTokens = 1024, jsonMode = false } = options
const messages: Messages[] = []
if (systemPrompt) messages.push({ role: "system", content: systemPrompt })
if (jsonMode && !systemPrompt) messages.push({ role: "system", content: "Always respond with valid JSON only." })
messages.push({ role: "user", content: prompt })
const response = await mistral.chat.complete({
model,
messages,
temperature,
maxTokens,
...(jsonMode ? { responseFormat: { type: "json_object" } } : {}),
})
return response.choices?.[0]?.message?.content ?? ""
}
/** Multi-turn conversation */
export async function converse(
messages: Messages[],
model: MistralModel = MODELS.SMALL,
): Promise<{ content: string; toolCalls?: any[] }> {
const response = await mistral.chat.complete({ model, messages })
const message = response.choices?.[0]?.message
return {
content: typeof message?.content === "string" ? message.content : "",
toolCalls: (message as any)?.toolCalls ?? undefined,
}
}
/** Stream generator */
export async function* streamChat(
prompt: string,
systemPrompt?: string,
model: MistralModel = MODELS.SMALL,
): AsyncGenerator<string> {
const messages: Messages[] = []
if (systemPrompt) messages.push({ role: "system", content: systemPrompt })
messages.push({ role: "user", content: prompt })
const stream = await mistral.chat.stream({ model, messages })
for await (const chunk of stream) {
const delta = chunk.data.choices[0]?.delta?.content
if (delta) yield delta as string
}
}
/** Generate text embeddings */
export async function embedTexts(texts: string[]): Promise<number[][]> {
const response = await mistral.embeddings.create({
model: MODELS.EMBED,
inputs: texts,
})
return response.data.map((d) => d.embedding)
}
/** Single text embedding */
export async function embedText(text: string): Promise<number[]> {
const [embedding] = await embedTexts([text])
return embedding
}
/** Codestral fill-in-the-middle */
export async function fillInMiddle(prefix: string, suffix: string): Promise<string> {
const response = await mistral.fim.complete({
model: MODELS.CODE,
prompt: prefix,
suffix,
temperature: 0.1,
maxTokens: 512,
})
return response.choices?.[0]?.message?.content ?? ""
}
/** Vision: analyze an image URL */
export async function analyzeImage(imageUrl: string, question: string): Promise<string> {
const response = await mistral.chat.complete({
model: MODELS.VISION,
messages: [{
role: "user",
content: [
{ type: "image_url", imageUrl: { url: imageUrl } },
{ type: "text", text: question },
],
}],
maxTokens: 1024,
})
return response.choices?.[0]?.message?.content as string ?? ""
}
export { mistral }
Tool-Calling Agent
// lib/mistral/agent.ts — function calling with Mistral
import { mistral, MODELS } from "./client"
import type { Messages, Tool } from "@mistralai/mistralai/models/components"
// Tool definitions
const TOOLS: Tool[] = [
{
type: "function",
function: {
name: "get_weather",
description: "Get current weather for a city",
parameters: {
type: "object",
properties: {
city: { type: "string", description: "City name" },
units: { type: "string", enum: ["celsius", "fahrenheit"], default: "celsius" },
},
required: ["city"],
},
},
},
{
type: "function",
function: {
name: "calculate",
description: "Evaluate a mathematical expression",
parameters: {
type: "object",
properties: {
expression: { type: "string", description: "Math expression, e.g. '2 + 3 * 4'" },
},
required: ["expression"],
},
},
},
]
// Tool implementations
async function executeTool(name: string, args: Record<string, unknown>): Promise<string> {
switch (name) {
case "get_weather": {
const { city, units = "celsius" } = args as { city: string; units: string }
// Mock — replace with a real weather API
return JSON.stringify({ city, temp: 22, units, condition: "Partly cloudy" })
}
case "calculate": {
try {
// Safe eval alternative
const result = Function(`"use strict"; return (${args.expression})`)()
return String(result)
} catch {
return "Error: Invalid expression"
}
}
default:
return `Unknown tool: ${name}`
}
}
/** Run agentic loop with tool calls */
export async function runAgent(userMessage: string, maxIterations = 5): Promise<string> {
const messages: Messages[] = [{ role: "user", content: userMessage }]
for (let i = 0; i < maxIterations; i++) {
const response = await mistral.chat.complete({
model: MODELS.LARGE,
messages,
tools: TOOLS,
toolChoice: "auto",
})
const message = response.choices?.[0]?.message
if (!message) break
messages.push(message as Messages)
const toolCalls = (message as any).toolCalls
if (!toolCalls?.length) {
return typeof message.content === "string" ? message.content : ""
}
// Execute all tool calls in parallel
const toolResults = await Promise.all(
toolCalls.map(async (tc: any) => ({
id: tc.id,
result: await executeTool(tc.function.name, JSON.parse(tc.function.arguments)),
})),
)
// Append tool results
for (const { id, result } of toolResults) {
messages.push({ role: "tool", content: result, toolCallId: id } as Messages)
}
}
return "Max iterations reached without a final answer."
}
For the OpenAI alternative when GPT-4o/o1 reasoning, DALL-E image generation, or maximum model capability benchmarks are required — OpenAI leads on reasoning tasks while Mistral Large is competitive at lower cost and processes data in the EU for GDPR compliance, see the OpenAI guide. For the Groq alternative when ultra-low latency (sub-100ms TTFT) and maximum tokens/second throughput are the primary requirement — Groq’s LPU hardware runs Mistral and Llama models 10-20x faster than GPU inference for latency-critical applications while Mistral’s own API includes access to proprietary models with EU data residency, see the Groq guide. The Claude Skills 360 bundle includes Mistral skill sets covering chat, tool agents, embeddings, and Codestral FIM. Start with the free tier to try Mistral AI generation.