Por que Saídas Estruturadas Superam a Formatação de JSON Baseada em Prompt
Todo desenvolvedor que integrou um LLM em um pipeline já escreveu um prompt como "responda apenas com JSON válido, sem nenhum outro texto."
Essa instrução geralmente funciona.
"Geralmente" é o problema.
Saídas estruturadas resolvem isso movendo a garantia de JSON do prompt para a própria requisição da API, usando um parâmetro chamado output_config.format. Em vez de pedir gentilmente ao Claude para formatar sua resposta de uma certa maneira, você declara a forma exata que requer, e a API restringe a geração para que a resposta a conforme. Esta página explica por que essa distinção importa, o que muda na forma como você constrói com a API Claude depois de confiar nela, e onde suas garantias param.
Resumo
- Ideia Central:
output_config.formatrestringe a resposta do Claude no momento da geração para corresponder a um JSON Schema que você fornece, em vez de depender da redação do prompt para solicitar JSON. - Por que Importa: Pedidos de JSON baseados em prompt são probabilísticos. O modelo ainda pode adicionar um preâmbulo, envolver o JSON em blocos de markdown, omitir um campo ou produzir sintaxe inválida sob alguns inputs, e cada um desses modos de falha precisa ser capturado e retentado pelo seu próprio código.
- Conceitos Chave: JSON Schema, output_config.format, resposta válida de acordo com o schema, client.messages.parse, modelo Pydantic, truncamento de max_tokens.
- Quando Usar: Qualquer hora que o código downstream analisar a resposta do modelo como dados - pipelines de extração, fluxos de trabalho adjacentes a ferramentas, preenchimento de formulários, classificação com campos estruturados, ou qualquer lugar onde uma resposta malformada quebraria um programa em vez de apenas parecer estranha para um leitor humano.
- Limitações / Trade-offs: Saídas estruturadas não suportam todas as construções de JSON Schema, e uma resposta pode ainda estar incompleta se atingir o limite de
max_tokensantes que o JSON seja fechado. - Tópicos Relacionados: Design de JSON Schema, validação Pydantic, uso estrito de ferramentas, tratamento de truncamento.
Fundamentos
Antes que as saídas estruturadas existissem como um recurso em nível de requisição, o padrão padrão para obter JSON de um LLM era inteiramente baseado em prompt.
Você escrevia um prompt de sistema instruindo o modelo a "apenas gerar JSON válido correspondendo a esta forma", talvez incluísse um exemplo, e então analisava qualquer texto que voltasse com json.loads().
Isso funciona na maioria das vezes, que é exatamente por que é arriscado.
O modelo está gerando texto token por token, e "responda apenas com JSON" é uma preferência que ele geralmente honra, não uma regra que ele não pode quebrar.
Sob certas entradas, especialmente conversas mais longas, instruções ambíguas ou dados de casos de borda, o modelo pode adicionar uma explicação de uma linha antes do JSON, envolver o objeto em um bloco de código markdown, usar um nome de campo que é próximo, mas não exatamente o que você pediu, ou deixar um valor de fora inteiramente.
Cada uma dessas saídas ainda "parece" que o modelo tentou cooperar, mas cada uma delas quebra uma chamada json.loads() ingênua.
Saídas estruturadas invertem essa relação.
Em vez de descrever a forma desejada em prosa, você a descreve com um JSON Schema, uma especificação legível por máquina da forma exata de campos, tipos e propriedades exigidas que sua resposta deve ter.
Você passa esse schema no campo output_config.format da sua requisição, e a API restringe o próprio processo de geração para que o conteúdo retornado se conforme ao schema.
O prompt não está mais fazendo o trabalho de imposição.
Um modelo mental simples: formatação baseada em prompt é como pedir a um colega para preencher um formulário corretamente descrevendo o formulário para ele em palavras. Saídas estruturadas é como entregar o formulário real para ele, com campos que só aceitam o tipo certo de entrada. Um depende de interpretação; o outro restringe o espaço de respostas possíveis antes que a geração ocorra.
from anthropic import Anthropic
client = Anthropic()
schema = {
"type": "object",
"properties": {
"name": {"type": "string"},
"is_urgent": {"type": "boolean"},
},
"required": ["name", "is_urgent"],
"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": "Extraia o assunto do ticket e a urgência."}],
)Note o que está faltando no prompt: nenhum "responda apenas com JSON", nenhuma instrução de formatação, nenhum exemplo de saída. O schema faz esse trabalho.
Mecânicas e Interações
A diferença prática entre as duas abordagens se mostra mais claramente em como as falhas se comportam.
Com JSON baseado em prompt, uma falha é uma falha completa de análise. Seu código chama json.loads() em uma string que pode conter texto introdutório, comentário final, ou um bloco de markdown, e se qualquer um desses estiver presente, a análise falha e você não tem nada utilizável. Você está então no negócio de escrever lógica defensiva de remoção de strings: regex para encontrar o primeiro { e o último }, remover blocos ```json, capturar e tentar novamente em JSONDecodeError. Esse código defensivo é um imposto que você paga em cada integração, para sempre, porque a garantia subjacente nunca melhorou - você apenas ficou melhor em limpar depois dela.
Com output_config.format, a restrição é aplicada durante a geração, não depois dela. A API está impondo o schema token por token à medida que a resposta é produzida, então uma resposta bem-sucedida é válida de acordo com o schema por construção, não por sorte. Isso remove uma categoria inteira de bugs de análise do seu código, porque não há mais um resultado de "o modelo quase acertou" para lidar - a resposta ou satisfaz o schema, ou algo mais aconteceu (truncamento, recusa, ou um erro genuíno da API) e você lida com isso como sua própria condição distinta e detectável em vez de texto ruidoso.
É aqui que o helper de nível superior do SDK Python também importa. client.messages.create(...) ainda retorna o conteúdo bruto da resposta que você extrairia e desserializaria. client.messages.parse(...) vai um passo adiante: ele retorna um objeto já validado e já analisado, comumente suportado por um modelo Pydantic que você define junto com o schema. A distinção é a mesma de output_config.format em si - mover o trabalho de "escrever código para verificar isso" para "deixar o framework garantir isso".
from pydantic import BaseModel
from anthropic import Anthropic
class Ticket(BaseModel):
name: str
is_urgent: bool
client = Anthropic()
response = client.messages.parse(
model="claude-sonnet-5",
max_tokens=1024,
output_config={"format": {"type": "json_schema", "schema": Ticket.model_json_schema()}},
messages=[{"role": "user", "content": "Ticket: servidor caiu, por favor ajude rápido!"}],
)
ticket = response.parsed_output # uma instância Ticket validada, não uma string brutaHá uma sutileza que vale a pena internalizar aqui: a imposição do schema acontece na camada da API, mas não é mágica que apaga todos os modos de falha. Duas condições ainda exigem seu próprio tratamento. Primeiro, a resposta pode ser truncada se atingir max_tokens antes que o objeto JSON seja fechado - o texto parcial não será um JSON válido, mesmo que a API estivesse tentando fielmente seguir seu schema. Segundo, nem toda construção que você pode querer expressar em JSON Schema é suportada pelo motor de imposição da API; existem limites em tipos de campo, tratamento de enum e certas restrições de schema, o que significa que o próprio design do schema se torna uma habilidade com seu próprio material de referência (veja Relacionados abaixo) em vez de "apenas escreva qualquer JSON Schema que você quiser".
Considerações Avançadas e Aplicações
Uma vez que você confia em saídas estruturadas, a forma do seu código de integração muda de uma maneira que se acumula em uma base de código, não apenas em uma única requisição.
A formatação de JSON baseada em prompt empurra a lógica de validação para downstream e a duplica: cada local de chamada que espera JSON de volta precisa de sua própria análise, seu próprio tratamento de erros, sua própria verificação "o modelo realmente seguiu as instruções desta vez". Saídas estruturadas centralizam essa garantia na definição do schema. Mude o schema uma vez, e cada resposta que o usa é validada da mesma forma, pela mesma camada de imposição, com os mesmos modos de falha.
Isso importa mais exatamente nos lugares onde o JSON baseado em prompt é mais arriscado: pipelines de produção com volume, onde uma taxa de falha de análise de baixa porcentagem de um dígito é invisível em testes, mas cara em escala; e sistemas downstream (bancos de dados, outros serviços, componentes de UI) que falharão ou corromperão o estado com entrada malformada em vez de apenas exibir uma string feia para um humano.
Vale a pena ser preciso sobre o que "garantia" significa aqui, no entanto. output_config.format garante que a resposta, se gerada com sucesso, esteja em conformidade com seu schema. Não garante que a resposta seja correta no sentido de ser factualmente certa ou completa - o modelo ainda pode colocar um valor plausível, mas errado, em um campo corretamente tipado. Saídas estruturadas resolvem um problema de confiabilidade sintática, não um problema de precisão semântica. Você ainda precisa de suas próprias verificações de correção, revisão humana ou verificações downstream; você apenas não precisa mais se defender contra sintaxe malformada em cima disso.
| Abordagem | Força | Fraqueza | Melhor Ajuste |
|---|---|---|---|
| Requisição de JSON baseada em prompt | Nenhuma superfície de API para aprender, funciona com qualquer modelo | Probabilístico; saída malformada requer análise defensiva e retentativas | Protótipos rápidos, uso manual de baixo volume |
output_config.format (bruto) | Garante JSON válido de acordo com o schema no nível da API | Você ainda analisa o texto retornado sozinho | Quando você quer a garantia, mas não um objeto tipado |
client.messages.parse() com Pydantic | Schema garantido e um objeto tipado validado em uma chamada | Requer a definição de modelos Pydantic; camada de conveniência específica do SDK Python | A maioria das integrações Python de produção que extraem dados estruturados |
Conceitos Errôneos Comuns
- "Se eu pedir claramente o suficiente no prompt, o modelo sempre retornará JSON válido." - Prompts mais claros genuinamente reduzem as taxas de falha, mas não podem eliminá-las, porque o modelo ainda está gerando texto livre e qualquer processo de geração tem alguma chance de desviar. Saídas estruturadas removem a "chance" restringindo a própria geração.
- "Saídas estruturadas significam que não preciso mais validar nada." - A API garante que sua resposta corresponda à forma do schema. Ela não garante que o conteúdo seja factualmente correto. Você ainda precisa de suas verificações de precisão.
- "Posso apenas descrever qualquer forma de JSON que eu quiser, não importa quão aninhada ou restrita." - O recurso de saídas estruturadas suporta um subconjunto significativo, mas limitado, do JSON Schema. Certas construções (como algumas restrições de intervalo numérico) não são impostas, e schemas muito complexos ou recursivos podem não ser suportados de forma alguma.
- "Uma resposta válida de acordo com o schema nunca pode ser truncada." - Pode. Se a resposta atingir o limite de
max_tokensantes que o modelo termine de escrever o JSON, o que retorna é uma string incompleta, mesmo que o modelo estivesse cooperando com o schema durante todo o tempo em que estava gerando.
FAQs
output_config.format é um novo endpoint de API ou um parâmetro na API de Mensagens existente?
- É um parâmetro (
output_config) nas mesmas chamadasmessages.create()/messages.parse()que você já usa. - Nenhum endpoint ou cliente separado é necessário.
Eu ainda preciso de json.loads() se usar output_config.format com client.messages.create()?
- Sim -
client.messages.create()ainda retorna o conteúdo da resposta como texto; a garantia é que o texto é um JSON válido de acordo com o schema, não que já está desserializado. - Use
client.messages.parse()em vez disso se você quiser um objeto já analisado e validado de volta.
Qual é a diferença entre client.messages.create() e client.messages.parse() para saídas estruturadas?
create()retorna a resposta bruta; você extrai o conteúdo de texto e o analisa sozinho.parse()valida a resposta contra seu schema (frequentemente um modelo Pydantic) e retorna um objeto analisado pronto para uso.
Saídas estruturadas podem garantir que os dados sejam factualmente corretos, não apenas bem formados?
- Não. A garantia é sintática: a resposta corresponde aos tipos e campos exigidos pelo seu schema.
- O modelo ainda pode preencher um campo corretamente tipado com um valor impreciso; verificações de correção ainda são sua responsabilidade.
Por que um recurso válido de acordo com o schema ainda produziria JSON quebrado às vezes?
- A causa mais comum é atingir o limite de
max_tokensantes que o objeto JSON seja fechado, o que trunca a saída no meio da estrutura. - Detectar isso e tentar novamente com um limite de tokens maior é uma parte padrão de uma integração de saídas estruturadas.
Cada palavra-chave do JSON Schema funciona com output_config.format?
- Não - existem limites nos tipos de campo suportados, tratamento de enum e certas restrições de schema.
- Verifique os tipos de campo e a referência de restrições antes de projetar qualquer coisa além de um objeto simples plano ou levemente aninhado.
Isso é útil apenas para tarefas de extração de dados?
- Extração (contratos, e-mails, formulários) é o caso de uso mais comum, mas qualquer fluxo de trabalho onde o código downstream consome a saída do modelo como dados se beneficia - classificação com campos estruturados, geração de formulários, resumos estruturados alimentando outro sistema.
Como isso é diferente de apenas usar um schema de ferramenta/chamada de função?
- Schemas de uso de ferramentas restringem a entrada para uma chamada de ferramenta que o modelo decide fazer.
output_config.formatrestringe a resposta da mensagem inteira em si, independentemente de qualquer ferramenta estar envolvida ou não - e os dois podem ser combinados para que tanto a resposta quanto quaisquer parâmetros de chamada de ferramenta sejam garantidos como válidos.
Eu preciso de Pydantic para usar saídas estruturadas em Python?
- Não, Pydantic não é necessário - você pode escrever manualmente o dicionário JSON Schema e usar
client.messages.create(). - Pydantic é uma conveniência comumente emparelhada com
client.messages.parse()porqueModel.model_json_schema()gera o schema para você e você obtém uma instância validada de volta.
O que acontece se o modelo não puder produzir uma saída que corresponda ao meu schema?
- Esta é uma condição separada do truncamento - uma recusa ou incapacidade de cumprir surge como seu próprio resultado distinto em vez de um blob JSON parcialmente formado, que é uma das razões pelas quais saídas estruturadas são mais fáceis de lidar programaticamente do que requisições de JSON em texto livre.
Devo parar de escrever instruções "retorne apenas JSON" em meus prompts agora?
- Você pode removê-las como um requisito -
output_config.formaté o que impõe a forma. - Manter uma breve instrução sobre a intenção da extração (não a formatação) ainda pode ajudar o modelo a produzir melhores valores, apenas não melhor sintaxe.
Relacionados
- Noções Básicas de Saídas Estruturadas - solicite uma resposta de JSON Schema e analise-a com client.messages.parse.
- Definindo um JSON Schema para output_config.format - como escrever o schema que esta página assume que você usará.
- Referência de Tipos de Campo e Restrições de Saída Estruturada - quais construções de JSON Schema são realmente suportadas.
- Tratando Saída JSON Malformada ou Truncada - o modo de falha de truncamento que esta página sinaliza como ainda sendo sua responsabilidade.
Versões de Stack: Escrito contra a linha de modelos Claude atual a partir de ~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.