Anvia
Agents

Structured Output

Configure agents to return schema-validated output.

Use structured output when the final agent response should match a schema instead of free-form prose.

Add an Output Schema

import { AgentBuilder } from "@anvia/core";
import { OpenAIClient } from "@anvia/openai";
import { z } from "zod";

const client = new OpenAIClient({ apiKey });
const model = client.completionModel("gpt-5");

const ticketSummarySchema = z.object({
  priority: z.enum(["low", "medium", "high"]),
  topic: z.string(),
  nextAction: z.string(),
});

const agent = new AgentBuilder("ticket-triage", model)
  .instructions("Classify the support ticket.")
  .outputSchema(ticketSummarySchema)
  .build();

const response = await agent
  .prompt("Customer cannot access billing settings.")
  .send();

const summary = ticketSummarySchema.parse(JSON.parse(response.output));

The schema is converted to provider JSON Schema and sent with the completion request.

Keep the Prompt Direct

Structured output works best when the instruction names the expected object.

const agent = new AgentBuilder("lead-qualifier", model)
  .instructions("Return only the lead qualification object.")
  .outputSchema(
    z.object({
      qualified: z.boolean(),
      companySize: z.string().optional(),
      reason: z.string(),
    }),
  )
  .build();

Avoid asking for both a long explanation and a strict object in the same agent. If you need both, include fields for both.

With Tools

Structured output can be combined with tools. The agent may call tools first, then return the final schema-shaped answer.

const agent = new AgentBuilder("order-status", model)
  .instructions("Look up the order, then return the status object.")
  .tool(lookupOrder)
  .defaultMaxTurns(3)
  .outputSchema(
    z.object({
      orderId: z.string(),
      status: z.string(),
      customerMessage: z.string(),
    }),
  )
  .build();

When To Use Extractors Instead

Use an agent output schema when the workflow needs agent behavior: tools, history, context, or multi-turn reasoning.

Use an extractor when the job is only converting input text into typed data.