La tua prima chiamata API in produzione (attenta ai costi)
- Nominare le quattro discipline che separano una chiamata di produzione da una riga giocattolo: segreti, streaming, costi e gestione degli errori
- Scrivere una chiamata resiliente in streaming che riprova i fallimenti transitori (429/5xx) con backoff — e non riprova mai un 400
- Tenere l'ID del modello nella configurazione, così cambiare modello è una modifica di una riga e non un cerca-e-sostituisci
- Tenere d'occhio il costo in token a ogni chiamata e limitarlo in modo deliberato
Una chiamata API di esempio è una sola riga. Una chiamata di produzione gestisce gli errori, trasmette l'output in streaming, tiene d'occhio i costi e protegge i segreti. Costruiamola, passo dopo passo.
Passo 1 — Segreti e modello dalla configurazione
export ANTHROPIC_API_KEY="sk-ant-..." # never in source control
Tieni l'ID del modello nella configurazione, non in valori letterali sparsi nel codice, così la migrazione è banale (perché). Scegli con criterio — Scegliere un modello.
Passo 2 — Una chiamata resiliente in 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)));
}
}
}
Fai uno smoke test prima di collegarla a qualsiasi cosa — una piccola chiamata dimostra che lo streaming, la riga dei token e la tua chiave funzionano tutti:
Primo smoke test (REPL Python)
ask_stream("Say hello in one sentence.", max_tokens=64)Passo 3 — Tieni d'occhio i costi
- Registra l'uso dei token (qui sopra) così puoi vedere quanto costa ogni chiamata.
- Dimensiona correttamente
max_tokense il modello; limita l'input con prompt mirati. - Per prefissi stabili e ripetuti, aggiungi il prompt caching.
- Vedi Token e prezzi e Costo e latenza.
Passo 4 — Gestisci i percorsi infelici
- Riprova gli errori transitori (429/5xx) con backoff (qui sopra); non riprovare i 400.
- Gestisci i rifiuti in modo elegante.
- Imposta un timeout e un budget di costo/iterazioni per qualsiasi cosa agentica.
Verifica
Forza ogni percorso e osserva cosa succede — una chiamata di produzione si guadagna il nome fallendo bene, non solo riuscendo:
Guided walkthrough1 of 4
- Il testo viene stampato progressivamente man mano che è generato, non in un unico blocco bloccante alla fine. È il guadagno di latenza che gli utenti percepiscono.
- Dopo la risposta vedi la riga [tokens in/out: …]. È il tuo contatore di costo per chiamata, registrato a ogni chiamata.
- Imposta ANTHROPIC_API_KEY su un valore sbagliato e riesegui — dovresti ottenere un errore pulito, non un crash con stack trace.
- Gli errori 429/5xx vengono riprovati con backoff fino a 5 tentativi; una richiesta 400 malformata deve emergere subito invece di essere riprovata inutilmente.
Mettiti alla prova
0/3- Una chiamata di produzione è quattro discipline sovrapposte alla riga singola: segreti fuori dal codice sorgente, output in streaming, costo monitorato, errori gestiti
- Riprova i fallimenti transitori (429/5xx) con backoff esponenziale più jitter — e non riprovare mai un 400, che è un bug della richiesta da correggere
- Tieni l'ID del modello nella configurazione, così cambiare modello è una riga e non un cerca-e-sostituisci su tutto il codice
- Registra l'uso dei token a ogni chiamata: è il tuo contatore di costo per richiesta e aggiungerlo non costa nulla
- Lo streaming migliora la latenza percepita; timeout e un budget di costo/iterazioni impediscono ai loop agentici di scappare di mano