Você trocou o modelo das suas chamadas à API do Claude por um mais recente e agora aparece o erro abaixo. Ou o texto da resposta volta vazio. A causa costuma ser a mesma: o primeiro bloco do conteúdo (content[0]) não é mais texto, e sim um bloco de raciocínio (thinking).

AttributeError: 'ThinkingBlock' object has no attribute 'text'

Se você lê response.content[0].text com o SDK de Python, recebe esse erro. Em JavaScript, o mesmo código devolve undefined, então, em vez de falhar, uma string vazia percorre o seu aplicativo. A parte traiçoeira: com entradas simples o primeiro bloco continua sendo texto, então os testes com entradas leves passam.

O problema em três linhas

O que acontece

O primeiro bloco não é mais texto

Principalmente com entradas pesadas, a resposta começa com um bloco de raciocínio (às vezes também com entradas leves). content[0].text quebra.

Causa

Raciocina sem você pedir

Os modelos Claude 5 e posteriores raciocinam quando necessário mesmo que você não defina thinking. Os modelos Claude 4 não raciocinam se você não definir.

Correção

Procure os blocos pelo tipo

Não presuma o primeiro bloco. Reúna os blocos cujo type é "text" e verifique também o stop_reason.

1. Quando acontece

O caso típico é uma migração em que você só muda o nome do modelo. Por exemplo, você passa do Claude Sonnet 4.6 para o Claude Sonnet 5.5 reescrevendo apenas o valor de model. Supondo que o formato da resposta é o mesmo, você não mexe no resto do código. Então acontece o seguinte (o terceiro caso acontece até com código bem escrito).

Como você lêO que acontece
content[0].text no SDK de PythonFalha com AttributeError: 'ThinkingBlock' object has no attribute 'text'
content[0].text em JavaScriptSem erro; vira undefined, e um texto vazio vai parar na tela ou no armazenamento
Procurando o bloco de textoSe o modelo raciocinar muito e atingir max_tokens, pode não haver nenhum bloco de texto

O terceiro caso acontece até com código bem escrito. Os tokens de raciocínio contam para o max_tokens, então, se o limite for pequeno, a resposta é cortada antes de o modelo escrever qualquer texto.

2. Causa: o Claude 5 e posteriores raciocinam sem você pedir

A documentação “Thinking” da Anthropic lista, modelo a modelo, o que acontece quando a requisição não inclui thinking. A linha divisória é o Claude 5.

ModeloSem thinkingConteúdo do raciocínio
Claude 5 e posteriores
(Opus 5.5, Sonnet 5.5, Haiku 5.5, Fable 5.1 etc.)
Raciocina (raciocínio adaptativo)Vazio por padrão (display: "omitted")
Opus 4.8, Opus 4.7Não raciocinaSó raciocina se você definir thinking: {type: "adaptive"}; o conteúdo vem vazio por padrão ("omitted")
Opus 4.6, Sonnet 4.6Não raciocinaSó raciocina se você definir thinking: {type: "adaptive"}; devolve um resumo por padrão ("summarized")

Fonte: a tabela por modelo e a descrição de display em “Thinking”, da Anthropic (consultado em 1º de novembro de 2026). Opus 4.5, Sonnet 4.5 e Haiku 4.5 não aceitam {type: "adaptive"}; para fazê-los raciocinar, use {type: "enabled"} com budget_tokens.

O modelo decide a cada entrada se vai raciocinar. A documentação “Steering thinking” explica que, em perguntas factuais simples, o modelo pode responder sem bloco de raciocínio. E alerta para não construir a lógica do aplicativo supondo que toda resposta começa com um bloco de raciocínio. Ou seja, o primeiro bloco às vezes é texto e às vezes é raciocínio. Código que presuma qualquer um dos dois vai quebrar em algum momento.

O conteúdo da resposta é ordenado como mostrado abaixo. O conteúdo do raciocínio vem vazio por padrão, mas o bloco em si continua sendo devolvido.

3. O que encontrei nos testes

Testei no meu próprio ambiente com o SDK de Python (anthropic 1.14.0) em 1º de novembro de 2026. Enviei a quatro modelos uma entrada leve e uma pesada, uma vez cada, tanto sem thinking quanto com {type: "adaptive"}. Defini max_tokens como 8000. A entrada leve era uma pergunta factual simples que pedia a capital do Japão em uma só palavra (perguntamos em japonês); a pesada era um problema que pedia todos os inteiros de quatro dígitos que atendem a cinco condições.

ModeloConfiguração de thinkingcontent (entrada leve)content (entrada pesada)
Sonnet 4.6Não definidotexttext
Sonnet 4.6adaptivetextsó thinking (atingiu o limite)
Haiku 5.5Não definidotextsó thinking (atingiu o limite)
Haiku 5.5adaptivetextsó thinking (atingiu o limite)
Sonnet 5.5Não definidotextthinking → text
Sonnet 5.5adaptivetextthinking → text
Opus 5.5Não definidotextthinking → text
Opus 5.5adaptivethinking → textthinking → text

Em vermelho, as combinações em que content[0].text lançou AttributeError: 'ThinkingBlock' object has no attribute 'text'. Cada uma é o resultado de uma única execução; se o modelo raciocina ou não pode variar de uma execução para outra, mesmo com a mesma entrada.

Três conclusões.

Primeira: os modelos Claude 5 e posteriores raciocinaram na entrada pesada mesmo sem thinking. Com o Sonnet 4.6, omiti-lo manteve o texto como primeiro bloco. Isso confirma o que diz a documentação: mudar só o nome do modelo muda o formato da resposta.

Segunda: com a entrada leve, o primeiro bloco foi texto em quase todas as combinações. Se os seus testes usam só entradas leves, você não vai encontrar esse problema. Por outro lado, o Opus 5.5 com adaptive raciocinou até na entrada leve. No Claude 5 e posteriores, omitir thinking e definir adaptive são a mesma configuração, então essa diferença provavelmente se deve à variação entre execuções. Não dá para dizer que “entradas leves não fazem o modelo raciocinar”.

Terceira: ao atingir o limite, não voltou texto nenhum. Na entrada pesada, o Haiku 5.5 gastou todos os 8000 tokens raciocinando, tanto sem thinking quanto com adaptive, e não devolveu nenhum bloco de texto. O Sonnet 4.6 com adaptive também atingiu o limite. No Claude 5 e posteriores o conteúdo do raciocínio também vem vazio por padrão, então o usuário não vê nada, mas você continua pagando pelos tokens de saída.

4. Como corrigir

A correção é parar de presumir qual bloco vem primeiro e reunir os blocos do tipo texto (type é "text"). Verifique também o stop_reason para não tratar como resposta normal uma que foi cortada no limite.

Python

import anthropic

client = anthropic.Anthropic()
response = client.messages.create(
    model="claude-sonnet-5-5",
    max_tokens=16000,
    messages=[{"role": "user", "content": prompt}],
)

# Não presuma o primeiro bloco: reúna só os blocos de texto
text = "".join(b.text for b in response.content if b.type == "text")

if response.stop_reason == "max_tokens":
    # Cortado no limite. text pode estar vazio
    raise RuntimeError("Atingiu max_tokens. Aumente o limite ou reduza o raciocínio")
if response.stop_reason == "end_turn" and not text:
    # Em fluxos com ferramentas, stop_reason é "tool_use" e texto vazio é normal
    raise RuntimeError("Nenhum bloco de texto")

TypeScript

import Anthropic from "@anthropic-ai/sdk";

const client = new Anthropic();
const response = await client.messages.create({
  model: "claude-sonnet-5-5",
  max_tokens: 16000,
  messages: [{ role: "user", content: prompt }],
});

// Filtre pelo tipo antes de ler text
const text = response.content
  .filter((b): b is Anthropic.TextBlock => b.type === "text")
  .map((b) => b.text)
  .join("");

if (response.stop_reason === "max_tokens") {
  throw new Error("Atingiu max_tokens. Aumente o limite ou reduza o raciocínio");
}
// Em fluxos com ferramentas, stop_reason é "tool_use" e texto vazio é normal
if (response.stop_reason === "end_turn" && text === "") {
  throw new Error("Nenhum bloco de texto");
}

No SDK de TypeScript, os elementos de content são uma união de tipos como texto, raciocínio e uso de ferramentas. Escrever content[0].text diretamente normalmente não passa na verificação de tipos. Mas, se você forçar o tipo com as, o erro passa despercebido.

Defina max_tokens contando o raciocínio

A documentação “Steering thinking” explica que max_tokens é um limite conjunto para o raciocínio e o texto da resposta. Também observa que um limite escolhido supondo que o modelo não vai raciocinar costuma ser pequeno demais para entradas difíceis. Quando você recebe stop_reason: "max_tokens", há duas correções.

Os 16000 dos exemplos acima são uma referência. Nos meus testes, até 8000 às vezes foram gastos inteiros no raciocínio. Para produção, rode entradas pesadas e defina o valor olhando usage.output_tokens_details.thinking_tokens (o número de tokens gastos no raciocínio) na resposta.

  • Aumentar o limite: quando o raciocínio melhora a qualidade da resposta nas entradas que foram cortadas
  • Reduzir o esforço: quando o modelo só está raciocinando demais e a qualidade da resposta não muda (o esforço é definido com output_config.effort)

Ao continuar uma conversa, devolva também os blocos de raciocínio

Ao acrescentar uma resposta ao histórico da conversa, não extraia só o texto; devolva o content como está. Principalmente em fluxos com ferramentas, o bloco de raciocínio guarda o motivo da chamada à ferramenta. A documentação pede que você devolva os blocos recebidos sem modificá-los, e blocos modificados são rejeitados com um erro 400. O mais seguro é manter separados o texto que você exibe e o content que devolve no histórico.

5. Dá para simplesmente desligar o raciocínio?

É tentador pensar “se o raciocínio atrapalha, é só desligar”, mas se dá ou não depende do modelo. Veja como thinking: {type: "disabled"} é tratado.

Modelo{type: "disabled"}
Opus 5.5, Fable 5.1, Fable 5Erro 400 (não dá para desligar)
Sonnet 5.5Erro 400 (em vez disso, {type: "between_tools"} pula o raciocínio inicial quando o esforço é high ou menor)
Haiku 5.5, Opus 5Dá para desligar (só com esforço high ou menor; erro 400 em xhigh e max)
Sonnet 5Dá para desligar

Fonte: “Thinking”, da Anthropic (consultado em 1º de novembro de 2026). Também é possível verificar se um modelo aceita com capabilities.thinking.types.disabled.supported na Models API. O esforço padrão é medium no Opus 5.5 e no Haiku 5.5 e high na maioria dos outros modelos, então os padrões atendem à condição de “high ou menor”.

Mesmo nos modelos em que dá para desligar, fazer isso pode reduzir a qualidade da resposta em entradas difíceis. E o mesmo problema volta toda vez que você troca de modelo. A correção de fundo é um código que leia a resposta em qualquer ordem. Se quiser reduzir o raciocínio, reduza primeiro o esforço. Segundo a documentação da Anthropic, pedir ao Sonnet 5.5 no prompt de sistema que raciocine menos não reduz o raciocínio de forma confiável, e o Haiku 5.5 continuou raciocinando mesmo quando instruído a responder diretamente (nos testes da Anthropic). Para os dois, ajuste com o esforço.

6. Como não deixar passar nos testes

Esse problema escapa nos testes com entradas leves. Ao trocar de modelo, verificar nesta ordem torna mais difícil deixá-lo passar.

  1. Procure content[0] no seu código: liste todos os lugares que leem por posição, como content[0], content[-1] e .content[0].text, não só no código de produção, mas também nos testes e nos logs
  2. Acrescente entradas pesadas aos testes: inclua como entradas de teste as entradas mais longas de produção e as tarefas mais difíceis (só com entradas leves, o primeiro bloco continua sendo texto e a falha fica escondida)
  3. Use respostas simuladas que comecem com um bloco de raciocínio: nos testes unitários que não chamam a API, prepare uma resposta [thinking, text] e outra só com thinking e stop_reason "max_tokens", para testar sem depender de o modelo raciocinar ou não
  4. Faça a implantação aos poucos: não troque tudo de uma vez; passe primeiro parte das cargas de trabalho para o novo modelo, acompanhe as contagens de texto vazio e de exceções e depois amplie

⚠️ Quando vários serviços ou equipes trocam de modelo juntos, acrescente uma linha ao pedido de migração: “O primeiro bloco da resposta nem sempre é texto. Procure-o pelo tipo.” A mudança parece uma simples troca de nome, e se você esperar que cada equipe perceba sozinha, o código que passou nos testes com entradas leves vai quebrar em produção.

Isso não é a única coisa a verificar ao trocar de modelo. Para o que mudou na migração a partir de gerações anteriores, veja “Guia de Migração para Claude Opus 4.7” e “As 3 mudanças incompatíveis do Claude Fable 5.1”. O esforço na API é explicado na documentação “Effort” da Anthropic, e como escolher o esforço no Claude Code, em “Configuração de esforço do Claude Code”.

Resumo

  • AttributeError: 'ThinkingBlock' object has no attribute 'text' ocorre quando o primeiro bloco da resposta é um bloco de raciocínio e você tenta ler o texto com content[0].text
  • Os modelos Claude 5 e posteriores raciocinam quando necessário mesmo sem thinking, então basta trocar o nome do modelo a partir de um Claude 4 para que o formato da resposta mude
  • Com entradas leves, o primeiro bloco costuma continuar sendo texto, então os testes leves passam
  • A correção é reunir os blocos cujo type é "text" e verificar se o stop_reason é "max_tokens"
  • Alguns modelos não permitem desligar o raciocínio, então a correção de fundo não é desligá-lo, e sim escrever código que leia a resposta em qualquer ordem

Perguntas frequentes

P. Nunca defini thinking. Por que recebo um bloco de raciocínio?

R. Nos modelos Claude 5 e posteriores, o raciocínio adaptativo fica ativo mesmo sem thinking, e o modelo raciocina nas entradas em que decide que precisa. O conteúdo do raciocínio vem vazio por padrão, mas o bloco em si é incluído na resposta. Modelos Claude 4, como o Claude Opus 4.8 e o Sonnet 4.6, não raciocinam se você não definir.

P. Por que recebo uma resposta sem nenhum bloco de texto?

R. Os tokens de raciocínio contam para o max_tokens, e o limite foi atingido antes de o modelo escrever qualquer texto. O stop_reason deve ser "max_tokens". Aumente o limite ou reduza o esforço para diminuir o raciocínio.

P. E se eu quiser ler o conteúdo do raciocínio?

R. Defina thinking: {type: "adaptive", display: "summarized"} para receber um resumo do raciocínio. O padrão no Claude 5 e posteriores é "omitted" (o conteúdo vem vazio e só a assinatura é incluída). De qualquer forma, você é cobrado por todos os tokens de raciocínio.

Histórico de atualizações

  • 1º de novembro de 2026Primeira versão. Escrita após revisar a documentação “Thinking” e “Steering thinking” da Anthropic e testar a ordem da resposta de quatro modelos no meu próprio ambiente.

Fontes