Definindo um JSON Schema para output_config.format
output_config.format só garante uma resposta válida em termos de schema se o schema que você fornece estiver bem formado.
Busque em todas as páginas da documentação
output_config.format só garante uma resposta válida em termos de schema se o schema que você fornece estiver bem formado.
Esta página cobre exatamente como escrever esse schema: os dois campos que todo objeto precisa, como construí-lo manualmente versus gerá-lo a partir de um modelo Pydantic, e como aninhamento, arrays e enums se encaixam.
O schema que você passa para output_config.format é um JSON Schema padrão, com duas convenções que a API Claude exige em cada objeto: um array required listando cada propriedade e additionalProperties: false.
Acertar esses dois em cada objeto aninhado é a fonte mais comum de erros de schema.
Você pode escrever o schema como um dicionário Python simples ou gerá-lo automaticamente a partir de um BaseModel Pydantic com .model_json_schema().
Ambas as abordagens produzem o mesmo formato de comunicação; Pydantic apenas economiza o trabalho de manter um dicionário e um tipo analisado em sincronia manualmente.
Nem toda palavra-chave JSON Schema é suportada, então um schema que parece razoável ainda pode ser rejeitado ou ignorado silenciosamente em algumas partes - veja a referência de tipos de campo e restrições para a lista completa.
Cartão de receita de referência rápida - pronto para copiar e colar.
from anthropic import Anthropic
client = Anthropic()
schema = {
"type": "object",
"properties": {
"title": {"type": "string"},
"priority": {"type": "string", "enum": ["low", "medium", "high"]},
},
"required": ["title", "priority"],
"additionalProperties": False,
}
response = client.messages.create(
model="claude-sonnet-5",
max_tokens=1024,
output_config={"format": {"type": "json_schema", "schema": schema}},
messages=[{"role": "user", "content": "Resuma este relatório de bug como um ticket."}],
)Quando usar isso:
from pydantic import BaseModel, Field
from anthropic import Anthropic
class BugReport(BaseModel):
title: str = Field(description="Um resumo curto e de uma linha do bug")
priority: str = Field(description="Um de: low, medium, high")
steps_to_reproduce: list[str] = Field(description="Lista ordenada de passos para reproduzir")
affected_component: str
client = Anthropic()
response = client.messages.parse(
model="claude-sonnet-5",
max_tokens=1024,
output_config={
"format": {"type": "json_schema", "schema": BugReport.model_json_schema()}
},
messages=[{
"role": "user",
"content": (
"Transforme isto em um relatório de bug: A página de checkout falha quando um usuário "
"aplica um código de desconto com caracteres especiais. Acontece sempre "
"no módulo de pagamentos. Faça login, adicione um item ao carrinho, aplique um código como "
"'SAVE#10', clique em checkout. Isso bloqueia todas as compras, então é alta prioridade."
),
}],
)
report: BugReport = response.parsed_output
print(report.title)
print(report.priority)
for step in report.steps_to_reproduce:
print("-", step)O que isso demonstra:
Field(description=...) em um modelo Pydantic se torna a description do JSON Schema que o modelo lê ao decidir o que colocar em cada campo.list[str] se torna automaticamente um array de itens string - nenhum schema de array manual é necessário.response.parsed_output retorna uma instância real de BugReport, não um dicionário, então o acesso a atributos e verificadores de tipo funcionam.output_config.format recebe um wrapper type: "json_schema" em torno do seu objeto schema; o schema em si é um documento JSON Schema padrão.required informa à API que cada propriedade listada deve estar presente na resposta; omitir uma propriedade de required a torna opcional, o que raramente é o que você quer para uma extração fixa.additionalProperties: false fecha o objeto - sem ele, a API (e qualquer validador rigoroso que você adicione por cima) não pode garantir que o modelo não adicionará campos extras e não solicitados.required quanto additionalProperties: false são necessários em todo objeto do schema, incluindo objetos aninhados - defini-los apenas no nível superior não se aplica em cascata.| Abordagem | O que você escreve | O que você obtém |
|---|---|---|
| Dicionário escrito à mão | Um dict Python simples que corresponde à sintaxe JSON Schema | Controle total, mas você mantém o schema e qualquer tipo downstream separadamente |
Pydantic model_json_schema() | Uma subclasse BaseModel com campos tipados | Schema gerado automaticamente; response.parsed_output retorna uma instância do seu modelo |
Schemas escritos à mão são úteis para formas muito simples e únicas, ou quando você não quer uma dependência Pydantic. Para qualquer coisa com mais de dois ou três campos, um modelo Pydantic mantém o schema e o tipo de dados da sua aplicação de se separarem à medida que a forma evolui.
from pydantic import BaseModel
class LineItem(BaseModel):
sku: str
quantity: int
class Order(BaseModel):
customer_name: str
items: list[LineItem]
# Order.model_json_schema() produz um objeto de nível superior com uma propriedade de array "items"
# onde a palavra-chave "items" aponta para o schema do objeto LineItem aninhado -
# cada nível ainda precisa de seu próprio required + additionalProperties: false, que
# Pydantic gera automaticamente para você.properties, items, $ref/$def), que é exatamente o que Pydantic emite para modelos aninhados.required e additionalProperties: false; Pydantic lida com isso corretamente por conta própria, mas se você escrever schemas aninhados manualmente, adicione ambos a cada objeto aninhado você mesmo.from pydantic import BaseModel
class Ticket(BaseModel):
subject: str
urgency: str
schema = Ticket.model_json_schema()
print(schema["required"]) # ['subject', 'urgency']
print(schema["additionalProperties"]) # Falsemodel_json_schema() do Pydantic define required e additionalProperties: false automaticamente para um BaseModel padrão sem campos opcionais - esta é uma razão para preferi-lo a escrever o dicionário manualmente.Optional[str] ou com um valor padrão é excluído de required pelo Pydantic - se você quiser que todos os campos sejam obrigatórios na resposta, evite padrões e Optional em campos que importam.response.parsed_output de client.messages.parse(...) é tipado como uma instância do modelo que você passou, então IDEs e verificadores de tipo entendem a forma sem anotação extra.| Campo | Tipo | Descrição |
|---|---|---|
output_config.format.type | str | Sempre "json_schema" para este recurso. |
output_config.format.schema | dict | O documento JSON Schema descrevendo a forma de resposta exigida. |
schema.required | list[str] | Todos os nomes de propriedades que devem estar presentes na resposta, por objeto. |
schema.additionalProperties | bool | Deve ser False em todo objeto do schema. |
additionalProperties: false em um objeto aninhado. Definir isso apenas no nível superior deixa os objetos internos abertos. Correção: verifique se todo objeto aninhado no schema também carrega additionalProperties: false - se você estiver escrevendo schemas manualmente, é fácil esquecer isso em um campo profundamente aninhado.properties mas não em required. O campo se torna opcional, então o modelo pode omiti-lo, e seu código precisa verificar defensivamente sua presença. Correção: inclua todo campo que você realmente precisa em required, e torne os campos opcionais apenas quando a resposta genuinamente pode não tê-los.enum e aninhamento simples.Optional para uma tarefa de extração "precisa ter tudo". Campos opcionais/com valor padrão saem de required automaticamente, o que enfraquece a garantia que você realmente queria. Correção: mantenha os campos não opcionais sem padrão quando todos os valores devem estar presentes na resposta.priority: "high" ainda pode ser válido em termos de schema e factualmente incorreto. Correção: mantenha sua própria validação ou etapa de revisão para correção, independente da conformidade do schema.| Alternativa | Use Quando | Não Use Quando |
|---|---|---|
| Dicionário de schema escrito à mão | A forma é pequena, fixa e você não quer uma dependência Pydantic | A forma tem mais do que alguns campos ou evolui com frequência |
Pydantic model_json_schema() | Você já tem (ou quer) uma classe Python tipada para os dados | Você precisa do schema em um contexto não Python e não pode compartilhar o modelo |
Ferramenta rigorosa input_schema (strict: true) | Você quer restringir os parâmetros de uma chamada de ferramenta em vez da resposta final da mensagem | Você está restringindo a resposta de texto geral do assistente, não a invocação de uma ferramenta |
| Apenas instruções JSON baseadas em prompt | Prototipagem rápida onde a saída ocasionalmente malformada é aceitável | Qualquer pipeline de produção que analisa a resposta programaticamente |
model_json_schema() define ambos automaticamente para um BaseModel sem campos opcionais.False em cada objeto do schema.required e o modelo pode incluí-lo ou não.required em vez de tornar os campos opcionais por hábito.{"type": "string", "enum": ["low", "medium", "high"]}enum é um construto bem suportado e é a maneira padrão de restringir um campo a um conjunto fixo de valores.properties para objetos aninhados e items para arrays funcionam, e Pydantic gera isso automaticamente para modelos aninhados e campos list[...].Optional) é excluído de required pelo Pydantic.Optional nesses campos.required / additionalProperties: false.output_config.format restringe toda a resposta da mensagem; o input_schema de uma ferramenta (com strict: true) restringe os parâmetros de uma única chamada de ferramenta.{
"type": "object",
"properties": {"answer": {"type": "string"}},
"required": ["answer"],
"additionalProperties": False,
}BaseModel do Pydantic é o caminho de conveniência comum porque .model_json_schema() produz o schema diretamente.dataclass simples não tem isso integrado - você escreveria o schema de dicionário manualmente se não quiser uma dependência Pydantic.Versões da Stack: Escrito contra a linha de modelos Claude atual em ~junho de 2026 - Claude Fable 5, Claude Opus 4.8, Claude Sonnet 5 (o padrão) e Claude Haiku 4.5 - e o SDK oficial
anthropicpara Python (última versão 0.x). Nomes de modelos, versões de SDK e preços mudam rapidamente - verifique os detalhes atuais em platform.claude.com/docs antes de confiar neles.
Revisado por Chris St. John·Última atualização: 13 de jul. de 2026