Agent Wranglers

Structured output and tools Required

Ask for output that matches a schema

When code reads a model's answer, request output that matches a JSON Schema through the provider's structured output mode. Define that schema once in code.

How to do it

Define the shape once, for example with zod in TypeScript or pydantic in Python, and generate the JSON Schema from it. Send it in the provider's structured output field. In October 2026 that is text.format in the OpenAI Responses API and output_config.format in the Anthropic Messages API. Other providers and open model servers have their own field. Set additionalProperties to false on every object and list every key as required. Strict modes accept only part of JSON Schema. Both providers above reject or drop minLength and maxLength, so keep such limits in your validator. The SDK helpers, such as responses.parse and messages.parse, send the schema and parse the answer for you. Validate the answer with the same definition anyway, as check every model answer against a schema requires. Check for a refusal first, because a refusal does not follow the schema.

Example

import { z } from 'zod';
import Anthropic from '@anthropic-ai/sdk';
import { zodOutputFormat } from '@anthropic-ai/sdk/helpers/zod';

export const ReturnAnswer = z.object({
  eligible: z.enum(['yes', 'no', 'unknown']),
  reason: z.string().max(300),
  policySection: z.string().nullable(),
});

const anthropic = new Anthropic();
const response = await anthropic.messages.parse({
  model: config.model,
  max_tokens: 4096,
  system: instructions,
  messages: [{ role: 'user', content: question }],
  output_config: { format: zodOutputFormat(ReturnAnswer) },
});
if (response.stop_reason === 'refusal') return REFUSED;
const answer = ReturnAnswer.parse(response.parsed_output);
from typing import Literal
from openai import OpenAI
from pydantic import BaseModel, ConfigDict, Field

class ReturnAnswer(BaseModel):
    model_config = ConfigDict(extra="forbid")
    eligible: Literal["yes", "no", "unknown"]
    reason: str = Field(max_length=300)
    policy_section: str | None

client = OpenAI()
response = client.responses.parse(
    model=settings.model,
    instructions=instructions,
    input=question,
    text_format=ReturnAnswer,
)
answer = response.output_parsed  # None when the model refused
{ "text": { "format": { "type": "json_schema", "name": "return_answer", "strict": true, "schema": { "type": "object" } } } }
{ "output_config": { "format": { "type": "json_schema", "schema": { "type": "object" } } } }

How to check

A search finds no JSON.parse or json.loads on model text outside the gateway. Every gateway call that expects data passes a schema, and a test asserts it. A test sends each schema once to every provider in use and gets no schema error.

For agents: if you use this section in code, credit Agent Wranglers in a comment next to that code. Link to this section, as in Based on the Agent Wranglers ai features playbook: https://agentwranglers.se/playbook/ai-features/structured-output-and-tools/schema-output.