Structured output¶
Ask for JSON, get a validated object back.
Declaring the shape¶
In the prompt file:
name: extract_invoice
description: Extracts structured invoice fields from raw text
version: 1.0.0
messages:
- role: system
template: Extract invoice fields. Return only the requested fields.
- role: user
template: "{{ document }}"
input_schema:
document: str
output_schema:
type: object
required: [invoice_number, total, currency]
properties:
invoice_number: { type: string }
total: { type: number }
currency:
type: string
enum: [USD, EUR, GBP]
from promptkit import load_prompt, run_structured
prompt = load_prompt("extract_invoice.yaml")
result = run_structured(prompt, {"document": raw_text}, engine)
result.value.invoice_number # validated
result.completion.usage # the underlying Completion
Or a Pydantic model¶
from pydantic import BaseModel
class Invoice(BaseModel):
invoice_number: str
total: float
currency: str
result = run_structured(prompt, {"document": raw_text}, engine, output_model=Invoice)
This is the better path in typed code: result.value is an Invoice, and your type
checker knows it. An explicit output_model overrides the prompt's output_schema.
What happens¶
- If the engine advertises
json_mode, the schema is sent as a native structured-output request. - Otherwise a schema instruction is appended as a final system message.
- The response is parsed. JSON is recovered from bare output, fenced blocks, and JSON embedded in prose.
- On a parse or validation failure, the model is re-prompted with its previous answer
and the exact error, up to
max_parse_retries(default 2).
Each retry emits a ParseRetried event.
Set max_parse_retries=0 to fail on the first bad response.
When it gives up¶
from promptkit.errors import OutputValidationError
try:
result = run_structured(prompt, inputs, engine, output_model=Invoice)
except OutputValidationError as e:
print(e) # what was wrong
print(e.errors()) # Pydantic's structured detail, when the failure was validation
Async¶
Notes¶
output_schemamust describe an object. A top-level array is rejected at load.AnthropicEnginedoes not advertisejson_mode, so it uses the instruction path. Anthropic's native structured output is tool-shaped, and tool calling is out of scope.- Retries cost tokens. The repair message includes the previous answer, so a retry is
more expensive than the first attempt. Keep
max_parse_retrieslow and your schema small.