Escolhendo entre Anthropic() e AsyncAnthropic() em Código de Produção
O pacote anthropic envia duas classes de cliente com uma superfície de método idêntica: Anthropic() e AsyncAnthropic().
A escolha certa depende inteiramente de como seu programa lida com concorrência, não de qual é "melhor".
Resumo
Anthropic() é um cliente bloqueante - chamar client.messages.create(...) pausa a thread atual até que uma resposta chegue.
AsyncAnthropic() é um cliente não bloqueante construído sobre asyncio - chamar await client.messages.create(...) cede o controle de volta para o loop de eventos enquanto a solicitação está em andamento.
Ambos expõem os mesmos parâmetros, os mesmos tipos de resposta e as mesmas classes de erro, portanto, alternar entre eles mais tarde é principalmente mecânico.
A decisão que importa é se sua aplicação já roda em um loop de eventos (um framework web async, uma fila de jobs async) ou roda como um script de linha reta, porque essa decisão foi efetivamente tomada para você antes mesmo de você escolher um cliente Claude.
Errar nisso não quebra a correção, custa taxa de transferência: um cliente síncrono chamado de dentro de um framework async bloqueia todo o loop de eventos, e um cliente async usado em um script single-threaded adiciona cerimônia sem benefício.
Receita
import anthropic
# Script, notebook, ferramenta CLI, job em lote
client = anthropic.Anthropic()
response = client.messages.create(
model="claude-sonnet-5",
max_tokens=1024,
messages=[{"role": "user", "content": "Olá"}],
)
# FastAPI, aiohttp, ou qualquer serviço baseado em asyncio
async_client = anthropic.AsyncAnthropic()
response = await async_client.messages.create(
model="claude-sonnet-5",
max_tokens=1024,
messages=[{"role": "user", "content": "Olá"}],
)Quando usar Anthropic():
- Scripts únicos, notebooks e ferramentas CLI que fazem solicitações sequencialmente.
- Jobs em lote ou ETL que processam itens um por um e não precisam de sobreposição entre as solicitações.
- Qualquer base de código construída em um framework web síncrono (Flask ou Django sem views async).
Quando usar AsyncAnthropic():
- Serviços web construídos em um framework async, mais comumente FastAPI, que já rodam em um loop de eventos.
- Cargas de trabalho que desdobram muitas chamadas Claude concorrentemente (resumindo 50 documentos de uma vez, por exemplo).
- Qualquer código que precise chamar Claude enquanto também aguarda outro I/O (uma consulta ao banco de dados, outra chamada de API) sem bloquear nenhum deles.
Exemplo de Trabalho
Este exemplo mostra o mesmo endpoint de sumarização escrito de duas maneiras: como um script síncrono e como uma rota FastAPI usando o cliente async, para que o contraste seja direto.
# sync_script.py - um job em lote autônomo
import anthropic
client = anthropic.Anthropic()
def summarize(text: str) -> str:
message = client.messages.create(
model="claude-sonnet-5",
max_tokens=300,
system="Resuma a entrada em uma frase.",
messages=[{"role": "user", "content": text}],
)
return message.content[0].text
if __name__ == "__main__":
documents = ["Texto do primeiro documento...", "Texto do segundo documento..."]
for doc in documents:
print(summarize(doc))# fastapi_service.py - um serviço web async
from fastapi import FastAPI
from pydantic import BaseModel
import anthropic
app = FastAPI()
client = anthropic.AsyncAnthropic()
class SummarizeRequest(BaseModel):
text: str
@app.post("/summarize")
async def summarize(req: SummarizeRequest):
message = await client.messages.create(
model="claude-sonnet-5",
max_tokens=300,
system="Resuma a entrada em uma frase.",
messages=[{"role": "user", "content": req.text}],
)
return {"summary": message.content[0].text}O que isso demonstra:
- Ambas as versões chamam o mesmo método (
messages.create) com os mesmos parâmetros; apenasasync/awaite a classe do cliente diferem. - A rota FastAPI
awaita a chamada Claude, então o loop de eventos pode servir outras requisições de entrada enquanto esta espera pela rede. - Ambos os clientes são construídos uma vez no escopo do módulo e reutilizados entre as chamadas, não recriados por requisição.
- O script em lote não tem requisições concorrentes para sobrepor, então o cliente síncrono não adiciona custo ali.
Análise Profunda
Como Funciona
- O loop de eventos
asynciodo Python executa uma corrotina por vez, mas muda para outra sempre que a corrotina em execução atinge umawaitem I/O, como uma chamada de rede. AsyncAnthropic()constrói suas chamadas HTTP sobre o transporte async dohttpx, então uma solicitação Claude pendente cede o controle de volta para o loop em vez de estacionar uma thread.Anthropic()usa o transporte síncrono dohttpx; uma chamada bloqueia a thread chamadora até que um cabeçalho de resposta chegue (ou, ao fazer streaming, até que o primeiro chunk chegue).- Um cliente síncrono chamado de dentro de código
async defainda funciona, mas bloqueia todo o loop de eventos durante a duração da chamada, paralisando todas as outras corrotinas agendadas nesse loop, incluindo requisições não relacionadas sendo servidas pelo mesmo processo FastAPI. - Construir um cliente novo por requisição (síncrono ou async) descarta o pooling de conexões e força um novo handshake TLS mais vezes do que o necessário; ambas as classes de cliente são destinadas a serem construídas uma vez e reutilizadas.
Síncrono vs Assíncrono em Resumo
| Preocupação | Anthropic() | AsyncAnthropic() |
|---|---|---|
| Estilo de chamada | client.messages.create(...) | await client.messages.create(...) |
| Bloqueia a thread chamadora enquanto espera | Sim | Não - cede para o loop de eventos |
| Encaixe natural | Scripts, CLIs, jobs em lote, frameworks síncronos | FastAPI, aiohttp, qualquer serviço baseado em asyncio |
| Modelo de concorrência | Uma requisição por vez por thread (use um pool de threads para mais) | Muitas requisições em voo em um loop de eventos |
| Gerenciador de contexto de streaming | with client.messages.stream(...) as stream: | async with client.messages.stream(...) as stream: |
Notas Python
# Executando muitas sumarizações concorrentemente com o cliente async
import asyncio
import anthropic
client = anthropic.AsyncAnthropic()
async def summarize(text: str) -> str:
message = await client.messages.create(
model="claude-sonnet-5",
max_tokens=300,
messages=[{"role": "user", "content": text}],
)
return message.content[0].text
async def main():
documents = ["Doc A...", "Doc B...", "Doc C..."]
results = await asyncio.gather(*(summarize(doc) for doc in documents))
print(results)
asyncio.run(main())asyncio.gather é o que realmente lhe confere o benefício de concorrência do cliente async: ele lança todas as requisições antes de aguardar qualquer uma delas, para que elas rodem sobrepostas em vez de uma após a outra. Usar AsyncAnthropic() mas ainda assim awaitar cada chamada sequencialmente em um loop não traz nenhum ganho de taxa de transferência e apenas a complexidade adicionada.
Armadilhas
- Chamar o cliente síncrono dentro de uma rota FastAPI async.
client.messages.create(...)(semawait) dentro deasync defbloqueia todo o loop de eventos pela duração da chamada, paralisando todas as outras requisições que o processo está manipulando. Correção: useAsyncAnthropic()dentro de manipuladores de rota async, ou execute a chamada síncrona em um pool de threads comawait run_in_threadpool(...). - Construir um novo cliente por requisição. Construir
anthropic.Anthropic()ouanthropic.AsyncAnthropic()dentro de um manipulador de requisição descarta o pooling de conexões a cada chamada. Correção: construa um cliente na inicialização do módulo ou da aplicação e reutilize-o. - Misturar chamadas
asyncio.run()dentro de um loop de eventos já em execução. Chamarasyncio.run(...)de dentro de um manipulador FastAPI (que já está dentro de um loop) levanta umRuntimeError. Correção:awaito cliente async diretamente no manipulador async em vez de envolvê-lo emasyncio.run(). awaitsequencial em um loop em vez deasyncio.gather.for doc in docs: await summarize(doc)executa as requisições uma por vez, desistindo da concorrência pela qual o cliente async foi escolhido. Correção: lance as corrotinas juntas e aguarde-as como um grupo comasyncio.gather(ou umasyncio.Semaphorelimitado para controlar a concorrência).- Esquecer
async withpara streaming async. Usarwithem vez deasync withemAsyncAnthropic().messages.stream(...)levanta umTypeError, já que o objeto de stream do cliente async é um gerenciador de contexto async. Correção: sempre combineAsyncAnthropic()streaming comasync witheasync for. - Assumir que o cliente async é mais rápido por chamada. Uma única requisição através de
AsyncAnthropic()leva o mesmo tempo de relógio que a mesma requisição através deAnthropic()- o benefício só aparece quando múltiplas requisições se sobrepõem. Correção: não mude para async apenas por razões de latência; mude-o por concorrência.
Alternativas
| Alternativa | Use Quando | Não Use Quando |
|---|---|---|
Anthropic() em um pool de threads (run_in_threadpool) | Um framework async precisa chamar um cliente síncrono sem bloquear o loop, por exemplo, reutilizando código síncrono existente | Você está escrevendo código novo do zero - apenas use AsyncAnthropic() diretamente |
AsyncAnthropic() em todos os lugares, mesmo em scripts | Você quer um tipo de cliente consistente em uma base de código que mistura scripts e serviços | O script não tem concorrência para explorar - a boilerplate asyncio.run() adiciona ruído sem ganho |
Múltiplos clientes Anthropic() em um pool de threads | Processamento em lote limitado por CPU onde cada thread de trabalho faz suas próprias chamadas sequenciais | Você precisa de controle granular sobre quantas requisições estão em voo ao mesmo tempo - asyncio.Semaphore com o cliente async é mais preciso |
FAQs
Eu perco algum recurso do SDK ao escolher o cliente síncrono em vez do assíncrono?
Não.
Anthropic() e AsyncAnthropic() suportam os mesmos parâmetros, o mesmo streaming e a mesma configuração de retentativa/timeout; a única diferença são as chamadas bloqueantes versus não bloqueantes.
Posso usar o cliente síncrono dentro de uma rota FastAPI?
Você pode, mas chamá-lo diretamente (sem um pool de threads) bloqueia o loop de eventos para todas as outras requisições sendo manipuladas por esse processo durante a chamada.
Prefira AsyncAnthropic() em rotas async, ou envolva a chamada síncrona em run_in_threadpool se você precisar reutilizar código síncrono existente.
Existe um custo de performance em usar AsyncAnthropic() em um script sem concorrência?
A latência por requisição é a mesma em ambos os casos.
O custo adicional é a complexidade do código: você precisa de asyncio.run(), async def, e await sem benefício de taxa de transferência se nada rodar concorrentemente.
Como faço para executar várias chamadas Claude ao mesmo tempo com o cliente async?
Use asyncio.gather para lançar múltiplas corrotinas antes de aguardá-las, em vez de aguardar cada uma sequencialmente em um loop. Veja a seção Notas Python acima.
Devo limitar quantas requisições rodam concorrentemente?
Sim, na maioria das cargas de trabalho de produção.
Envolva cada chamada com um asyncio.Semaphore dimensionado para um limite de concorrência sensato, para que um grande desdobramento não sobrecarregue seus limites de taxa ou o serviço de destino.
Django funciona com AsyncAnthropic()?
Django moderno suporta views async, então AsyncAnthropic() funciona lá também.
Views Django clássicas síncronas devem usar Anthropic() em vez disso, combinando com o modelo de execução do framework.
O que acontece se eu esquecer "await" em uma chamada AsyncAnthropic()?
Você recebe um objeto corrotina em vez de uma Message, e qualquer código que tente ler .content nele levanta um AttributeError. Python não executa o corpo da corrotina até que ela seja aguardada.
O cliente async é considerado beta ou experimental?
Não.
Tanto Anthropic() quanto AsyncAnthropic() são partes totalmente suportadas e geralmente disponíveis do mesmo pacote anthropic.
Posso mudar uma base de código de síncrona para assíncrona mais tarde sem reescrever?
Na maioria das vezes, sim.
Como ambos os clientes compartilham nomes de métodos e parâmetros, a migração geralmente significa adicionar async/await, trocar a classe do cliente e mudar with para async with para streaming - não redesenhar as chamadas em si.
O streaming se comporta de forma diferente entre os dois clientes?
O gerenciador de contexto de streaming existe em ambos, mas a versão async é um gerenciador de contexto async iterado com async for em vez de for. O stream subjacente de eventos é, de outra forma, o mesmo.
Qual cliente um worker Celery deve usar?
Workers Celery são tipicamente síncronos, uma tarefa por processo/thread de worker, então Anthropic() combina com esse modelo de execução, a menos que você esteja executando Celery com um pool async.
Relacionado
- O Modelo Mental do SDK Python da Anthropic - por que síncrono e assíncrono compartilham uma única superfície de API
- Streaming de Respostas com o SDK Python -
stream()em ambos os tipos de cliente - Tratando Uso de Ferramentas em Streaming em Fluxos de Trabalho Python Async - combinando
AsyncAnthropiccom uso de ferramentas - Referência de Configuração de Retentativa e Timeout do SDK Python -
max_retriesetimeoutem ambos os clientes
Versões da Stack: Escrito contra a linha de modelos Claude atual em ~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.