Context
PR #95 added responseFormat?: ResponseFormat to GenerateTextParams and StreamTextParams to close #93. This works but couples structured-output concerns to the text-generation API.
Vercel AI SDK takes a different approach: separate top-level generateObject() / streamObject() functions with first-class typing for the schema input.
What Vercel does differently
Separate functions:
generateObject({ model, schema, prompt }) → returns { object: T }
streamObject({ model, schema }) → returns { partialObjectStream, elementStream }
Flexible schema input — accepts:
- Zod schemas (
z.object({...}))
- JSON Schema (
{ type: 'object', ... })
- Standard Schema spec
- Custom validators
output discriminator — 'object' | 'array' | 'enum' | 'no-schema' with array mode auto-emitting elementStream for streaming arrays.
partialObjectStream — emits parsed partial JSON deltas as the response streams in.
Tradeoffs vs our current approach
|
Param-on-generateText (us) |
Split functions (Vercel) |
| Backwards compat |
✅ no API change |
❌ new public API |
| Type complexity |
Branching in result types |
Clean per-function types |
| Streaming UX |
User parses text manually |
partialObjectStream ready-to-use |
| Schema input |
OpenAI shape only |
Zod + JSON Schema + custom |
| Discoverability |
Hidden in config |
Top-level export |
Proposal
Open question for discussion. Three paths:
- Keep current —
responseFormat param is fine, add Zod accept-and-convert (zod-to-json-schema) as a small DX win
- Add
generateObject() / streamObject() alongside — both APIs work, share the same provider plumbing
- Deprecate
responseFormat in v3 — full Vercel parity, breaking change
My lean: option 2. Lets us catch up on DX without breaking anyone.
cc whoever owns SDK direction
Context
PR #95 added
responseFormat?: ResponseFormattoGenerateTextParamsandStreamTextParamsto close #93. This works but couples structured-output concerns to the text-generation API.Vercel AI SDK takes a different approach: separate top-level
generateObject()/streamObject()functions with first-class typing for the schema input.What Vercel does differently
Separate functions:
generateObject({ model, schema, prompt })→ returns{ object: T }streamObject({ model, schema })→ returns{ partialObjectStream, elementStream }Flexible schema input — accepts:
z.object({...})){ type: 'object', ... })outputdiscriminator —'object' | 'array' | 'enum' | 'no-schema'with array mode auto-emittingelementStreamfor streaming arrays.partialObjectStream— emits parsed partial JSON deltas as the response streams in.Tradeoffs vs our current approach
partialObjectStreamready-to-useProposal
Open question for discussion. Three paths:
responseFormatparam is fine, add Zod accept-and-convert (zod-to-json-schema) as a small DX wingenerateObject()/streamObject()alongside — both APIs work, share the same provider plumbingresponseFormatin v3 — full Vercel parity, breaking changeMy lean: option 2. Lets us catch up on DX without breaking anyone.
cc whoever owns SDK direction