structured-output
Skill33 starsChanged 22 days agoMITView on GitHub
Use when an LLM must return machine-readable data. Covers schema design for models, native structured-output modes, validation and repair, and extraction that survives contact with messy input. Trigger on "llm returns invalid json", "extract fields from these emails", "classify tickets into fixed categories". Do not use for scraping web pages — see the web-data-extraction skill; for general prompt quality, see the prompt-engineering skill.
We split this skill into the rules it gives an agent
3 rules. 0 are common, 3 are distinctive, and 0 are very specific to this project.
0
Common
Most of the 3 edited versions we read keep these.
3
Distinctive
This author's own choices. Worth a look.
0
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Distinctive: line 56
Always allow null, and say what null means.
- Distinctive: line 57
Ask for a confidence score, and act on it.
- Distinctive: line 137
If accuracy is critical, extract twice with different prompts and flag disagreements for review.
“Common” is measured: kept by at least 6 in 10 of the 3 edited versions of this file we could read. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
Structured Output
Purpose
Get reliably parseable, correctly typed data out of a language model. The naive approach — asking for JSON in the prompt and calling json.loads — fails often enough to be a production incident.
When to Use
- Extracting fields from unstructured text.
- Classification with a fixed set of labels.
- Any LLM output consumed by code rather than read by a human.
- A pipeline that fails intermittently on parse errors.
Capabilities
- Schema design that models follow reliably.
- Native structured output: JSON schema mode, tool calling, constrained decoding.
- Validation, repair, and retry.
- Confidence and abstention: letting the model say it does not know.
- Extraction from long, messy, or partially irrelevant documents.
Inputs
- The target schema and the semantics of each field.
- The input text and how messy it actually is.
- What should happen when a field is genuinely absent.
Outputs
- Validated, typed objects.
- An explicit representation of absence, distinct from a guess.
- A measured extraction accuracy per field.
Workflow
- Use the API's native mechanism — JSON schema mode or tool calling constrains the decoder so that malformed output is structurally impossible. Asking for JSON in prose does not.
- Design the schema for a model, not a database — Descriptive field names, enums instead of free strings, and a description on every field explaining what belongs in it. The schema is documentation the model reads.
- Make absence representable — A nullable field with a clear meaning. Without one, the model will invent a plausible value rather than leave it out, because that is what the schema demanded.
- Validate, then repair, then fail — Parse against the schema. On a semantic failure (a valid date that is in the future when it must be past), send the error back for one repair attempt, then give up cleanly.
- Measure per field — Aggregate extraction accuracy hides the one field that is wrong 40% of the time.
Best Practices
- Structured-output mode makes the output parseable, not correct. It guarantees the shape; it guarantees nothing about the values. Validate the semantics separately.
- An enum is more reliable than a string with instructions. If there are five valid categories, the schema should permit exactly five values.
- Deeply nested schemas degrade accuracy. Flatten where you can; a model fills a flat object of ten fields far more reliably than a three-level tree.
- Always allow null, and say what null means. Forcing a value into every field is how you get hallucinated data that looks perfectly well-formed.
- Ask for a confidence score, and act on it. Below a threshold, route to a human rather than writing a guess to the database.
- Extract the source span alongside the value when the extraction must be auditable. It makes verification possible and hallucination visible.
Examples
A schema that guides the model:
from pydantic import BaseModel, Field
from typing import Literal
class ExtractedInvoice(BaseModel):
invoice_number: str | None = Field(
description="The invoice number exactly as printed. Null if not present. "
"Do not construct one from the filename or the date."
)
total_cents: int | None = Field(
description="The final amount due, in minor units (cents/pence). "
"Use the TOTAL, not the subtotal and not any line item."
)
currency: Literal["USD", "EUR", "GBP"] | None = Field(
description="ISO code, inferred from the currency symbol or explicit code. "
"Null if genuinely ambiguous — do not assume USD."
)
due_date: date | None
confidence: float = Field(
ge=0, le=1,
description="Your confidence that every extracted field is correct. "
"Below 0.7 if the document is unclear, is not an invoice, "
"or if you had to guess any field."
)
source_quotes: dict[str, str] = Field(
description="For each non-null field, the exact text from the document "
"that supports it. This is used for audit."
)Extraction with validation, one repair attempt, and a human fallback:
async def extract(document: str) -> ExtractedInvoice | HumanReview:
result = await model.complete(
EXTRACTION_PROMPT.format(document=document),
response_format=ExtractedInvoice, # native constrained decoding
)
# Structurally valid by construction. Now check that it is semantically sane.
errors = validate_semantics(result, document)
if errors:
# One repair attempt, with the specific errors fed back.
result = await model.complete(
REPAIR_PROMPT.format(document=document, previous=result, errors=errors),
response_format=ExtractedInvoice,
)
errors = validate_semantics(result, document)
if errors or result.confidence < 0.7:
return HumanReview(document=document, draft=result, reasons=errors)
return result
def validate_semantics(inv: ExtractedInvoice, document: str) -> list[str]:
errors = []
if inv.total_cents is not None and inv.total_cents <= 0:
errors.append("total_cents must be positive")
if inv.due_date and inv.due_date.year < 2000:
errors.append(f"due_date {inv.due_date} is implausible")
# The strongest check available: every quoted span must exist in the source.
for field, quote in inv.source_quotes.items():
if quote not in document:
errors.append(f"source_quote for '{field}' does not appear in the document — "
f"this field is likely hallucinated")
return errorsNotes
- The
source_quotescheck above is the most effective anti-hallucination mechanism available for extraction: a value the model cannot quote from the document is a value it invented, and a simple substring check catches it. - Confidence scores from LLMs are poorly calibrated in absolute terms but useful relative to each other. Set the threshold by measuring on real data, not by intuition.
- If accuracy is critical, extract twice with different prompts and flag disagreements for review. It doubles the cost and catches most of what a single pass misses.
Other versions3 projects use a version of this.
Word for word · 0
None found.
Edited · 0
None found.
Wrote their own version · 3
- nahid-sparktales/agent-dispatcher★ 59same name
- mykaarma/kaarma-skills★ 4same name
- Zavelinski/structured-output★ 0same name
How matches are found. Word for word: the exact same text. Edited: shares passages with this file (“99% same” means 99% of its five-word phrases also appear here; 10% or more counts). Their own version: similar meaning, or, weakest, the same name. We can’t tell which project had it first. Projects are counted among the 200 most-starred candidates, and mentions are links to the repository we found, up to 50 per site, so both counts are a floor.
In this repository137 other files it gives its agents.
- agent-instructionsSkill
- agent-memorySkill
- hooksSkill
- plugin-developmentSkill
- skill-authoringSkill
- skill-reviewSkill
- slash-commandsSkill
- subagentsSkill
- agent-designSkill
- context-engineeringSkill
- fine-tuningSkill
- llm-cost-optimizationSkill
- llm-evaluationSkill
- llm-integrationSkill
- mcp-serverSkill
- ml-pipelineSkill
- model-selectionSkill
- prompt-engineeringSkill
- ragSkill
- api-designSkill
- background-jobsSkill
- cachingSkill
- djangoSkill
- event-driven-architectureSkill
- fastapiSkill
- graphqlSkill
- microservicesSkill
- nestjsSkill
- realtime-websocketsSkill
- spring-bootSkill
- competitive-analysisSkill
- lead-researchSkill
- product-analysisSkill
- resumeSkill
- user-researchSkill
- database-performanceSkill
- data-modelingSkill
- data-qualitySkill
- pandasSkill
- postgresSkill
- sparkSkill
- brand-guidelinesSkill
- generative-artSkill
- themingSkill
- ui-reviewSkill
- visual-designSkill
- architecture-decisionsSkill
- bug-fix-protocolSkill
- cli-developmentSkill
- code-reviewSkill
- debuggingSkill
- design-patternsSkill
- domain-modelingSkill
- git-workflowSkill
- legacy-modernizationSkill
- refactoringSkill
- repository-explorationSkill
- simple-designSkill
- system-designSkill
- aws-cdkSkill
- The first 60 shown.
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

