Context
#168 emits Anthropic tool-call schemas (the input_schema JSON + a tools.ts barrel) from the IR. This PRD adds the calling code: the scaffold every structured-output pipeline reinvents — call client.messages.create, force tool_choice, parse the result, validate with Zod, return typed data.
Problem statement
For every entity that needs extraction, AI engineers hand-write the same wrapper function. The boilerplate is mechanical and the failure modes (forgot tool_choice, missed Zod validation, untyped return) are common.
Solution
Opt in via an IR flag (project-level + per-type, mirroring #168). For each opted-in entity, emit frames/<TypeName>.frame.ts exporting extract<TypeName>(sourceText, client) => Promise<<TypeName>>. The function imports the entity's Zod schema and tool definition from #168, forces tool_choice to that tool, runs Schema.parse on the response, and throws ExtractionError on validation failure. Default system prompt is a one-liner with a TODO comment encouraging users to tune in a non-generated wrapper file.
Open questions
- Cross-flag enforcement:
frame: true requires both project-level Anthropic tools enabled and the type's own tool: true. IR validation error vs UI gating — probably both, but verify the error message points users to the right next step.
- Prompt tuning surface: how does the user override the default system prompt without forking the generated extractor? A non-generated wrapper file pattern is the cleanest answer, but worth confirming when there's a real use case.
Out of scope
- A frame barrel / registry — add later if users want a single import point.
- Streaming variants of the extractor.
- Multi-shot / retry-on-validation-failure logic. Single-shot default; users layer retry themselves.
- Non-Anthropic backends — separate work if demanded.
Relationship to other PRDs
Context
#168 emits Anthropic tool-call schemas (the
input_schemaJSON + atools.tsbarrel) from the IR. This PRD adds the calling code: the scaffold every structured-output pipeline reinvents — callclient.messages.create, forcetool_choice, parse the result, validate with Zod, return typed data.Problem statement
For every entity that needs extraction, AI engineers hand-write the same wrapper function. The boilerplate is mechanical and the failure modes (forgot
tool_choice, missed Zod validation, untyped return) are common.Solution
Opt in via an IR flag (project-level + per-type, mirroring #168). For each opted-in entity, emit
frames/<TypeName>.frame.tsexportingextract<TypeName>(sourceText, client) => Promise<<TypeName>>. The function imports the entity's Zod schema and tool definition from #168, forcestool_choiceto that tool, runsSchema.parseon the response, and throwsExtractionErroron validation failure. Default system prompt is a one-liner with a TODO comment encouraging users to tune in a non-generated wrapper file.Open questions
frame: truerequires both project-level Anthropic tools enabled and the type's owntool: true. IR validation error vs UI gating — probably both, but verify the error message points users to the right next step.Out of scope
Relationship to other PRDs