Extraction is different from summarization in one crucial way: the output is consumed by software, not people. A summary that is 95% right is useful; a JSON payload that is 95% valid crashes your pipeline. That changes how you prompt — and, more importantly, it means the format guarantee should come from the API, not from polite requests in prose.
Let the schema do the formatting
The old pattern — "respond only with JSON in this exact shape" — still works, but it is no longer the right tool. Claude's structured outputs feature accepts a JSON Schema in the request via output_config: {"format": {"type": "json_schema", "schema": {...}}} and constrains generation to match it. Anthropic's docs note that objects should set additionalProperties: false. Structured outputs are generally available on the Claude API and supported on Vertex AI, Bedrock (a subset), Microsoft Foundry, and Claude Platform on AWS.
With the schema handling shape, your prompt only has to handle meaning: what each field represents, where in the document it typically appears, and what to do when it is absent. That division of labor is the core extraction pattern.
from anthropic import AnthropicBedrockMantle
client = AnthropicBedrockMantle(aws_region="us-east-1")
schema = {"type": "object", "additionalProperties": False,
"properties": {"invoice_number": {"type": "string"},
"total": {"type": "string"},
"currency": {"type": "string"}},
"required": ["invoice_number", "total", "currency"]}
msg = client.messages.create(
model="anthropic.claude-sonnet-5", max_tokens=1024,
output_config={"format": {"type": "json_schema", "schema": schema}},
messages=[{"role": "user", "content": f"Extract from:\n{invoice_text}"}],
)
In Python, the SDK's client.messages.parse() helper accepts a Pydantic model directly, auto-transforms schema constraints the API doesn't support, and validates the response client-side.
Know the schema's limits
Per the official docs, some JSON Schema features return a 400 error: recursive schemas, external $ref, numeric constraints like minimum/maximum, and string length constraints like minLength/maxLength. So a rule like "total must be positive" cannot live in the schema — it belongs in the prompt, with validation code as the backstop. The same docs flag two edge cases worth handling: a refusal comes back as HTTP 200 with stop_reason: "refusal", and output truncated at max_tokens may be incomplete JSON — retry with a higher limit.
Prompt patterns that raise field accuracy
Describe fields, don't just name them. "invoice_number: the vendor's invoice identifier, usually top-right, formats like INV-2026-0042" beats a bare field name. Anthropic's guidance to add context — explain why and how an instruction applies — pays off directly here.
Define the null case. The most common extraction failure is a confident value for a field that isn't in the document. Say explicitly: "If a field is not present in the document, return an empty string — never infer or compute a value."
Show 3–5 worked examples. The official best practices recommend 3–5 relevant, diverse examples wrapped in <example> tags. For extraction, make at least one example a messy document with missing fields, so Claude sees the null-handling rule in action.
Document first, instructions last. As with summarization, place long source text at the top of the prompt and the extraction request at the end; Anthropic reports up to 30% quality improvement from this ordering on long inputs.
output_config.format returns a 400 error. If you need both extracted fields and source locations, run extraction as structured output and ask for evidence snippets as ordinary string fields in the schema.Scaling it up
Extraction backlogs (say, 40,000 historical invoices) are the textbook case for batch processing: on the Claude API and Claude Platform on AWS, the Message Batches API runs up to 100,000 requests per batch at 50% of standard prices, with most batches finishing in under an hour. On Bedrock and Vertex AI, use those platforms' own cloud-native batch inference instead. PDFs work as inputs across all platforms, though Bedrock and Google Cloud accept base64 only.
Where to go next
For a deeper look at schema-constrained JSON, see structured extraction to JSON and the structured outputs explainer. For validating what comes back, read output validation patterns.