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:- Client
.parse()(non-streaming, typed output) - Client
.stream()(streaming, typed output) - Runner
response_format(typed output inside an agent/tool loop) - Schemas & patterns (optional fields, nested models, enums/unions)
- 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.
TypeScript: same example using Effect Schema
TypeScript: same example using Effect Schema
.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
UseOptional[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.
TypeScript (Effect): nullable fields
TypeScript (Effect): nullable fields
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:TypeScript: tool parameters with Effect Schema
TypeScript: tool parameters with Effect Schema
Schema.Struct({ ... })).Enums and Unions
DedalusRunner API
The Runner supportsresponse_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)
- 🟡
google/*- Schema forwarded togenerationConfig.responseSchema - 🟡
anthropic/*- Prompt-based JSON generation (~85-90% success rate)
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
Using @effect/schema (deprecated upstream)
Using @effect/schema (deprecated upstream)
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
Streaming
Improve UX for long tool/MCP runs
Handoffs
Use fast/strong models by phase
Use Cases
Structured extraction workflows
