In una riunione di budget arrivano sempre due domande. Perché questa configurazione e non una più economica. E come faremo a sapere, fra sei mesi, che sta ancora funzionando. La prima è un problema di compromessi misurati, la seconda di telemetria decisa in anticipo.

Non ottimizzare la latenza prima di aver visto il tetto

L’ordine di lavoro è dichiarato: «It’s always better to first engineer a prompt that works well without model or prompt constraints, and then try latency reduction strategies afterward. Trying to reduce latency prematurely might prevent you from discovering what top performance looks like». Chi comprime subito non scoprirà mai qual era il massimo raggiungibile, e finirà per difendere una configurazione mediocre come se fosse un ottimo.

Le grandezze da distinguere sono la latenza di base e il tempo al primo token (TTFT), rilevante quando si usa lo streaming. La distinzione non è pedanteria: lo streaming migliora la reattività percepita, non riduce il tempo totale. Prometterlo come guadagno di latenza è il modo più rapido per farsi contestare al primo grafico.

Le leve, e quale muovere per prima

La prima leva non è il modello. Il parametro effort scambia intelligenza contro latenza e costo dentro un singolo modello, e la raccomandazione è netta: «Tuning effort is often a better lever than switching models». Cinque livelli, default high, e impostare high «produces exactly the same behavior as omitting the effort parameter entirely». Agisce su tutti i token in uscita, quindi a livelli bassi Claude fa meno chiamate ai tool e più terse. Resta però «a behavioral signal, not a strict token budget»: non è un tetto, e non va presentato come tale.

Il modello si sceglie poi, con due strategie esplicite. Efficiency-first parte da Claude Haiku 4.5 — il più rapido — e sale solo se una capacità manca. Capability-first parte da Claude Opus 5 e scende in seguito, ed è indicata quando l’accuratezza pesa più del costo.

C’è poi un vincolo incrociato che solo un architetto vede, e che salva conversazioni lunghe:

cambiare il livello di effort fra due richieste invalida la cache del prompt
-> tienilo costante dentro una conversazione che vive di cache hit
-> varialo fra carichi di lavoro diversi, non dentro lo stesso

Sui prompt e sugli output restano le leve ovvie, con un avvertimento: max_tokens è un limite netto che taglia anche a metà parola, quindi «a blunt technique» adatta a risposte brevi, non a testi che l’utente leggerà.

Difendere la configurazione: eval, non aneddoti

La decisione si giustifica con una suite, non con due prove a mano. Il punto di partenza è modesto: 20-50 compiti costruiti sui fallimenti reali. Poi due regole che evitano suite fragili. La prima riguarda l’oggetto: «it’s often better to grade what the agent produced, not the path it took», perché un agente che arriva al risultato per una strada diversa dalla vostra non ha sbagliato. La seconda riguarda il non determinismo: pass@k misura la probabilità che almeno un tentativo su k riesca, pass^k che riescano tutti. Un sistema che passa a pass@3 e crolla a pass^3 fallirà sotto gli occhi degli utenti.

Se il giudice è un modello, «model-based graders should be closely calibrated with human experts». E per il confronto fra modelli: «having a good evaluation set is the most important step in the process».

Un limite va dichiarato invece di riempirlo con nozioni generiche: la documentazione non pubblica un SLA di latenza per richiesta né una metodologia di A/B testing. Il Priority Tier documenta un obiettivo di uptime del 99,5% per chi ha già un impegno di capacità, ma non è più acquistabile; il tier standard è «best-effort availability». Qualunque impegno di latenza verso il business è vostro, derivato dalle vostre misure.

Osservabilità: cosa esce di default, cosa devi accendere, cosa costa

La telemetria è spenta finché non si imposta CLAUDE_CODE_ENABLE_TELEMETRY=1 più almeno un exporter. I tre segnali OpenTelemetry hanno interruttori indipendenti, e le trace richiedono anche il flag beta.

metriche  : claude_code.token.usage, claude_code.cost.usage, claude_code.session.count,
            claude_code.code_edit_tool.decision, claude_code.active_time.total
eventi    : tool_decision, tool_result, api_request, api_error, api_refusal,
            permission_mode_changed, mcp_server_connection
span      : claude_code.interaction > claude_code.llm_request | claude_code.tool | hook

Il dettaglio che cambia la diagnosi su architetture multi-agente: gli span di un subagent si annidano sotto lo span claude_code.tool del genitore, così l’intera catena di delega appare come una sola trace. Senza questo, un fallimento in un subagent è indistinguibile da una chiamata a tool lenta.

Tre problemi emergono solo su scala. Il primo è il silenzio: «the CLI fails silently on export errors by default», cioè l’agente continua a funzionare e la telemetria sparisce; serve la diagnostica esplicita su stderr. Il secondo è la privacy: i contenuti non sono registrati per impostazione predefinita, e le variabili che aggiungono prompt, argomenti dei tool o corpi completi vanno lasciate spente «unless your observability pipeline is approved to store the data your agent handles». Il terzo è l’attribuzione: gli attributi di identità identificano la credenziale del vostro servizio, non l’utente finale, quindi in multi-tenant enduser.id e tenant.id vanno iniettati come resource attribute. Fatto questo, gli eventi di decisione sui tool diventano una pista di audit per utente da inoltrare al SIEM.

Sulla cardinalità la regola resta un compromesso: «lower cardinality generally means better performance and lower storage costs but less granular data for analysis». E i valori di costo possono essere rivisti fino a 30 giorni: non costruiteci sopra un cruscotto in tempo reale.