Structured Output

easy5 minstructured-output.ts

You need typed JSON from the model — a support ticket classified into fields your code can switch on — not free text.

What it shows

  • Set responseFormat: { type: 'json_schema', schema } with a Zod schema
  • Read the parsed, validated value from result.structured

The code

structured-output.ts
import { Agent, Cogitator } from '@cogitator-ai/core';
import { z } from 'zod';

const apiKey = process.env.GOOGLE_API_KEY;
if (!apiKey) throw new Error('Set GOOGLE_API_KEY');

const ticketSchema = z.object({
  category: z.enum(['billing', 'bug', 'feature-request', 'other']),
  urgency: z.enum(['low', 'medium', 'high']),
  summary: z.string(),
  customerEmail: z.string().optional(),
});

const cog = new Cogitator({ llm: { providers: { google: { apiKey } } } });

const triage = new Agent({
  name: 'ticket-triage',
  model: 'google/gemini-3.5-flash-lite',
  instructions: 'Classify the support message. Leave out customerEmail when the message has no email address.',
  responseFormat: { type: 'json_schema', schema: ticketSchema },
  temperature: 0,
});

const result = await cog.run(triage, {
  input:
    'Hi, I was charged twice for my Pro plan this month and need a refund ASAP. — dana@example.com',
});

const ticket = result.structured as z.infer<typeof ticketSchema> | undefined;
if (!ticket) throw new Error(`The model did not return a valid ticket: ${result.output}`);

console.log(`${ticket.category} / ${ticket.urgency}: ${ticket.summary}`);
console.log('Reply to:', ticket.customerEmail ?? '(no email)');

await cog.close();

Run it

install · bash
pnpm add @cogitator-ai/core zod
EnvironmentGOOGLE_API_KEY
run · bash
GOOGLE_API_KEY=your-key npx tsx structured-output.ts

Learn more