🔗
API da Anthropic: messages, streaming, vision, batch e cache
⏱ 15 min de leitura·+75 XP
Pré-requisitos (0/1)0%
- ⬜⊕ O ecossistema Anthropic: Claude, modelos, produtos e roadmap(Claude & Anthropic na Prática)
Recomendamos completar os pré-requisitos antes de seguir, mas nada te impede de continuar.
A API Messages da Anthropic é o primitivo fundamental para construir qualquer aplicação com Claude integrado. Não é um wrapper de chat — é uma API de geração de texto com primitivos para streaming, processamento de imagens, cache de prompts e processamento em lote. Entender cada um é o que separa uma integração amadora de uma que funciona em produção.
Messages API: a estrutura básica
# SDK Python — pip install anthropic
import anthropic
client = anthropic.Anthropic(api_key="sk-ant-...")
# Request básico
response = client.messages.create(
model="claude-sonnet-4-5",
max_tokens=1024,
system="Você é um assistente técnico especialista em Python. Responda em PT-BR.",
messages=[
{"role": "user", "content": "Explique o GIL em 3 frases"}
]
)
print(response.content[0].text)
print(f"Tokens usados: {response.usage.input_tokens} in, {response.usage.output_tokens} out")
# Conversa multi-turno
messages = []
messages.append({"role": "user", "content": "O que é o GIL?"})
# (chamada à API retorna resposta)
messages.append({"role": "assistant", "content": response.content[0].text})
messages.append({"role": "user", "content": "E como isso afeta o asyncio?"})
# Nova chamada com o histórico completo
# IMPORTANTE: a API é stateless — você é responsável por enviar
# o histórico completo de mensagens a cada request.
# Não há sessão no servidor. Todo o estado fica no cliente.Streaming: respostas em tempo real
# Streaming: o modelo envia tokens à medida que gera
import anthropic
client = anthropic.Anthropic()
# Context manager para streaming
with client.messages.stream(
model="claude-sonnet-4-5",
max_tokens=1024,
messages=[{"role": "user", "content": "Escreva um poema sobre o GIL"}]
) as stream:
for text in stream.text_stream:
print(text, end="", flush=True)
print() # nova linha ao final
# Com eventos completos (para saber quando termina, ver stop_reason, etc.)
with client.messages.stream(...) as stream:
for event in stream:
if event.type == "content_block_delta":
print(event.delta.text, end="", flush=True)
elif event.type == "message_stop":
print(f"
Stop reason: {stream.get_final_message().stop_reason}")
# SDK TypeScript/JavaScript:
import Anthropic from "@anthropic-ai/sdk";
const client = new Anthropic();
const stream = await client.messages.stream({
model: "claude-sonnet-4-5",
max_tokens: 1024,
messages: [{ role: "user", content: "Hello" }],
});
for await (const chunk of stream) {
if (chunk.type === "content_block_delta") {
process.stdout.write(chunk.delta.text);
}
}
# Para Next.js API Routes (streaming SSE):
export async function POST(req: Request) {
const encoder = new TextEncoder();
const stream = new TransformStream();
const writer = stream.writable.getWriter();
const anthropicStream = await client.messages.stream({ ... });
(async () => {
for await (const chunk of anthropicStream) {
if (chunk.type === "content_block_delta") {
await writer.write(encoder.encode(`data: ${chunk.delta.text}
`));
}
}
await writer.close();
})();
return new Response(stream.readable, {
headers: { "Content-Type": "text/event-stream" },
});
}Vision: processar imagens com Claude
# Claude Sonnet e Opus suportam imagens (Haiku tem suporte limitado)
# Formatos: JPEG, PNG, GIF, WebP
# Limite: até 20 imagens por request; cada imagem ≤ 5MB
import anthropic, base64
client = anthropic.Anthropic()
# Opção 1: URL pública (mais simples)
response = client.messages.create(
model="claude-sonnet-4-5",
max_tokens=1024,
messages=[{
"role": "user",
"content": [
{
"type": "image",
"source": {
"type": "url",
"url": "https://exemplo.com/screenshot.png"
}
},
{
"type": "text",
"text": "Descreva o que está nesta imagem e identifique eventuais problemas de UI."
}
]
}]
)
# Opção 2: Base64 (para imagens locais ou sem URL pública)
with open("screenshot.png", "rb") as f:
image_data = base64.standard_b64encode(f.read()).decode("utf-8")
response = client.messages.create(
model="claude-sonnet-4-5",
max_tokens=1024,
messages=[{
"role": "user",
"content": [
{
"type": "image",
"source": {
"type": "base64",
"media_type": "image/png",
"data": image_data
}
},
{"type": "text", "text": "Existe algum erro ou warning neste screenshot de log?"}
]
}]
)
print(response.content[0].text)
# Custo de imagem: aproximadamente 1.600 tokens base + tokens por dimensão
# 1080x1080 px ≈ 1.600 tokens ≈ $0.005 com Sonnet (input)
# Otimização: redimensione imagens para max 1.568px no lado maior antes de enviarPrompt Caching: reduzir custo em APIs de alto volume
# Prompt caching: marque seções que não mudam entre requests
# Caso ideal: system prompt longo + documentos de referência + pergunta do usuário
# O system + documentos ficam cacheados; apenas a pergunta varia
import anthropic
client = anthropic.Anthropic()
# Documento de referência longo (1000+ tokens) que é o mesmo em todos os requests
MANUAL_TECNICO = """
# Manual Técnico do Sistema de Pagamentos
[... milhares de linhas de documentação ...]
"""
def perguntar_sobre_manual(pergunta: str) -> str:
response = client.messages.create(
model="claude-sonnet-4-5",
max_tokens=1024,
system=[
{
"type": "text",
"text": "Você é um assistente especialista no manual técnico abaixo.",
"cache_control": {"type": "ephemeral"} # ← cacheia esta parte
},
{
"type": "text",
"text": MANUAL_TECNICO,
"cache_control": {"type": "ephemeral"} # ← cacheia o manual também
}
],
messages=[{"role": "user", "content": pergunta}] # ← não cacheado (varia)
)
# Verificar se o cache foi usado:
usage = response.usage
print(f"Input normal: {usage.input_tokens} tokens")
print(f"Input cacheado: {usage.cache_read_input_tokens} tokens (10% do preço)")
print(f"Cache criado: {usage.cache_creation_input_tokens} tokens (110% do preço, uma vez)")
return response.content[0].text
# Primeiro request: paga 110% para criar o cache (uma vez)
# Requests subsequentes (dentro de 5min): paga 10% para a parte cacheada
# Economia real em 100 requests: ~80-90% do custo de inputBatch API: processamento em lote com 50% de desconto
# Messages Batch API — para alto volume sem urgência de latência
import anthropic, json
from datetime import datetime
client = anthropic.Anthropic()
# Criar um batch de requests
batch = client.messages.batches.create(
requests=[
{
"custom_id": f"analise-{i}", # ID único para rastrear o resultado
"params": {
"model": "claude-haiku-4-5", # Haiku + batch = custo mínimo
"max_tokens": 500,
"messages": [{
"role": "user",
"content": f"Classifique o sentimento deste review: {review}"
}]
}
}
for i, review in enumerate(lista_de_reviews) # até 10.000 por batch
]
)
print(f"Batch criado: {batch.id}")
print(f"Status: {batch.processing_status}") # "in_progress"
# Verificar status (polling — geralmente termina em minutos)
import time
while True:
batch = client.messages.batches.retrieve(batch.id)
if batch.processing_status == "ended":
break
print(f"Aguardando... {batch.request_counts}")
time.sleep(30)
# Processar resultados
for result in client.messages.batches.results(batch.id):
if result.result.type == "succeeded":
texto = result.result.message.content[0].text
print(f"{result.custom_id}: {texto}")
else:
print(f"{result.custom_id}: ERRO - {result.result.error}")
| Abordagem | Latência | Custo | Ideal para |
|---|---|---|---|
| Síncrono + streaming | < 1s TTFT | 100% | Chat, interfaces interativas |
| Síncrono sem stream | 5-30s | 100% | Scripts, automação simples |
| Batch API | Minutos-horas | 50% | Análise em lote, pipelines offline |
| Síncrono + cache | < 1s | ~15-20%* | APIs com system prompt fixo |
* Para a parte cacheada. Custo total depende do tamanho do cache vs mensagem do usuário.
✅
Decisão de API: interface de usuário → streaming obrigatório. System prompt longo e fixo → prompt caching obrigatório. Processamento em lote sem urgência → Batch API com Haiku = custo mínimo. Vision quando precisar processar screenshots, diagramas ou documentos escaneados. A combinação caching + Haiku para APIs internas de alto volume pode reduzir custo em 10-20x versus Opus síncrono sem cache.
💡
Próximo: Prompt engineering para Claude — as técnicas que realmente funcionam: XML tags, chain-of-thought, prefill, few-shot e como extrair JSON confiável.
🧩
Quiz rápido
3 perguntas · Acerte tudo e ganhe o badge 🎯 Gabarito
Continue lendo