Context
Contexture already emits Convex schema, Zod, JSON Schema, schema-index, and per-table CRUD from the IR. This adds another emit target: Anthropic tool-call schemas — the input_schema JSON every AI engineer currently hand-authors when wiring up tool calls or structured outputs.
Problem statement
Hand-authoring input_schema JSON for every tool duplicates shape information that already lives in the IR. Every IR change has to be reflected by hand; the tool-call schema drifts most often because it's pure JSON nobody runs locally.
Solution
Opt in via an IR flag (project-level on/off plus per-type opt-in for granularity, since not every entity is a tool). For each opted-in entity, emit <TypeName>.tool.json with the input_schema as Anthropic's API expects, plus a tools.ts barrel exporting { name, description, input_schema } triples ready to drop into client.messages.create({ tools: [...] }). Description comes from the IR's type-level description; name is snake_case(typeName).
Open questions
- Refs vs inline: does Anthropic's tool-call
input_schema support $ref / $defs? Verify against current API docs at implementation time. Default to inlining nested types; fall back to $ref only if explicitly supported.
- Empty-description handling: validation warning (current default) versus block emission entirely. Lean toward warning — descriptions are encouraged but not load-bearing for the API.
Out of scope
Relationship to other PRDs
Context
Contexture already emits Convex schema, Zod, JSON Schema, schema-index, and per-table CRUD from the IR. This adds another emit target: Anthropic tool-call schemas — the
input_schemaJSON every AI engineer currently hand-authors when wiring up tool calls or structured outputs.Problem statement
Hand-authoring
input_schemaJSON for every tool duplicates shape information that already lives in the IR. Every IR change has to be reflected by hand; the tool-call schema drifts most often because it's pure JSON nobody runs locally.Solution
Opt in via an IR flag (project-level on/off plus per-type opt-in for granularity, since not every entity is a tool). For each opted-in entity, emit
<TypeName>.tool.jsonwith theinput_schemaas Anthropic's API expects, plus atools.tsbarrel exporting{ name, description, input_schema }triples ready to drop intoclient.messages.create({ tools: [...] }). Description comes from the IR's type-level description; name issnake_case(typeName).Open questions
input_schemasupport$ref/$defs? Verify against current API docs at implementation time. Default to inlining nested types; fall back to$refonly if explicitly supported.Out of scope
Relationship to other PRDs
tools.tsbarrel and the<TypeName>.tool.jsonfiles this emitter produces.