katas-defensive-structured-extraction

Extract structured data from free text using forced tool_choice with JSON Schema contracts.

Updated Jun 28, 2026
One-click install
npx skills add https://github.com/JaviMontano/claude-plugins --skill katas-defensive-structured-extraction-javimontano
Or copy as Structured Prompt for Agent▼
Please help me install this Agent Skill.
Skill: katas-defensive-structured-extraction
Source: https://github.com/JaviMontano/claude-plugins/tree/main/plugins/claude-native-toolkit/skills/katas-defensive-structured-extraction
Command: npx skills add https://github.com/JaviMontano/claude-plugins --skill katas-defensive-structured-extraction-javimontano

SYSTEM DOCUMENTATION & REQUIREMENTS

What problem does it solve? Asking a model to "return JSON" in prose and parsing it with json.loads produces silent hallucinations: invented fields, empty-string defaults, and out-of-domain enum values that look like valid JSON and corrupt downstream pipelines. This Skill converts those silent failures into explicit states by forcing tool_choice with a JSON Schema contract. ## Core Features & Use Cases - Forced tool_choice extraction: The model always invokes the extraction tool and never returns prose, so output always conforms to the declared schema. - Defensive schema design: Declares only source-guaranteed fields as required, models optionals as nullable unions, and gives every enum an escape valve ('other'/'unclear') plus a details field. - Use Case: Extracting invoice_id, currency, status, and due_date from a free-text invoice email where the currency (GBP) is outside the enum and the due date is missing — the pattern returns currency 'other' with details 'GBP' and due_date null instead of lying or defaulting to ''. ## Quick Start Ask the assistant to extract invoice fields from the provided source text using a forced extraction tool with a JSON Schema that marks only source-guaranteed fields as required.

Frequently Asked Questions about katas-defensive-structured-extraction

High-intent search queries and answers about installing and using this skill.

FAQPage Schema
How do I extract structured data from text with the Claude API reliably?▼

Define a tool with an input_schema describing the fields, then call messages.create with tool_choice set to that tool so the model must populate the schema instead of answering in prose. This guarantees the output conforms to the declared structure.

How should I model optional fields in a JSON Schema for extraction?▼

Model optionals as nullable unions such as {"type":["string","null"]}, and dates as {"type":["string","null"],"format":"date"}. Only mark a field required if it is always present in the source; otherwise the model will hallucinate a value.

What should I do when a value falls outside my enum options?▼

Add an escape value like 'other' or 'unclear' to every enum, plus a companion details field to capture the actual value. For example, currency 'other' with currency_other_details 'GBP' preserves the source value without forcing a wrong classification.

Why is parsing model output with json.loads risky?▼

Prose-based JSON prompting produces silent hallucinations: invented fields, empty-string defaults, and out-of-domain enum values that still parse as valid JSON. The corrupted data then flows downstream undetected, so schema-bound tool use is safer.

When should I not force tool_choice for extraction?▼

Do not force tool_choice when the model must decide among several tools or when a hybrid response mixing text and extraction is legitimate. Forcing a single tool in those cases removes valid routing behavior.