
Guaranteed JSON From Claude: Two Native API Patterns That Never Need a Retry Loop
Chris Harper
3 min read
Aug 6, 2026 · 20:02 UTC
The Claude API offers two orthogonal structured-output patterns — output_config JSON schema mode for constrained text responses and strict:true tool definitions for schema-valid tool inputs — that together eliminate JSON parse failures from agentic pipelines.
What you'll be able to do after this:
- Get parseable JSON from Claude every time without try/except retry loops
- Guarantee tool call inputs match your schema exactly via grammar-constrained sampling
- Combine both patterns to build reliable agentic pipelines where Claude calls tools AND returns structured data
The two patterns
Pattern 1 controls what Claude says (its text response). Pattern 2 controls what Claude does (its tool call parameters). Both are orthogonal — use either or both together.
Pattern 1: output_config JSON schema (constrained text responses)
Pass an output_config block with a json_schema format. The API compiles your schema into a grammar and samples tokens only from schema-valid continuations — the response is always valid JSON matching your schema.
import anthropic, json
client = anthropic.Anthropic()
schema = {
"type": "object",
"properties": {
"sentiment": {"type": "string", "enum": ["positive", "negative", "neutral"]},
"confidence": {"type": "number", "minimum": 0, "maximum": 1},
"key_phrases": {"type": "array", "items": {"type": "string"}, "maxItems": 5}
},
"required": ["sentiment", "confidence", "key_phrases"],
"additionalProperties": False
}
response = client.messages.create(
model="claude-sonnet-4-6-20260901",
max_tokens=512,
output_config={
"format": {
"type": "json_schema",
"json_schema": {
"name": "sentiment_result",
"schema": schema
}
}
},
messages=[{"role": "user", "content": "Analyze sentiment: 'The new API is incredibly fast and docs are clear.'"}]
)
result = json.loads(response.content[0].text)
# {"sentiment": "positive", "confidence": 0.95, "key_phrases": ["incredibly fast", "docs are clear"]}
# sentiment is always "positive", "negative", or "neutral" — no parse error possible
Tradeoff: complex schemas with many nested objects produce larger grammars that take longer to compile on the first call. Keep schemas focused; subsequent calls with the same schema benefit from server-side caching.
Pattern 2: strict:true tool use (guaranteed tool call parameters)
Add "strict": true as a top-level property in a tool definition. When Claude calls that tool, its input always matches your input_schema — no coercion, no extra keys, no missing required fields.
tool = {
"name": "create_task",
"description": "Create a task in the task management system",
"strict": True,
"input_schema": {
"type": "object",
"properties": {
"title": {"type": "string", "maxLength": 100},
"priority": {"type": "integer", "minimum": 1, "maximum": 5},
"assignee_id": {"type": "string", "pattern": "^usr_[a-z0-9]+$"}
},
"required": ["title", "priority"],
"additionalProperties": False
}
}
response = client.messages.create(
model="claude-sonnet-4-6-20260901",
max_tokens=256,
tools=[tool],
messages=[{"role": "user", "content": "Create a high-priority task: 'Fix the auth bug', assigned to usr_abc123."}]
)
for block in response.content:
if block.type == "tool_use" and block.name == "create_task":
task_data = block.input
# task_data["priority"] is always 1-5, title always ≤ 100 chars — guaranteed
Combining both patterns
You can set strict: true on tools AND pass output_config in the same request. Claude calls tools with guaranteed-valid parameters and returns a structured final response — the right shape for multi-step agentic workflows.
response = client.messages.create(
model="claude-sonnet-4-6-20260901",
max_tokens=1024,
tools=[tool], # strict: True
output_config={
"format": {
"type": "json_schema",
"json_schema": {"name": "summary", "schema": summary_schema}
}
},
messages=[{"role": "user", "content": "Create tasks for the auth bug fix and return a summary."}]
)
# Claude calls create_task (guaranteed-valid inputs) then returns structured summary JSON
This pattern is available on Claude Sonnet 4.5+, Opus 4.5+, Haiku 4.5+, and later.
Sources: Structured outputs — Claude Platform Docs · Strict tool use — Claude Platform Docs · How to implement tool use — Claude Platform Docs