> ## Documentation Index
> Fetch the complete documentation index at: https://ai.aidalinfo.fr/llms.txt
> Use this file to discover all available pages before exploring further.

# Structured outputs

> Validate agent responses with Zod and the `structuredOutput` option.

Use `structuredOutput` to force the agent to respect a `zod` schema. Always build the schema with `Output.object({ schema: z.object(...) })` so OpenAI/Google models get the right hints and TypeScript infers your payload automatically.

```ts theme={null}
import { Output } from "@ai_kit/core";
import { z } from "zod";

const personSpec = Output.object({
  schema: z.object({
    name: z.string(),
    age: z.number().nullable().describe("Person age."),
    contact: z.object({
      type: z.literal("email"),
      value: z.string(),
    }),
    occupation: z.object({
      type: z.literal("employed"),
      company: z.string(),
      position: z.string(),
    }),
  }),
});

const structured = await assistant.generate({
  prompt: "Create a sample profile for a potential customer.",
  structuredOutput: personSpec,
});

console.log(structured.experimental_output);
// -> { name: "...", age: 32, contact: { ... }, occupation: { ... } }
```

* `Output.object` offers an ergonomic builder for the expected payload.
* Schema descriptions are forwarded to the model to boost accuracy.
* If parsing fails, the SDK throws—catch it to retry or log the error.

## Targeted extraction

```ts theme={null}
import { Agent, Output } from "@ai_kit/core";
import { z } from "zod";
import { google } from "@ai-sdk/google";

const siretOutput = Output.object({
  schema: z.object({
    siret: z
      .string()
      .length(14, "The SIRET must contain exactly 14 digits."),
  }),
});

const assistant = new Agent({
  name: "life-assistant",
  instructions: "Lifestyle assistant",
  model: google("gemini-2.5-flash"),
  tools: {
    google_search: google.tools.googleSearch({}),
  },
});

const result = await assistant.generate({
  prompt: "Find the SIRET of Aidalinfo.",
  structuredOutput: siretOutput,
});

console.log(result.experimental_output);
// -> { siret: "12345678901234" }
```

## Tips

* Prefer `agent.generate` for structured generation—streaming + schemas remains experimental.
* Log parsing errors to fine-tune prompts or trigger retries.
* Separate “strict” outputs (IDs, metadata) from free-form content (summaries, answers).

## Scaleway models

Scaleway’s OpenAI-compatible endpoint still validates schemas client-side. The SDK now infers `AgentStructuredOutput` straight from your Zod schema, so you can keep the exact same builder and pass it to Scaleway without extra generics:

```ts theme={null}
import { Agent, Output, scaleway } from "@ai_kit/core";
import { z } from "zod";

const codeSchema = Output.object({
  schema: z.object({
    language: z.string(),
    code: z.string(),
    explanation: z.string(),
  }),
});

const assistant = new Agent({
  name: "code-assistant",
  model: scaleway("qwen3-coder-30b-a3b-instruct"),
});

const result = await assistant.generate({
  prompt: "Generate a commented Python snippet.",
  structuredOutput: codeSchema,
});
```

Behind the scenes `codeSchema` is typed as `AgentStructuredOutput<typeof schema>`, keeping the Scaleway requirements and your DX identical to OpenAI/Google workflows.

> When you target a non-OpenAI provider **without tools**, AI Kit now goes straight to `generateObject`. Your original (text or multimodal) messages are enough to populate `experimental_output`; there’s no need to remind the model to “answer in JSON”.
