Extended thinking, effort e Batch API
Objetivos de aprendizagem
- Configurar extended thinking adaptativo (
thinking={"type": "adaptive"}) nos modelos atuais. - Saber que
budget_tokensfoi removido nos modelos atuais e que profundidade é controlada poroutput_config.effort. - Decidir quando ativar thinking/effort alto — e quando é desperdício.
- Conhecer a Message Batches API: 50% de desconto, janela de até 24h, sem SLA de latência,
custom_id, resultados fora de ordem, sem multi-turn tool calling (task statement 4.5). - Calcular janelas de submissão de batch compatíveis com um SLA de negócio.
- Aplicar a prática de refinar o prompt em amostra antes de processar o lote inteiro.
Extended thinking nos modelos atuais: adaptativo
Extended thinking é o raciocínio interno do modelo antes da resposta. Nos modelos atuais a configuração é o thinking adaptativo: thinking={"type": "adaptive"} — o modelo decide quanto raciocinar conforme a dificuldade da tarefa. O antigo budget_tokens (thinking={"type": "enabled", "budget_tokens": N}) foi removido nos modelos atuais: enviá-lo retorna erro 400 (ele permanece apenas em modelos antigos). Em claude-opus-5, o thinking já é ativo por padrão — omitir thinking equivale a adaptativo.
output_config.effort: o controle de custo/profundidade
A profundidade (e o custo) do raciocínio é controlada por output_config={"effort": ...} com os níveis low | medium | high | xhigh | max:
| Effort | Quando usar |
|---|---|
low | Tarefas mecânicas de alto volume: classificação simples, extração de campos diretos, reformatação. |
medium | Tarefas rotineiras com algum julgamento. |
high | Análise não trivial: revisão de código, extração com reconciliação de valores. |
xhigh / max | Problemas difíceis de raciocínio profundo: arquitetura, depuração complexa, matemática/provas. Custo e latência máximos. |
Regra de decisão: ligue effort alto quando a tarefa envolve julgamento multi-etapas cujo erro custa caro; mantenha baixo em tarefas mecânicas de volume — pagar raciocínio profundo para extrair um CNPJ é desperdício. Detalhe de API no claude-opus-5: thinking={"type": "disabled"} só é aceito com effort high ou menor — combiná-lo com xhigh/max retorna 400.
import anthropic
client = anthropic.Anthropic()
# Tarefa difícil: raciocínio adaptativo com esforço alto
response = client.messages.create(
model="claude-opus-5",
max_tokens=16000,
thinking={"type": "adaptive"},
output_config={"effort": "high"},
messages=[{
"role": "user",
"content": "Reconcilie as divergências entre estes dois balancetes e explique cada ajuste.",
}],
)
for block in response.content:
if block.type == "thinking":
print("[thinking]", block.thinking)
elif block.type == "text":
print(block.text)
Message Batches API
A Batches API processa requisições da Messages API de forma assíncrona com 50% de desconto em todos os tokens. Os fatos que caem na prova:
- Janela de processamento de até 24 horas — a maioria termina em menos de 1h, mas não há SLA de latência garantido. Nunca projete assumindo "costuma ser rápido".
custom_idem cada request correlaciona pedido e resultado — obrigatório na prática porque os resultados podem vir fora de ordem.- Sem multi-turn tool calling dentro de um request: o batch não pode executar sua ferramenta no meio e devolver o resultado para continuar — cada request é uma única rodada. (O modelo até pode pedir um tool_use, mas ninguém executa dentro do batch.)
- Limites: até 100.000 requests ou 256 MB por batch; resultados disponíveis por 29 dias; suporta os recursos da Messages API (visão, tools, caching).
- Adequado a workloads tolerantes a latência e não bloqueantes: relatórios noturnos, auditorias semanais, geração noturna de testes, reprocessamento de acervo. Inadequado a fluxos bloqueantes: checagem pré-merge em que o dev espera, resposta a usuário em tempo real.
Janela de submissão vs SLA
Se o negócio promete resultado em até N horas e o batch pode levar até 24h, os documentos não podem "envelhecer" na fila de entrada mais do que N − 24 horas. Exemplo do exam guide: com SLA de 30h, submeter batches a cada 4 horas garante que um documento espere no máximo 4h + 24h = 28h < 30h (com folga de 2h para retries e pós-processamento). Submeter uma vez por dia (janela de 24h) estouraria: 24h + 24h = 48h.
Outra prática cobrada: em falhas parciais, reprocessar apenas os requests que falharam — identificados pelo custom_id — com as correções necessárias (ex.: dividir em chunks documentos que estouraram o contexto), em vez de reenviar o lote inteiro.
Refine antes do lote: antes de processar 50.000 documentos, rode o prompt em uma amostra representativa na API síncrona, meça a taxa de sucesso e refine. Descobrir um defeito de prompt depois de um batch de 24h custa um ciclo inteiro (e o retrabalho é cobrado). Maximizar o acerto de primeira passada é a forma de reduzir custo de resubmissão iterativa.
import time
import anthropic
from anthropic.types.message_create_params import MessageCreateParamsNonStreaming
from anthropic.types.messages.batch_create_params import Request
client = anthropic.Anthropic()
documents = {
"doc-001": "Relatório trimestral Q3...",
"doc-002": "Ata de reunião de 12/09...",
}
batch = client.messages.batches.create(
requests=[
Request(
custom_id=doc_id, # correlaciona resultado (pode vir fora de ordem)
params=MessageCreateParamsNonStreaming(
model="claude-opus-5",
max_tokens=2048,
messages=[{"role": "user", "content": "Resuma em 3 bullets:\n" + text}],
),
)
for doc_id, text in documents.items()
]
)
while True:
status = client.messages.batches.retrieve(batch.id)
if status.processing_status == "ended":
break
time.sleep(60)
failed_ids = []
for result in client.messages.batches.results(batch.id):
if result.result.type == "succeeded":
msg = result.result.message
text = next((b.text for b in msg.content if b.type == "text"), "")
print(result.custom_id, "->", text[:80])
else:
failed_ids.append(result.custom_id) # só estes serão resubmetidos
print("Reprocessar apenas:", failed_ids)
flowchart TD
A[Amostra na API síncrona] --> B{Taxa de sucesso OK?}
B -->|Não| C[Refinar prompt/schema] --> A
B -->|Sim| D[Submeter batch - janela compatível com SLA]
D --> E[Poll até processing_status == ended]
E --> F[Correlacionar resultados por custom_id]
F --> G{Falhas parciais?}
G -->|Sim| H[Resubmeter só os custom_ids falhos, com correções]
G -->|Não| I[Pipeline downstream]
Pegadinhas da prova
- Distrator típico:
thinking={"type": "enabled", "budget_tokens": 8000}em modelo atual —budget_tokensfoi removido (400); o caminho atual é adaptativo +output_config.effort. - Distrator típico: mover a checagem pré-merge para a Batch API "pelo desconto de 50%" — fluxo bloqueante não tolera até 24h sem SLA; o desconto vale só para workloads tolerantes a latência.
- Distrator típico: "batch não serve porque os resultados vêm fora de ordem" — ordem não é problema:
custom_idcorrelaciona cada resultado. - Distrator típico: reenviar o lote inteiro após falhas parciais — reprocesse apenas os
custom_idfalhos, com as devidas correções. - Distrator típico: agente com loop de ferramentas dentro de um único request de batch — batch não suporta multi-turn tool calling no request.
Resumo em 5 linhas
- Modelos atuais:
thinking={"type": "adaptive"};budget_tokensfoi removido (erro 400). - Profundidade/custo do raciocínio:
output_config.effort= low | medium | high | xhigh | max — alto só quando o julgamento difícil justifica. - Batch API: 50% de desconto, até 24h, sem SLA de latência,
custom_idpara correlação, resultados fora de ordem, sem multi-turn tool calling. - Batch para workloads tolerantes a latência (relatórios noturnos, auditorias); síncrona para fluxos bloqueantes (pré-merge).
- Janela de submissão = SLA − 24h (com folga); refine o prompt em amostra antes do lote e resubmeta só os falhos.
Documentação oficial
Questões de fixação
1. Código legado envia thinking={"type": "enabled", "budget_tokens": 6000} para claude-opus-5 e recebe erro 400. Qual é a correção?
Gabarito: C. budget_tokens foi removido nos modelos atuais; o thinking adaptativo o substitui e o effort controla custo/profundidade. A e B tentam salvar um parâmetro que não existe mais em nenhuma forma. D é o oposto — o thinking é até ativo por padrão no claude-opus-5; o que mudou foi o mecanismo de controle.
2. Para reduzir custos, um gerente propõe migrar para a Batch API dois fluxos: (1) análise de risco pré-merge que bloqueia o botão de merge até concluir, e (2) auditoria semanal de contratos gerada aos domingos. Qual avaliação está correta?
Gabarito: A. O critério é tolerância a latência: auditoria semanal é o caso ideal de batch; fluxo bloqueante não pode depender de uma janela sem SLA. B aposta em "costuma ser rápido", que não é garantia. C é um falso problema — custom_id resolve a correlação. D adiciona complexidade e, no pior caso, paga duas vezes pelo mesmo trabalho no fluxo bloqueante.
3. Um contrato prevê que documentos recebidos sejam processados em até 30 horas. Usando a Batch API (janela de até 24h), qual frequência de submissão respeita o SLA?
Gabarito: B. O tempo total no pior caso = idade máxima do documento na fila + 24h de processamento. Com janelas de 4h: 4 + 24 = 28h ≤ 30h (folga de 2h). A dá 24 + 24 = 48h e C dá 30 + 24 = 54h — ambos estouram. D erra a premissa: o SLA do negócio conta do recebimento do documento, não da submissão.
4. (escolha duas) Num batch de 10.000 extrações, 200 falharam — parte por documentos maiores que o contexto, parte por erro de servidor. Quais ações estão corretas?
Gabarito: B e E. O padrão é resubmissão seletiva por custom_id com a correção adequada a cada causa (chunking para estouro de contexto; retry simples para erro de servidor). A paga 9.800 execuções redundantes. C joga fora a automação. D confunde parâmetros: max_tokens limita a saída; o estouro foi da janela de entrada.