O que mudou no Amazon Bedrock
A AWS anunciou suporte nativo a saídas estruturadas para todos os modelos Anthropic Claude disponíveis no Amazon Bedrock. O recurso funciona tanto no endpoint bedrock-runtime — acessado via Boto3 e APIs do Bedrock — quanto no endpoint bedrock-mantle, utilizado pela Messages API. Em ambos os casos, as respostas do modelo passam a ser Notação de Objeto JavaScript (JSON) rigorosamente compatíveis com o esquema definido pela aplicação.
Na prática, isso significa que desenvolvedores não precisam mais escrever código de validação, lógica de retentativa por falha de parsing ou pós-processamento para garantir que o modelo retornou os campos esperados. A conformidade com o esquema é garantida durante a própria geração dos tokens.
Como funciona a geração com restrições
A diferença fundamental em relação à abordagem anterior está em quando a conformidade é aplicada. Antes, a validação acontecia depois que o modelo já havia gerado a resposta — um processo probabilístico que podia falhar. Agora, o Amazon Bedrock utiliza decodificação restrita: o modelo simplesmente não produz tokens que violem o esquema fornecido. A geração de saída deixa de ser probabilística e passa a ser determinística em relação à estrutura.
O fluxo interno funciona assim:
- Validação do esquema: o Amazon Bedrock valida o esquema JSON fornecido contra o subconjunto suportado do JSON Schema Draft 2020-12.
- Compilação de gramática: para esquemas novos, o serviço compila um artefato de gramática. A primeira requisição pode ser ligeiramente mais lenta por conta dessa etapa.
- Cache de gramática: gramáticas compiladas ficam em cache por 24 horas, tornando requisições subsequentes mais rápidas. O cache é por conta AWS e é invalidado apenas quando a estrutura do esquema muda — alterações em nomes ou descrições de campos não invalidam o cache.
- Geração restrita: o modelo gera tokens que produzem JSON válido conforme o esquema.
Dois mecanismos complementares
A AWS disponibilizou dois mecanismos que cobrem cenários distintos:
- Formato de saída JSON Schema: controla a estrutura da resposta do modelo. Indicado para extração de dados, geração de relatórios e respostas de Interface de Programação de Aplicação (API).
- Uso estrito de ferramentas (strict tool use): valida parâmetros de ferramentas contra esquemas no momento da geração. Indicado para fluxos agênticos, chamadas de função e automações de múltiplas etapas.
O que isso significa para quem desenvolve
Com saídas estruturadas, cada resposta é um JSON válido — sem erros de JSON.parse() ou exceções de parsing. Os tipos de campo são respeitados, campos obrigatórios estão sempre presentes e o modelo não adiciona campos fora do esquema. Isso traz três ganhos diretos:
- Confiabilidade: não é mais necessário fazer retentativas para lidar com violações de esquema.
- Segurança de tipos: a integração com bancos de dados, sistemas de CRM ou outras APIs é mais segura porque os tipos dos campos são garantidos.
- Redução de custos: ao restringir as respostas apenas aos campos definidos, o número de tokens de saída cai — o que pode reduzir custos de inferência em cargas de trabalho de alto volume.
Disponibilidade e compatibilidade
O recurso é compatível com inferência em lote (batch inference), permitindo processar grandes volumes de requisições de forma assíncrona com saídas conformes ao esquema. No endpoint bedrock-runtime, também funciona com inferência entre regiões (cross-Region inference), sem necessidade de configuração adicional. Para quem precisa de respostas em tempo real, é possível transmitir respostas estruturadas como eventos tipados via streaming.
Exemplo prático: extração de dados com a API InvokeModel
O exemplo abaixo, retirado do post original da AWS, demonstra como extrair dados estruturados de um e-mail de cliente usando Boto3 com um modelo Claude:
import boto3
import json
REGION = "us-east-1" # Choose your preferred region
bedrock_runtime = boto3.client(service_name="bedrock-runtime", region_name=REGION)
# Define the JSON schema for structured output
schema = {
"type": "object",
"properties": {
"name": {"type": "string", "description": "Customer name"},
"email": {"type": "string", "description": "Customer email address"},
"plan_interest": {"type": "string", "description": "Product plan of interest"},
"demo_requested": {"type": "boolean", "description": "Whether a demo was requested"}
},
"required": ["name", "email", "plan_interest", "demo_requested"],
"additionalProperties": False
}
# Make a request with structured outputs via the InvokeModel API
# (reusing the schema defined for the Converse example)
response = bedrock_runtime.invoke_model(
modelId="global.anthropic.claude-sonnet-5-5",
body=json.dumps({
"anthropic_version": "bedrock-2023-05-31",
"max_tokens": 512,
"messages": [
{"role": "user", "content": (
"Paulo Santos (paulo@example.com) is interested in our Enterprise plan "
"and wants to schedule a demo for next Tuesday at 2pm."
)}
],
"output_config": {"format": {"type": "json_schema", "schema": schema}}
})
)
body = json.loads(response["body"].read())
# Check the stop reason before parsing
if body["stop_reason"] == "end_turn":
result_text = next(b["text"] for b in body["content"] if b["type"] == "text")
print(json.dumps(json.loads(result_text), indent=2))
elif body["stop_reason"] == "max_tokens":
print("Response truncated: increase max_tokens and retry.")
A saída retornada pelo modelo seria:
{
"name": "Paulo Santos",
"email": "paulo@example.com",
"plan_interest": "Enterprise",
"demo_requested": true
}
Nenhuma validação adicional é necessária. Para mais exemplos de uso da API, incluindo a Messages API, a AWS disponibilizou um notebook de exemplo no GitHub.
Uso estrito de ferramentas para fluxos agênticos
O Amazon Bedrock Mantle é voltado para aplicações agênticas com ferramentas do lado do servidor, inferência em segundo plano e conversas com estado. Com o uso estrito de ferramentas no endpoint bedrock-mantle, é possível garantir que os parâmetros das ferramentas correspondam exatamente ao esquema de entrada definido.
O exemplo abaixo mostra como definir uma ferramenta com aplicação estrita de esquema:
import json
from anthropic import AnthropicBedrockMantle
# Reusing the client created in the Messages API example
client = AnthropicBedrockMantle(aws_region="us-east-1")
message = client.messages.create(
model="anthropic.claude-sonnet-5",
max_tokens=512,
messages=[{"role": "user", "content": "What's the weather like in San Francisco?"}],
tools=[
{
"name": "get_weather",
"description": "Get the current weather for a specified location",
"strict": True,
"input_schema": {
"type": "object",
"properties": {
"location": {
"type": "string",
"description": "The city and state, e.g., San Francisco, CA"
},
"unit": {
"type": "string",
"enum": ["celsius", "fahrenheit"],
"description": "Temperature unit"
}
},
"required": ["location", "unit"],
"additionalProperties": False
}
}
]
)
# Tool inputs conform to the schema
for block in message.content:
if block.type == "tool_use":
print(f"Tool: {block.name}")
print(f"Input: {json.dumps(block.input, indent=2)}")
Com strict: true, o campo location será sempre uma string e unit será sempre celsius ou fahrenheit. O modelo não pode adicionar campos fora do esquema. Isso é especialmente valioso em casos de uso agênticos no Amazon Bedrock Mantle, onde os modelos orquestram fluxos de múltiplas etapas com ferramentas do servidor como busca na web e interpretador de código.
Principais casos de uso
A AWS destaca três padrões onde as saídas estruturadas reduzem mais a complexidade de tratamento de erros:
- Extração de dados: extrair campos de notas fiscais, contratos, e-mails e transcrições em JSON pronto para ser carregado em bancos de dados ou sistemas de Gestão de Relacionamento com o Cliente (CRM).
- Chamadas de ferramentas confiáveis em agentes: validar argumentos de ferramentas contra seus esquemas no momento da geração, para que fluxos agênticos de múltiplas etapas rodem sem falhas por entrada malformada.
- Classificação em escala: classificar tickets, leads ou conteúdo por intenção, prioridade e sentimento para roteamento, moderação e avaliação.
O exemplo abaixo, também do post original, mostra como classificar e rotear tickets de suporte usando o modelo Claude Haiku 5.5:
import boto3
import json
REGION = "us-east-1" # Choose your preferred region
bedrock_runtime = boto3.client(service_name="bedrock-runtime", region_name=REGION)
# Classification schema: enums restrict output to a fixed set of labels
schema = {
"type": "object",
"properties": {
"category": {
"type": "string",
"enum": ["billing", "technical", "account", "sales", "other"],
"description": "Primary ticket category"
},
"priority": {
"type": "string",
"enum": ["low", "medium", "high", "urgent"],
"description": "Urgency based on business impact"
},
"sentiment": {
"type": "string",
"enum": ["positive", "neutral", "negative"],
"description": "Customer sentiment"
},
"escalate": {"type": "boolean", "description": "Whether a human should review immediately"},
"reason": {"type": "string", "description": "One-sentence justification for the classification"}
},
"required": ["category", "priority", "sentiment", "escalate", "reason"],
"additionalProperties": False
}
ticket = (
"Our production API calls have been failing with 500 errors since this morning. "
"We're losing orders every minute. This is the second outage this month!"
)
# Make a request with structured outputs via the InvokeModel API
response = bedrock_runtime.invoke_model(
modelId="global.anthropic.claude-haiku-5-5",
body=json.dumps({
"anthropic_version": "bedrock-2023-05-31",
"max_tokens": 512,
"system": "You are a support ticket classifier. Classify the ticket accurately.",
"messages": [
{"role": "user", "content": f"Classify this support ticket:\n\n{ticket}"}
],
"output_config": {"format": {"type": "json_schema", "schema": schema}}
})
)
body = json.loads(response["body"].read())
# Check the stop reason before parsing
if body["stop_reason"] == "end_turn":
result_text = next(b["text"] for b in body["content"] if b["type"] == "text")
result = json.loads(result_text)
print(json.dumps(result, indent=2))
# Route the ticket based on the guaranteed-valid labels
if result["escalate"]:
print(f"Escalating to on-call: {result['category']} / {result['priority']}")
elif body["stop_reason"] == "max_tokens":
print("Response truncated: increase max_tokens and retry.")
Requisitos e boas práticas
A AWS recomenda as seguintes diretrizes para usar saídas estruturadas de forma eficaz no Amazon Bedrock:
- Defina
additionalProperties: falseem todos os objetos: isso é obrigatório para que as saídas estruturadas funcionem. Sem esse campo, o esquema não será aceito. - Use nomes e descrições de campos descritivos: o modelo utiliza nomes e descrições de propriedades para entender quais dados extrair. Nomes claros como
customer_emailtêm desempenho superior a nomes genéricos comofield1. - Use
enumpara valores restritos: quando um campo tem um conjunto limitado de valores válidos, useenumpara restringir as opções. - Comece simples e adicione complexidade gradualmente: esquemas básicos compilam mais rápido, são mais fáceis de depurar e mantêm o payload da requisição enxuto.
- Reutilize esquemas para se beneficiar do cache: estruture a aplicação para reutilizar esquemas entre requisições. O cache de gramática de 24 horas melhora a performance para consultas repetidas.
- Verifique o
stop_reasonem toda resposta: dois cenários podem produzir respostas não conformes — recusas do modelo por razões de segurança e limite de tokens atingido antes de completar a resposta. Ambos os casos devem ser tratados no código. - Teste com dados realistas antes de fazer o deploy: valide os esquemas com entradas representativas de produção. Casos extremos em dados reais frequentemente revelam problemas de design no esquema.
Para boas práticas adicionais e recomendações de design de esquemas, consulte a seção Saídas Estruturadas no Guia do Usuário do Amazon Bedrock.
Recursos de JSON Schema suportados
O Amazon Bedrock suporta os seguintes recursos do JSON Schema para saídas estruturadas:
- Todos os tipos básicos:
object,array,string,integer,number,boolean,null. enum(strings, números, booleanos ou nulos).const,anyOf,allOf(com limitações).$ref,$defedefinitions(apenas referências internas).- Formatos de string:
date-time,time,date,duration,email,hostname,uri,ipv4,ipv6,uuid. minItemspara arrays (apenas valores 0 e 1).
Não suportados: os seguintes recursos são aceitos pela API, mas não são aplicados durante a geração. Uma requisição que os inclua retorna resposta bem-sucedida, mas o modelo pode retornar valores que os violem — portanto, valide essas restrições na sua aplicação:
- Esquemas recursivos.
- Referências
$refexternas. - Restrições numéricas (
minimum,maximum,multipleOf). - Restrições de string (
minLength,maxLength). additionalPropertiesdefinido como qualquer valor diferente defalse.
Disponibilidade geral
As saídas estruturadas para modelos Anthropic Claude no Amazon Bedrock estão geralmente disponíveis agora, nos endpoints bedrock-runtime e bedrock-mantle. Para saber mais, acesse a documentação do Amazon Bedrock e explore o notebook de exemplo disponibilizado pela AWS.
Fonte
Structured outputs for Anthropic Claude models on Amazon Bedrock (https://aws.amazon.com/blogs/machine-learning/structured-outputs-for-anthropic-claude-models-on-amazon-bedrock/)
Leave a Reply