O Modelo Mental do SDK Python da Anthropic
O pacote oficial anthropic para Python é menor do que parece por fora.
Por baixo de cada chamada de método, decorador e gerenciador de contexto de streaming, existe um único endpoint HTTP: POST /v1/messages.
O trabalho do SDK é tornar a chamada desse endpoint segura, tipada e ergonômica a partir do Python, tanto em scripts bloqueantes quanto em serviços concorrentes.
Uma vez que você veja o pacote dessa forma, o restante de sua superfície, clientes síncronos versus assíncronos, configuração de retentativa e streaming, deixa de parecer uma pilha de recursos não relacionados e começa a parecer um pequeno número de decisões sobrepostas a uma única requisição.
Resumo
- Ideia Central: O pacote
anthropicé um cliente HTTP tipado para a API de Mensagens, oferecido como duas classes de cliente paralelas que diferem apenas no modelo de concorrência. - Por que Importa: Falar diretamente com a API usando
requestsouhttpxsignifica reimplementar retentativas, análise de streaming e tipagem de resposta por conta própria; o SDK oferece tudo isso gratuitamente. - Conceitos-Chave: cliente, síncrono vs assíncrono, política de retentativa, timeout, streaming, modelo de resposta.
- Quando Usar: Qualquer código Python que chame o Claude, desde um script único até um serviço FastAPI de produção lidando com centenas de requisições concorrentes.
- Limitações / Trade-offs: O SDK não esconde a forma da API subjacente. Você ainda precisa entender mensagens, tokens e motivos de parada; o SDK apenas remove a "canalização" (plumbing) em torno deles.
- Tópicos Relacionados: Forma da requisição/resposta da API de Mensagens, configuração de retentativa e timeout, eventos de streaming, modelos de resposta com type hints.
Fundamentos
Um endpoint, duas portas
Toda chamada que você faz com o pacote anthropic, seja ela client.messages.create(...) ou client.messages.stream(...), envia no final uma requisição POST para /v1/messages com um corpo JSON contendo model, max_tokens e uma lista de messages.
O SDK oferece duas classes de cliente como pontos de entrada para esse mesmo endpoint:
anthropic.Anthropic()é o cliente síncrono. Chamá-lo bloqueia a thread atual até que uma resposta (ou o primeiro chunk de streaming) chegue.anthropic.AsyncAnthropic()é o cliente assíncrono. Chamá-lo retorna uma corrotina que vocêawait, permitindo que seu programa faça outro trabalho enquanto a requisição está em andamento.
Ambas as classes expõem os mesmos métodos, os mesmos parâmetros e os mesmos tipos de resposta. Escolher uma em vez da outra não muda o que você pode pedir ao Claude para fazer. Muda como seu programa Python se comporta enquanto espera pela resposta.
O cliente como um objeto pequeno e reutilizável
Uma instância de cliente não é uma única requisição. É um ponto de entrada configurado que você constrói uma vez e reutiliza.
import anthropic
client = anthropic.Anthropic() # lê ANTHROPIC_API_KEY do ambienteA construção é onde você define coisas que devem se aplicar a todas as requisições feitas através desse cliente: a chave da API, um base_url personalizado, timeout padrão e max_retries padrão. Você então chama client.messages.create(...) ou client.messages.stream(...) muitas vezes contra o mesmo cliente, em vez de construir um novo para cada requisição.
Isso é importante porque as retentativas, o pooling de conexões e o comportamento de timeout são propriedades do cliente, não de uma chamada individual. Um cliente que você constrói uma vez no início da aplicação e reutiliza é o padrão normal; construir um cliente novo dentro de um loop de tratamento de requisições "quente" apenas descarta essa reutilização sem nenhum benefício.
Mecânicas e Interações
Síncrono e assíncrono são o mesmo contrato, runtimes diferentes
Como Anthropic() e AsyncAnthropic() compartilham os mesmos nomes de método e parâmetros, mover código entre eles é majoritariamente mecânico: adicione async à assinatura da função, await a chamada e use async with em vez de with para o gerenciador de contexto de streaming.
# Síncrono
response = client.messages.create(model="claude-sonnet-5", max_tokens=1024, messages=[...])
# Assíncrono
response = await async_client.messages.create(model="claude-sonnet-5", max_tokens=1024, messages=[...])O que difere é o que acontece em seu programa enquanto a requisição está pendente. O cliente síncrono estaciona a thread chamadora. O cliente assíncrono cede o controle de volta para o event loop, permitindo que outras corrotinas, outras chamadas de API em andamento, consultas ao banco de dados, requisições web recebidas, façam progresso ao mesmo tempo.
É por isso que a decisão entre os dois clientes é realmente uma decisão sobre o modelo de concorrência do seu programa, não sobre a API Claude em si. Um script que faz uma requisição e imprime a resposta não tem nada a ganhar com o assíncrono. Um serviço web que atende a muitas requisições simultâneas, cada uma das quais precisa chamar o Claude, ganha muito com isso, pois um único event loop pode gerenciar centenas de chamadas de API pendentes sem centenas de threads do sistema operacional.
Retentativas ficam entre você e a rede
Redes reais falham de maneiras que não têm nada a ver com seu prompt: uma conexão cai, a API retorna um 529 porque está temporariamente sobrecarregada, um 429 chega porque você excedeu brevemente um limite de taxa. A camada de retentativa do SDK existe para absorver exatamente essa classe de falha sem que você precise escrever um loop de retentativa manualmente.
Por padrão, ambos os clientes tentam novamente uma requisição automaticamente algumas vezes, com um atraso de backoff entre as tentativas, sempre que a falha parece transitória (erros de rede, 408, 409, 429 e respostas 5xx). Falhas que não são transitórias, como uma requisição malformada, uma chave de API inválida, um modelo que não existe, não são retentadas, pois retentá-las apenas reproduziria o mesmo erro.
Esse comportamento é configurável por cliente (max_retries=... na construção) e por requisição (with_options(...)), o que permite apertar as retentativas para chamadas sensíveis à latência e afrouxá-las para trabalhos em segundo plano. A referência completa de parâmetros está em uma página dedicada (veja Relacionados).
Streaming transforma uma resposta em muitos eventos
Uma chamada não-streaming espera pela resposta completa antes de retornar qualquer coisa. Para respostas curtas, isso está bom. Para respostas longas, uma explicação de múltiplos parágrafos, uma grande geração de código, esperar pela resposta completa antes de mostrar algo ao usuário faz com que um aplicativo pareça lento, mesmo quando o modelo está trabalhando em um ritmo normal.
Streaming muda a forma da interação de "uma requisição, uma resposta" para "uma requisição, muitos eventos incrementais". Em vez de retornar um objeto Message completo, client.messages.stream(...) retorna um gerenciador de contexto que expõe um iterador, mais comumente consumido através de seu helper text_stream, que produz texto à medida que o modelo o gera.
Não-streaming: requisição ──────────────────► [ resposta completa ]
Streaming: requisição ─► chunk ─► chunk ─► chunk ─► [ fim ]
Conceitualmente, streaming não muda o que o modelo produz. Muda quando você pode ver pedaços dele. A mesma mensagem final, o mesmo uso de tokens, o mesmo motivo de parada ainda estão disponíveis no final do stream; você apenas teve a opção de renderizar a saída à medida que ela chegava, em vez de esperar.
Considerações Avançadas e Aplicações
Onde os três conceitos se encontram
A razão pela qual síncrono/assíncrono, retentativas e streaming pertencem a um único modelo mental é que eles interagem.
Uma requisição retentada durante o streaming, por exemplo, é mais sutil do que uma requisição não-streaming retentada: se uma conexão cair no meio do stream depois que algum texto já foi mostrado a um usuário, simplesmente retentar a requisição inteira do zero corre o risco de duplicar a saída que o usuário já viu. O SDK lida com os casos comuns de falha transitória aqui, mas você deve entender essa interação antes de construir um recurso de streaming de produção, em vez de descobri-la durante um incidente.
Assíncrono e streaming também compõem diretamente: o gerenciador de contexto de streaming de um cliente AsyncAnthropic é um gerenciador de contexto assíncrono, iterado com async for, que permite que um único aplicativo assíncrono faça streaming de respostas para muitos clientes concorrentes (por exemplo, muitas conexões WebSocket abertas) sem dedicar uma thread para cada um.
| Abordagem | Força | Fraqueza | Melhor Ajuste |
|---|---|---|---|
| Síncrono, não-streaming | Código mais simples, mais fácil de raciocinar | Bloqueia até que a resposta completa chegue | Scripts únicos, jobs em lote, notebooks |
| Síncrono, streaming | Renderiza a saída incrementalmente com fluxo de controle simples | Ainda bloqueia a thread entre os chunks | Ferramentas CLI, aplicativos desktop para um único usuário |
| Assíncrono, não-streaming | Libera o event loop enquanto espera | Adiciona complexidade de async/await | Serviços de backend lidando com muitas requisições independentes |
| Assíncrono, streaming | Renderiza incrementalmente e lida com muitos usuários concorrentes | Mais complexo de raciocinar e depurar | UIs de chat, serviços web multiusuário, loops de agente |
Escolhendo um ponto de partida
Um padrão razoável: comece com Anthropic(), pois é a coisa mais simples que funciona, e passe para AsyncAnthropic() apenas quando tiver um requisito de concorrência concreto, tipicamente um framework web (como FastAPI) que já é assíncrono, ou uma carga de trabalho que dispara muitas chamadas Claude simultâneas. Adicione streaming quando a resposta for longa o suficiente, ou a interação for interativa o suficiente, para que mostrar a saída parcial melhore visivelmente a experiência.
Nenhuma dessas são portas de mão única. Como a superfície de métodos é compartilhada entre as duas classes de cliente, o código escrito contra o cliente síncrono se traduz para o cliente assíncrono com mudanças mecânicas e de baixo risco, em vez de uma reescrita.
Equívocos Comuns
- "AsyncAnthropic() é mais rápido." Não é mais rápido por requisição; uma única chamada assíncrona para Claude leva o mesmo tempo que a mesma chamada feita síncronamente. O que o assíncrono oferece é a capacidade de ter muitas requisições em andamento ao mesmo tempo sem uma thread por requisição.
- "Streaming permite obter uma resposta parcial se eu cancelar cedo." Verdadeiro em um sentido restrito, mas o streaming não muda o que o modelo computa; muda quando você o recebe. Cancelar um stream cedo ainda significa que você pediu (e foi cobrado por, até aquele ponto) trabalho que o modelo já fez.
- "Retentativas significam que nunca preciso lidar com erros." O SDK retenta falhas transitórias automaticamente, mas uma requisição que falha após as retentativas ainda levanta uma exceção. Retentativas reduzem a frequência com que você vê erros transitórios; elas não eliminam o tratamento de erros.
- "Eu deveria sempre usar o cliente assíncrono para código de produção." Produção não é sinônimo de assíncrono. Um pipeline de lote de produção que processa documentos um por um não tem concorrência para explorar, e o cliente síncrono é a escolha mais simples e igualmente correta lá.
FAQs
Anthropic() e AsyncAnthropic() suportam recursos diferentes?
Não.
Ambos os clientes expõem os mesmos métodos (messages.create, messages.stream, etc.) com os mesmos parâmetros e retornam os mesmos tipos de resposta.
A única diferença é que um bloqueia a thread chamadora e o outro é aguardado dentro de um event loop.
Posso usar ambos os clientes na mesma aplicação?
Sim, embora seja incomum.
Um caso típico é um serviço web majoritariamente assíncrono que também tem um script de inicialização ou manutenção síncrono usando Anthropic() diretamente, fora do event loop.
O streaming muda o resultado final que recebo do modelo?
Não.
O mesmo texto, uso de tokens e motivo de parada são produzidos, independentemente de você fazer streaming ou não; o streaming apenas muda se você vê a saída incrementalmente ou toda de uma vez no final.
O que conta como uma falha "transitória" que é retentada automaticamente?
Erros de conexão em nível de rede e respostas HTTP nos intervalos 408, 409, 429 e 5xx.
Estes representam problemas na rede ou no lado do servidor que provavelmente terão sucesso se você simplesmente tentar novamente.
O SDK retentará uma requisição que falha devido a um prompt incorreto ou parâmetros inválidos?
Não.
Erros do cliente, como um nome de modelo inválido ou uma requisição malformada, retornam um erro 4xx (excluindo 408/409/429) e não são retentados, pois retentar uma requisição malformada inalterada falharia novamente.
O objeto cliente é thread-safe para ser reutilizado entre requisições?
Sim, uma única instância de cliente é projetada para ser construída uma vez e reutilizada para muitas requisições, o que também permite que o pooling de conexões e o comportamento configurado de retentativa/timeout realmente entrem em vigor.
Por que eu escolheria o cliente síncrono para uma aplicação web?
Se o seu framework web for ele próprio síncrono (visões Flask ou Django WSGI clássicas sem suporte a async), o cliente síncrono é a combinação natural. Ligar um cliente assíncrono a um framework síncrono adiciona complexidade sem um benefício de concorrência.
O streaming requer o cliente assíncrono?
Não.
Ambos os clientes suportam streaming; Anthropic().messages.stream(...) e AsyncAnthropic().messages.stream(...) existem, iterados com for e async for respectivamente.
O que acontece com o uso de tokens e a cobrança quando faço streaming?
Não é afetado pelo streaming.
Você é cobrado pelos tokens que o modelo realmente gera, quer você os receba como uma resposta final ou como muitos chunks incrementais.
Se eu cancelar um stream no meio, isso impede o modelo de gerar mais tokens?
Isso impede que seu cliente receba chunks adicionais, mas se a geração subjacente para imediatamente depende de como você cancela (fechando o contexto do stream vs. permitindo que a conexão continue). Trate o cancelamento no meio do stream como melhor esforço, não como uma parada abrupta instantânea.
Preciso analisar JSON bruto da resposta de streaming por conta própria?
Não.
O SDK analisa os eventos enviados pelo servidor subjacentes para você e expõe acessadores tipados como text_stream, bem como a mensagem final completa assim que o stream é concluído.
Um cliente é "mais oficial" ou mais pronto para produção que o outro?
Não, ambos são totalmente suportados, partes GA do mesmo pacote.
Nenhum é uma versão beta ou de fallback do outro; são duas interfaces para a mesma API subjacente.
Relacionados
- Noções Básicas do SDK Python - instale o SDK, construa um cliente e envie sua primeira requisição.
- Escolhendo Entre Anthropic() e AsyncAnthropic() em Código de Produção - uma comparação mais profunda e focada em decisões para serviços FastAPI e scripts.
- Streaming de Respostas com o SDK Python - código de exemplo para
client.messages.stream()etext_stream. - Referência de Configuração de Retentativa e Timeout do SDK Python - a referência completa de
max_retries,timeoutewith_options().
Versões da Stack: Escrito contra a linha de modelos Claude atual em aproximadamente 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.