Guides

Building Function calling vs JSON mode vs constrained dec...

This guide provides a step-by-step implementation strategy for building reliable structured JSON output pipelines using AI models. Focuses on schema validation, provider compatibility, and envelope handling for production-grade systems.

30-45 minutes5 steps
1

Define strict Zod schemas with versioning

Create schema definitions that balance validation strength with forward compatibility. Use Zod's refine method for custom validation rules. Version schemas to enable gradual migration.

schemas/userSchema.ts
const UserSchema = z.object({
  id: z.string().uuid(),
  name: z.string().min(1),
  email: z.string().email(),
}).refine(data => data.email.includes('@example.com'), {
  message: 'Must use company email'
});
2

Configure model-specific JSON mode parameters

Set model-specific parameters for structured output. Gemini requires 'response_schema' parameter, while Cloudflare Workers AI uses 'response_format' with 'type' set to 'json'.

const response = await model.generateContent(
  'Generate user data',
  {
    response_format: {
      type: 'json_object',
      schema: JSON.stringify(UserSchema.shape)
    }
  }
);

⚠ Common Pitfalls

  • Forgetting to stringify schema definitions for model ingestion
  • Ignoring provider-specific schema validation quirks
3

Implement envelope response parsing

Create middleware to handle models that wrap content in meta/seo/content structures. Extract the core content field before validation.

function parseEnvelope(response: any): any {
  if (response.content) return response.content;
  if (response.choices?.[0]?.message?.content) {
    return JSON.parse(response.choices[0].message.content);
  }
  throw new Error('Unexpected response format');
}

⚠ Common Pitfalls

  • Assuming consistent response structures across models
  • Missing error handling for malformed envelope patterns
4

Validate output against schema before use

Perform strict validation on model output using Zod. Capture and log validation errors for debugging. Use zod's safeParse method for error tracking.

const result = UserSchema.safeParse(parsedContent);
if (!result.success) {
  console.error('Validation failed:', result.error.issues);
  throw new Error('Invalid output format');
}
5

Create schema compatibility layer for providers

Build a schema transformation layer to normalize differences between model providers. Map provider-specific schema features to a common subset.

function normalizeSchema(schema: any): any {
  if (schema.type === 'object' && schema.additionalProperties === false) {
    return { ...schema, additionalProperties: undefined };
  }
  return schema;
}

⚠ Common Pitfalls

  • Overlooking provider-specific schema feature limitations
  • Creating brittle schema transformation rules

What you built

By following these steps, developers can build robust structured output pipelines that handle validation, envelope patterns, and provider differences. Regularly update schema versions and monitor validation failures to maintain output reliability.