Skip to main content
LLMs generate text. Applications need data structures. Structured outputs bridge this gap—define a schema (Pydantic in Python, Zod or Effect Schema in TypeScript), and the Dedalus SDK ensures responses conform with full type safety. This is essential for building reliable applications. Instead of parsing free-form text and hoping for the best, you get validated objects that your code can trust.

Extract typed data

Define a schema. Call .parse(). Get validated objects.

Advanced

This section is a reference you can skim and come back to. It’s organized as a progression:
  1. Client .parse() (non-streaming, typed output)
  2. Client .stream() (streaming, typed output)
  3. Runner response_format (typed output inside an agent/tool loop)
  4. Schemas & patterns (optional fields, nested models, enums/unions)
  5. Structured tool calls (when you need deterministic tool calling)

Client API (reference)

The client provides three methods for structured outputs:
  • .parse() - Non-streaming with type-safe schemas
  • .stream() - Streaming with type-safe schemas (context manager)
  • .create() - Dict-based schemas only

TypeScript setup

TypeScript schema helpers are optional peer dependencies. Install the validator you want to use:

.parse() (non-streaming)

This is the same pattern as the progressive example above, shown again in a more “API-reference” style.

.stream() (streaming)

Use this when you want streaming UX and a typed final result.
Streaming helpers differ by language:
  • Python: use .stream(...) as a context manager and read typed stream events.
  • TypeScript: stream tokens with create({ stream: true, ... }), then validate the final JSON with Zod/Effect.

Optional Fields

Use Optional[T] in Python, .nullable() in Zod, or Schema.NullOr(...) in Effect for nullable fields:
With OpenAI strict mode, every field must be required. Model “optional” values as nullable.
Avoid Schema.optional(...) for structured outputs—use Schema.NullOr(...) instead.

Schemas & patterns

Nested Models

Structured Tool Calls (advanced)

Define type-safe tools with automatic argument parsing:
If you need deterministic tool calling, set tool_choice to one of the object variants: { type: 'auto' } (model decides), { type: 'any' } (require a tool call), { type: 'tool', name: 'search_events' } (require a specific tool), { type: 'none' } (disable tools). Passing the OpenAI string form (e.g. tool_choice: 'required') will fail schema validation with a 422.
Tool parameters must be an object schema (use Schema.Struct({ ... })).

Enums and Unions

DedalusRunner API

The Runner supports response_format with automatic schema conversion:

.create() vs .parse() vs .stream()

.create() expects a plain JSON Schema object. Don’t pass a Pydantic model, Zod schema, or Effect schema directly.
“Streaming + typed output” is language-dependent: - Python: .stream(...) yields typed events and a typed final snapshot. - TypeScript: stream tokens and validate the final JSON with Zod/Effect.

Error Handling

Supported Models

The Dedalus SDK’s .parse() and .stream() methods work across all providers. Schema enforcement varies: Strict Enforcement (CFG-based, schema guarantees):
  • openai/* - Context-free grammar compilation
  • xai/* - Native schema validation
  • fireworks_ai/* - Native schema validation (select models)
  • deepseek/* - Native schema validation (select models)
Best-Effort (schema sent for guidance, no guarantees):
  • 🟡 google/* - Schema forwarded to generationConfig.responseSchema
  • 🟡 anthropic/* - Prompt-based JSON generation (~85-90% success rate)
For google/* and anthropic/* models, always validate parsed output and implement retry logic.

Provider Examples

You can use .parse() and .stream() with models from any provider. In practice, you only change model—everything else stays the same. For a full list of model IDs, see the providers guide.

Quick Reference

Python (Pydantic)

TypeScript (Zod)

TypeScript (Effect Schema)

Zod Helpers

Effect Helpers

If you still use @effect/schema, schemas from @effect/schema/Schema also work with helpers/effect.You still need to install effect (the Dedalus SDK uses effect/JSONSchema and effect/Schema for conversion + validation).Prefer effect/Schema for new code.

Next steps

  • Stream output: Streaming — Improve UX for long tool/MCP runs
  • Route across models: Handoffs — Use fast/strong models by phase
  • See patterns: Use Cases — Structured extraction workflows
Connect these docs programmatically to Claude, VSCode, and more via MCP for real-time answers.
Last modified on June 30, 2026