Sua Primeira Chamada de API em Produção (Consciente de Custo)
Intermediário
Uma chamada de API de brinquedo tem uma linha. Uma chamada de produção trata erros, faz streaming da saída, monitora o custo e mantém os segredos seguros. Vamos construir isso, passo a passo.
Passo 1 — Segredos & modelo a partir da configuração
export ANTHROPIC_API_KEY="sk-ant-..." # never in source control
Mantenha o ID do modelo na configuração, não espalhado em literais, para que a migração seja trivial (por quê). Escolha-o deliberadamente — Escolhendo um Modelo.
Passo 2 — Uma chamada resiliente, com streaming
- Python
- TypeScript
import os, time, random, anthropic
client = anthropic.Anthropic()
MODEL = os.environ.get("CLAUDE_MODEL", "claude-sonnet-5")
def ask_stream(prompt, system=None, max_tokens=1024):
for attempt in range(5):
try:
with client.messages.stream(
model=MODEL, max_tokens=max_tokens,
system=system or anthropic.NOT_GIVEN,
messages=[{"role": "user", "content": prompt}],
) as stream:
for text in stream.text_stream:
print(text, end="", flush=True)
final = stream.get_final_message()
print()
usage = final.usage
print(f"\n[tokens in/out: {usage.input_tokens}/{usage.output_tokens}]")
return final
except (anthropic.RateLimitError, anthropic.APIStatusError):
if attempt == 4: raise
time.sleep(min(2 ** attempt + random.random(), 30))
import Anthropic from "@anthropic-ai/sdk";
const client = new Anthropic();
const MODEL = process.env.CLAUDE_MODEL ?? "claude-sonnet-5";
export async function askStream(prompt: string, system?: string, maxTokens = 1024) {
for (let attempt = 0; attempt < 5; attempt++) {
try {
const stream = client.messages.stream({ model: MODEL, max_tokens: maxTokens, system,
messages: [{ role: "user", content: prompt }] });
for await (const e of stream)
if (e.type === "content_block_delta") process.stdout.write(e.delta.text ?? "");
const final = await stream.finalMessage();
console.error(`\n[tokens in/out: ${final.usage.input_tokens}/${final.usage.output_tokens}]`);
return final;
} catch (e: any) {
if (attempt === 4 || ![429, 500, 529].includes(e?.status)) throw e;
await new Promise(r => setTimeout(r, Math.min(2 ** attempt * 1000, 30000)));
}
}
}
Passo 3 — Atenção ao custo
- Registre o uso de tokens (acima) para que você possa ver quanto custa cada chamada.
- Dimensione corretamente
max_tokense o modelo; limite a entrada com prompts focados. - Para prefixos estáveis e repetidos, adicione cache de prompt.
- Veja Tokens & Preços e Custo & Latência.
Passo 4 — Trate os caminhos infelizes
- Repita erros transitórios (429/5xx) com backoff (acima); não repita erros 400.
- Trate recusas com elegância.
- Defina um timeout e um orçamento de custo/iterações para qualquer coisa agêntica.
Verifique
Execute-a: você deve ver a saída em streaming, uma linha de uso de tokens e um comportamento elegante se forçar um erro (por exemplo, uma chave inválida → mensagem limpa, não uma falha).