Skip to content

Tools and schemas ​

Mistral completion models support normal Anvia tools, tool choice, and output schemas. The model can request a tool, but your application executes it and remains responsible for authorization.

Add a tool to an agent ​

Define the tool boundary with Zod schemas:

ts
import { Agent, createTool } from '@anvia/core'
import { z } from 'zod'

const getOrder = createTool({
  name: 'get_order',
  description: 'Look up one order available to the current user.',
  inputSchema: z.object({
    orderId: z.string().min(1),
  }),
  outputSchema: z.object({
    id: z.string(),
    status: z.string(),
  }),
  async execute({ orderId }) {
    await auth.requireOrderAccess(user.id, orderId)
    return orders.get(orderId)
  },
})

const agent = new Agent({
  id: 'order-support',
  model,
  instructions: 'Use get_order for account-specific status. Never guess order data.',
  maxTurns: 4,
  tools: [getOrder],
})

The runtime validates the model-supplied input, calls execute, validates the returned value when outputSchema is present, and gives the result back to the model. Authorization belongs inside the tool boundary; model arguments are not proof of access.

Control tool choice ​

Use automatic selection when the agent must look up information and then produce a final answer:

ts
const agent = new Agent({
  id: 'order-status',
  model,
  instructions: 'Look up the order before answering.',
  toolChoice: 'auto',
  maxTurns: 3,
  tools: [getOrder],
})

const result = await agent.generate({
    prompt: 'Where is order ord_123?'
})

if (result.type === 'response') {
  console.log(result.output)
}

Agent-level toolChoice: 'required' applies to every model turn, including turns after a tool result. A model honoring it keeps calling tools until the turn budget is exhausted; it does not mean "require a tool only on the first turn." If the lookup is mandatory, perform it in application code before starting the answering agent, or scope required choice to a direct completion whose tool call the application handles. Test tool selection and streamed tool arguments with the exact Mistral model used.

Parse a structured result ​

Use generateCompletion(...) for one schema-validated model call:

ts
import { generateCompletion } from '@anvia/core'
import { z } from 'zod'

const incidentSchema = z.object({
  severity: z.enum(['low', 'medium', 'high']),
  summary: z.string(),
  needsFollowUp: z.boolean(),
})

const result = await generateCompletion({
    prompt: 'Checkout requests timed out for 12 minutes.',
    model,
    outputSchema: incidentSchema
})

console.log(result.output.severity)

Use an agent outputSchema when tools or runtime context must run before the final structured answer:

ts
const triageAgent = new Agent({
  id: 'incident-triage',
  model,
  instructions: 'Classify the incident from the available evidence.',
  outputSchema: incidentSchema,
})

const result = await triageAgent.generate({
    prompt: incidentText
})

if (result.type === 'response') {
  const incident = result.output
  console.log(incident.severity)
}

A schema validates structure, not truth. Validate identifiers, permissions, and business rules before any product write.

The current Mistral adapter does not expose provider-executed tools. Keep application tool handlers bounded, observable, and idempotent where practical.

Built for Anvia.