Structured output
End-to-end path: Zod schema → IR → model JSON → Rust parse. Use model(provider).generateObject when you need a typed object, not free text.
Happy path
structured.ts
typescript
import { model, mock } from "@monorch/ai";
import { z } from "zod";
const handle = model(
mock([{ text: JSON.stringify({ city: "Lisbon", tempC: 22 }) }]),
);
const Weather = z.object({
city: z.string(),
tempC: z.number(),
});
const weather = await handle.generateObject({
prompt: "Weather in Lisbon as JSON",
output: Weather,
});
// weather: { city: "Lisbon", tempC: 22 }Pipeline
- 1. Zod
- You pass a Zod schema as
output. Supported checks include stringemail/uuid/url/regexand numberint. Exoticrefine/transform/pipethrowSCHEMA_UNSUPPORTED— keep schemas in the common subset (objects, primitives, arrays, enums, optional, union + those checks). - 2. zodToIr
- Monorch compiles the schema to IR for the Rust validator (
zodToIris also a public export if you need IR for tools). - 3. Model text
- The provider is asked for JSON-only. Empty text →
EMPTY_OUTPUT. Unparseable →INVALID_JSON(including markdown fences that still do not contain valid JSON — never a rawSyntaxError). - 4. Rust parse
getRuntime().parse(ir, json)validates. Failure →VALIDATION_FAILEDwithdetails.errors.
Failure cases
structured-fail.ts
typescript
import { AiError, model, mock } from "@monorch/ai";
import { z } from "zod";
const Schema = z.object({ n: z.number() });
try {
await model(mock([{ text: "not-json" }])).generateObject({
prompt: "x",
output: Schema,
});
} catch (e) {
// e instanceof AiError && e.code === "INVALID_JSON"
}
try {
await model(mock([{ text: '{"n":"nope"}' }])).generateObject({
prompt: "x",
output: Schema,
});
} catch (e) {
// e instanceof AiError && e.code === "VALIDATION_FAILED"
}Gaps vs “full” structured output
This path validates after generation. It does not bind provider-native JSON-schema / tool-choice constrained decoding. For OpenAI-compatible hosts that support response formats, you can still pass provider options on raw generate / stream and then validate with the same Zod schema yourself — generateObject is the batteries-included loop for mock + OpenAI-compatible text JSON.
Error catalog: Errors & failure modes.