AutoGen Tutorial (TypeScript): parsing structured output for advanced developers
This tutorial shows how to make an AutoGen TypeScript agent return structured data you can reliably parse, validate, and feed into downstream systems. You need this when free-form LLM text is too risky for production workflows like claims triage, KYC extraction, or ticket classification.
What You'll Need
- •Node.js 18+ installed
- •A TypeScript project with
ts-nodeortsx - •
autogen-coreandautogen-agentchatpackages - •
zodfor schema validation - •An OpenAI API key in
OPENAI_API_KEY - •Basic familiarity with AutoGen agents and model clients
Install the dependencies:
npm install autogen-core autogen-agentchat zod
npm install -D typescript tsx @types/node
Set your environment variable:
export OPENAI_API_KEY="your-key-here"
Step-by-Step
- •Start by defining the exact shape you want back from the model. In production, don’t parse natural language if you can avoid it; define a schema first and force the model to fill it.
import { z } from "zod";
export const ClaimSummarySchema = z.object({
claimId: z.string(),
riskLevel: z.enum(["low", "medium", "high"]),
summary: z.string(),
recommendedAction: z.string(),
});
export type ClaimSummary = z.infer<typeof ClaimSummarySchema>;
- •Create an assistant agent that is instructed to emit only JSON matching your schema. The trick is not just prompting for JSON, but making the output contract explicit enough that you can validate it before using it.
import { AssistantAgent } from "autogen-agentchat";
import { OpenAIChatCompletionClient } from "autogen-core";
import { ClaimSummarySchema } from "./schema.js";
const modelClient = new OpenAIChatCompletionClient({
model: "gpt-4o-mini",
});
export const agent = new AssistantAgent({
name: "claim_summarizer",
modelClient,
systemMessage: `
You are a claims analyst.
Return ONLY valid JSON matching this schema:
${JSON.stringify(ClaimSummarySchema.shape, null, 2)}
Do not wrap the JSON in markdown.
`,
});
- •Send a real input and parse the response as JSON. If the model returns malformed output, fail fast and log the raw payload so you can inspect prompt drift or model regressions.
import { agent } from "./agent.js";
import { ClaimSummarySchema } from "./schema.js";
async function main() {
const result = await agent.run({
task: "Claim ID C-10492. Customer reports water damage in kitchen after pipe burst. Photos show moderate damage. No prior claims.",
});
const rawText = result.messages.at(-1)?.content ?? "";
const parsed = JSON.parse(rawText);
const validated = ClaimSummarySchema.parse(parsed);
console.log("Validated output:", validated);
}
main().catch((err) => {
console.error(err);
process.exit(1);
});
- •Add a defensive parser for production use. In real systems, you want one place that handles JSON extraction, schema validation, and error reporting instead of scattering parsing logic across handlers.
import { ZodError } from "zod";
import { ClaimSummarySchema } from "./schema.js";
export function parseClaimSummary(rawText: string) {
let parsed: unknown;
try {
parsed = JSON.parse(rawText);
} catch (error) {
throw new Error(`Model returned invalid JSON: ${rawText}`);
}
try {
return ClaimSummarySchema.parse(parsed);
} catch (error) {
if (error instanceof ZodError) {
throw new Error(`JSON did not match schema: ${error.message}`);
}
throw error;
}
}
- •Wire the parser into your app flow and persist only validated data. This keeps downstream services insulated from hallucinated fields, wrong types, and partial responses.
import { agent } from "./agent.js";
import { parseClaimSummary } from "./parse.js";
async function run() {
const result = await agent.run({
task: "Claim ID C-10492. Customer reports water damage in kitchen after pipe burst. Photos show moderate damage. No prior claims.",
});
const rawText = result.messages.at(-1)?.content ?? "";
const claimSummary = parseClaimSummary(rawText);
console.log("Persisting record:", {
claimId: claimSummary.claimId,
riskLevel: claimSummary.riskLevel,
summary: claimSummary.summary,
recommendedAction: claimSummary.recommendedAction,
});
}
run();
Testing It
Run the script a few times with slightly different claim descriptions and confirm that the output still validates against the same schema. If the model starts returning extra prose or malformed JSON, your parser should reject it immediately instead of letting bad data move downstream.
For a stronger test, deliberately change one field in the schema, such as making riskLevel accept only "high", and verify that validation fails on lower-risk outputs. Also test a broken response by mocking rawText with invalid JSON so you know your error path is deterministic.
In production, log three things every time parsing fails:
- •The raw model output
- •The prompt version
- •The schema version
That gives you enough signal to debug whether the failure came from prompt changes, model behavior drift, or a breaking contract change.
Next Steps
- •Add retry logic that reprompts the agent when JSON parsing fails
- •Move from
JSON.parseto a stricter structured-output strategy if your model/client supports it - •Store schemas alongside versioned business rules so downstream consumers can evolve safely
Keep learning
- •The complete AI Agents Roadmap — my full 8-step breakdown
- •Free: The AI Agent Starter Kit — PDF checklist + starter code
- •Work with me — I build AI for banks and insurance companies
By Cyprian Aarons, AI Consultant at Topiax.
Want the complete 8-step roadmap?
Grab the free AI Agent Starter Kit — architecture templates, compliance checklists, and a 7-email deep-dive course.
Get the Starter Kit