Skilllibrary structured-output-pipelines
Enforce structured output from LLMs using JSON schema constraints, Pydantic model binding, function calling extraction, and retry/repair loops for malformed responses. Use when an LLM must produce typed JSON, fill a schema, or return structured data that downstream code parses. Do not use for free-form text generation, summarization, or chat responses where structure is not required.
git clone https://github.com/merceralex397-collab/skilllibrary
T=$(mktemp -d) && git clone --depth=1 https://github.com/merceralex397-collab/skilllibrary "$T" && mkdir -p ~/.claude/skills && cp -r "$T/11-ai-llm-runtime-and-integration/structured-output-pipelines" ~/.claude/skills/merceralex397-collab-skilllibrary-structured-output-pipelines && rm -rf "$T"
11-ai-llm-runtime-and-integration/structured-output-pipelines/SKILL.mdPurpose
Use this skill to reliably extract structured data from LLM outputs — define JSON schemas or Pydantic models, choose the right extraction method (native JSON mode, function calling, or prompted extraction), implement retry and repair loops for malformed responses, and validate outputs before passing them to downstream code.
When to use this skill
Use this skill when:
- an LLM must return valid JSON conforming to a specific schema (API responses, data extraction, form filling)
- defining Pydantic models that bind to LLM outputs via
,instructor
, orlangchain
function callingopenai - using OpenAI's
or Anthropic's tool-use for structured extractionresponse_format: { type: "json_schema" } - implementing function calling where the LLM selects and parameterizes tool calls
- building retry/repair loops that re-prompt the LLM when output fails validation
- extracting structured entities from unstructured text (names, dates, addresses, product attributes)
- debugging malformed LLM JSON output (trailing commas, unquoted keys, truncated responses)
Do not use this skill when
- the LLM output is free-form text (summaries, creative writing, chat replies)
- the task is defining API request/response schemas without LLM involvement (use standard API design practices)
- the task is data validation for user input in a web form (use standard validation libraries)
- a narrower active skill already owns the problem
Operating procedure
-
Define the target schema. Write a Pydantic model (v2 preferred) or JSON Schema that describes every field the LLM must produce. Use
on every field — these descriptions become part of the extraction prompt. Mark optional fields withField(description="...")
and provide defaults. UseOptional[T]
orLiteral
for constrained-choice fields.Enum -
Choose the extraction method.
- Native JSON mode (OpenAI
, Anthropic tool-use): Guarantees syntactically valid JSON. Use when the provider supports it and schema complexity is moderate.response_format - Function calling (OpenAI functions/tools, Anthropic tool-use): The LLM "calls a function" with typed arguments matching your schema. Best for action-oriented extraction (tool selection, API parameter filling).
- Prompted extraction with parsing: Include the JSON schema in the prompt and parse the response. Use as fallback for models without native JSON mode. Wrap with
and Pydanticjson.loads()
.model_validate() - Instructor library: Wraps OpenAI/Anthropic clients with automatic Pydantic validation and retry. Use for rapid prototyping and when retry logic is needed.
- Native JSON mode (OpenAI
-
Craft the extraction prompt. Place the schema definition or example output in the system prompt. Include 1–2 few-shot examples of input → expected JSON output. Explicitly instruct the model to output only JSON with no surrounding text, markdown fences, or explanation.
-
Implement validation. Parse the raw LLM response with
. Validate against the Pydantic model usingjson.loads()
. Catchmodel_validate(data)
and extract the specific field failures for the repair prompt.ValidationError -
Build the retry/repair loop. On validation failure, construct a repair prompt: include the original input, the malformed output, and the specific validation errors. Re-send to the LLM with instructions to fix only the errors. Limit retries to 3 attempts. If all retries fail, return a structured error object rather than crashing.
-
Handle edge cases.
- Truncated JSON: If the response hit the
limit, increase the limit or simplify the schema.max_tokens - Extra fields: Use
in Pydantic to silently drop unexpected fields.model_config = ConfigDict(extra="ignore") - Markdown wrapping: Strip
fences before parsing if the model wraps output despite instructions.```json - Null vs missing: Distinguish between
values and missing keys — use Pydantic'snull
to detect.model_fields_set
- Truncated JSON: If the response hit the
-
Test with diverse inputs. Run 20+ representative inputs through the full pipeline. Verify that every field populates correctly, edge cases (empty lists, null optionals, enum boundaries) are handled, and the retry loop activates and recovers on at least 80% of initial failures.
Decision rules
- Use native JSON mode or function calling over prompted extraction whenever the provider supports it — parsing reliability is dramatically higher.
- Always validate with Pydantic, not just
— syntactically valid JSON can still violate the schema.json.loads() - Limit schema depth to 3 levels of nesting — deeper schemas increase extraction failure rates.
- Use
instead ofLiteral["option1", "option2"]
for any field with a known finite set of values.str - Set
to at least 2x the expected output size to prevent truncation.max_tokens - When retry count exceeds 2 for >10% of requests, simplify the schema or add more few-shot examples rather than increasing retry budget.
Output requirements
— complete schema with field descriptions and constraintsPydantic Model or JSON Schema
— system prompt, few-shot examples, and output instructionsExtraction Prompt
— LLM call → parse → validate → retry loop → output or errorPipeline Code
— 10+ test cases covering happy path, edge cases, and expected failuresValidation Test Suite
— what happens when all retries fail (fallback value, error response, alert)Error Handling Spec
References
Read these only when relevant:
references/json-schema-best-practices.mdreferences/function-calling-patterns.mdreferences/retry-repair-strategies.md
Related skills
llm-integrationtool-use-agentsrag-retrieval
Anti-patterns
- Parsing LLM output with regex instead of
+ Pydantic — brittle and fails on edge cases.json.loads() - Defining schemas without field descriptions — the LLM has no guidance on what each field should contain.
- Retrying with the exact same prompt on failure — the model will produce the same error; include the validation error in the retry prompt.
- Using
type for every field and parsing later — loses the schema constraint benefit and pushes validation downstream.str - Embedding the schema in the user message instead of the system prompt — reduces reliability on multi-turn conversations.
Failure handling
- If the LLM consistently returns extra text around the JSON, add a post-processing step that extracts the first
or{...}
block before parsing.[...] - If a specific field fails validation repeatedly, add a targeted few-shot example that demonstrates the correct format for that field.
- If function calling returns
arguments, verify the function schema matches the model's expected format and that required fields are marked correctly.null - If the retry loop cannot recover, log the original input, all attempts, and validation errors, then return a typed error object with
and the failure reason.success: false