Gli agenti AI con Anthropic SDK 0.100–0.102: cosa eliminare su Cloudflare

Con Anthropic SDK 0.100–0.102, outcome e webhook sostituiscono parte dell’orchestrazione: ecco quali componenti Cloudflare eliminare e quali mantenere.

Saturday, September 5, 2026Omid Saffari
Gli agenti AI con Anthropic SDK 0.100–0.102: cosa eliminare su Cloudflare

Tra il 6 e il 13 maggio, l’Anthropic Python SDK ha pubblicato in sequenza le versioni 0.100.0, 0.101.0 e 0.102.0: tre release in otto giorni che hanno trasformato Managed Agents in un runtime hosted per agenti AI, completo di outcome, webhook e orchestrazione multiagente. Ho passato al setaccio il mio stack Cloudflare basato su 6 Durable Object per capire che cosa sostituisca davvero client.beta.managed_agents.sessions.create(). La risposta, senza giri di parole: circa 280 righe di codice per retry e polling in due step del workflow. Tutto il resto rimane.

Cosa cambia per gli agenti AI gestiti con SDK 0.100–0.102

Tre release in otto giorni hanno ampliato l’API dell’SDK Python più di quanto fosse accaduto nei sei mesi precedenti. Le date contano: chi in produzione è rimasto su anthropic==0.99.x si è perso l’intero runtime Managed Agents nell’arco di un solo sprint.

v0.100.0 (6 maggio 2026) ha aggiunto al namespace beta il supporto per multiagent, outcome e webhook, oltre alla convalida del vault. Il cambiamento decisivo è questo: client.beta.managed_agents.sessions.create(thread=..., outcome=..., metadata=...) restituisce un session_id ed esegue il lavoro in modo asincrono sull’infrastruttura Anthropic. Il ciclo di orchestrazione non è più a carico dell’applicazione.

v0.101.0 (11 maggio 2026) ha introdotto il client AWS per Claude Platform on AWS e aggiornato tutti gli esempi dei cookbook a claude-sonnet-4-5-20250929. Per chi usa Bedrock, è questa la release necessaria: il supporto alla variabile d’ambiente ANTHROPIC_BEDROCK_SERVICE_TIER (default/flex/priority) è arrivato qui, non nella 0.100.

v0.102.0 (13 maggio 2026) ha aggiunto i tipi BetaManagedAgentsSearchResultBlock, la diagnostica della cache per la beta del prompt caching e la convalida eager degli iteratori Pydantic. La superficie dei tipi di blocco è ancora in evoluzione, ed è il motivo principale per cui non sto ancora migrando il mio codice multiagente.

La novità centrale sono gli outcome. Si definisce una rubrica, un agente valutatore separato assegna un giudizio al risultato e l’agente riprova finché non supera la verifica. Secondo l’eval interno di Anthropic, il successo delle attività migliora fino a +10 punti rispetto ai normali cicli di prompting, con +8.4% nella generazione di docx e +10.1% in quella di pptx. È coerente con ciò che osservo nel mio Critic Durable Object: un singolo re-prompt corredato dalle note del valutatore vale all’incirca un salto di fascia nella qualità del modello.

L’altra metà del cambiamento sono i webhook. Otto eventi di sessione vengono inviati a un URL registrato nella Claude Console: session.status_run_started, session.status_idled, session.status_rescheduled, session.status_terminated, session.thread_created, session.thread_idled, session.thread_terminated e, soprattutto, session.outcome_evaluation_ended. Il signing secret ha il formato whsec_… e viene mostrato una sola volta al momento della creazione. La verifica si esegue con client.webhooks.unwrap(payload, signature, secret).

È arrivata anche l’orchestrazione multiagente, ma è subordinata a una richiesta di accesso alla research preview. Più avanti spiego perché, per ora, non attiverò quell’opzione.

Cosa cambia per i founder senza un profilo tecnico

Ora è Anthropic a eseguire l’agente. Si scrive la rubrica («l’articolo ha raggiunto 2,000 parole, cita tre fonti primarie e supera la regex anti-AI?»), l’agente valutatore di Anthropic controlla l’output e rilancia l’agente finché la verifica non passa. L’ingegnere non deve più implementare il ciclo di retry.

Sul costo ci sono due effetti. Il primo è la riduzione dei cicli di retry artigianali nel codebase, quindi meno tempo di un senior engineer assorbito dalla loro manutenzione. Il secondo è l’aumento dei tentativi all’interno della sessione Anthropic, ognuno addebitato a $0.08 per ora di sessione oltre ai token. Il vantaggio netto dipende interamente dalla durata delle sessioni.

In concreto: se il team sta lanciando la v1 di un prodotto agentico, Managed Agents sostituisce circa il 40% del codice di orchestrazione che altrimenti dovrebbe scrivere un senior engineer. Se il prodotto è già in produzione, la porzione è più piccola; i webhook, però, eliminano il ciclo di polling che quasi certamente esiste da qualche parte.

La domanda da fare al CTO questa settimana è: «Stiamo ancora interrogando il sistema in polling per sapere quando ha finito, oppure siamo già passati a session.outcome_evaluation_ended Se la risposta è «polling», basta un refactoring di mezza giornata per ridurre insieme costo infrastrutturale e latenza delle richieste.

Lo stack Cloudflare che uso oggi

Per capire che cosa si può eliminare, partiamo dall’architettura attuale: un singolo worker Hono su Cloudflare Workers (target ES2021 e binding Static Assets) espone sei Durable Object, uno per ogni routine di pubblicazione. Editorial, Discovery, Writer, Distribution, Maintenance e Manager, più un settimo, ManualIntake, a supporto dell’interfaccia di amministrazione.

Ogni routine viene avviata tramite uno dei sei Cloudflare Workflows: PublishWorkflow, WriteArticle, PublishArticle, EnrichIdea, DiscoverIdeas, DistributeArticle. Quello che svolge più lavoro è PublishWorkflow, articolato in otto step idempotenti: validate, ground, generate, clean, persist, index, cover, publish. Ogni step di I/O è racchiuso in:

TypeScript
const result = await step.do(
  "generate-article",
  { retries: { limit: 3, backoff: "exponential" } },
  async () => env.WRITER.generate(brief)
);

D1 conserva lo stato canonico (transizioni di editorial_brief.status: dispatcheddraftingpublished / failed). Vectorize gestisce gli embedding per singolo blocco (Gemini-2 768d, formato di retrieval asimmetrico). Tutte le chiamate a modelli a pagamento passano da un unico punto di controllo, callAi(env, ctx, runner), che registra in ai_call_log i campi agent_id, workflow_instance_id e idea_id per aggregare i costi, applicando un tetto giornaliero di $20 e un limite di $1 per istanza.

È l’architettura con 6 DO che ho descritto in precedenza. Ai fini della migrazione a Managed Agents, conta soprattutto dove risiede la logica di retry. È in due punti:

  1. Retry degli step del workflow (economici, gratuiti se la chiamata sottostante va a buon fine): problemi di rete momentanei, rate limit ed errori 5xx transitori dei provider upstream.
  2. Un ciclo “judge-and-retry” scritto a mano in clean.ts: esegue Writer, poi Critic rispetto a una rubrica e, se score < 0.75, ripete il prompt allegando le note di Critic, per un massimo di 3 tentativi.

Managed Agents sostituisce il secondo. Il primo resta.

Le 280 righe che SDK 0.100 permette di eliminare

Il ciclo judge-and-retry in src/worker/workflows/publish/clean.ts è il candidato più diretto per la conversione agli outcome. Oggi occupa circa 120 righe di orchestrazione: invoca Writer, esegue Critic sulla rubrica conservata in editorial_brief.rubric_md, interpreta il punteggio, verifica la soglia, ripete il prompt inserendo le note come blocco di sistema e ricomincia, fino a tre tentativi. Critic richiede altre 80 righe di Durable Object (hook di ibernazione, SQLite per istanza per lo storico delle rubriche, chiavi di idempotenza per ogni tentativo). L’aggregazione per tentativo in ai_call_log, dentro callAi.ts, vale altre 40 righe, perché ogni tentativo viene registrato separatamente e poi riunito nella dashboard.

Tutti e tre i blocchi si riducono a una sola chiamata a Managed Agents:

TypeScript
const session = await anthropic.beta.managedAgents.sessions.create({
  thread: { messages: [{ role: "user", content: brief.body_md }] },
  outcome: {
    rubric: brief.rubric_md,
    evaluator: "claude-sonnet-4-5-20250929"
  },
  metadata: { brief_id: brief.id, workflow_instance: ctx.instanceId }
});
return { session_id: session.id, status: "pending" };

Tutto qui. La sessione viene completata in modo asincrono sull’infrastruttura Anthropic. Il parametro outcome svolge il lavoro prima affidato al Critic DO: un agente valutatore separato giudica l’output rispetto alla rubrica e rilancia l’agente principale finché il risultato non supera la verifica.

Il codice da aggiungere è una route in /api/admin/webhooks/managed-agents: verifica la firma whsec_…, intercetta event.type === "session.outcome_evaluation_ended" e scrive il risultato in D1.

TypeScript
app.post("/api/admin/webhooks/managed-agents", async (c) => {
  const raw = await c.req.text();
  const event = await anthropic.webhooks.unwrap(
    raw, c.req.header("anthropic-signature")!, c.env.WEBHOOK_SECRET
  );

  if (event.type !== "session.outcome_evaluation_ended") {
    return c.json({ ok: true });
  }

  await c.env.DB.update(editorial_brief).set({
    status: event.outcome.passed ? "published" : "failed",
    body_md: event.result.body,
    session_cost_usd: event.session.usage.total_cost_usd
  }).where(eq(editorial_brief.id, event.session.metadata.brief_id));

  return c.json({ ok: true });
});

Quaranta righe, firma verificata e idempotenza garantita dalla chiave brief_id.

Diff netto: 240 righe di orchestrazione in meno. Un binding Durable Object in meno in wrangler.json. Un file di migrazione in meno. In compenso, 40 righe per gestire il webhook e un secret nel Cloudflare Secrets Store.

L’endpoint di polling GET /api/admin/workflows/:id/status continua a funzionare. Ora legge da D1 lo stato della sessione, popolato dal webhook, anziché ottenerlo da env.PUBLISH_WORKFLOW.get(id).status(). L’interfaccia non cambia e la dashboard di amministrazione non si accorge della differenza.

C’è un punto da sottolineare: i wrapper di retry step.do restano su tutti gli altri step di I/O. Generazione dell’immagine di copertina, revalidation di Vercel e purge della cache Cloudflare non traggono alcun vantaggio dalle rubriche degli outcome, mentre beneficiano tutti della cache replay-safe degli step di Workflows. Non va rimosso ciò che funziona.

Il file che conservo e il punto in cui i costi cambiano scala

callAi.ts rimane. Tetto giornaliero di $20, limite di $1 per istanza. Ogni chiamata a pagamento passa da qui, sia quella diretta, sia quella tramite AI Gateway o Managed Agents.

Il motivo sta nel modello di costo. Managed Agents fattura su tre assi: token alle tariffe standard, più $0.08 per ora di sessione, più $10 ogni 1000 ricerche web. Con i miei volumi — sei routine di pubblicazione, un articolo per ogni esecuzione e circa 3 minuti per sessione — il costo per ora di sessione aggiunge circa $0.004 per articolo oltre ai token. Irrilevante.

Il quadro cambia quando le sessioni si allungano. Una sessione Anthropic Skills di 4 ore costa $0.32 solo di runtime, oltre ai token. Con 50 sessioni di questo tipo al giorno, sono $480 al mese di sole ore di sessione, prima ancora dei token. Una sessione di ricerca multi-step che rimane un’ora in attesa nella coda di una ricerca web costa $0.08 che prima non sarebbero stati addebitati. Anche il tempo di inattività mentre la sessione attende un servizio downstream viene fatturato: la documentazione Anthropic indica una misurazione al millisecondo e, nel frattempo, il contatore continua a girare.

Il punto di controllo impone un limite rigido che la dashboard di Managed Agents non offre. La dashboard mostra il costo della sessione a posteriori. callAi.ts, invece, genera un NonRetryableError nel mezzo del workflow, prima dell’avvio della sessione, se la stima preliminare supera il tetto giornaliero.

La stima preliminare è prudenziale:

TypeScript
async function estimateSessionCost(brief: Brief): Promise<number> {
  const tokenEstimate = brief.body_md.length / 3.5;
  const inputCost = (tokenEstimate / 1_000_000) * 3.0;
  const outputCost = (tokenEstimate * 1.5 / 1_000_000) * 15.0;
  const sessionHourEstimate = (brief.expected_minutes / 60) * 0.08;
  const safetyMargin = 1.4;
  return (inputCost + outputCost + sessionHourEstimate) * safetyMargin;
}

Il calcolo del costo per ora di sessione è il punto in cui le configurazioni da solo engineer deragliano più rapidamente. Senza un tetto, un singolo agente fuori controllo — proprio il comportamento che il ciclo di retry basato su outcome può favorire quando la rubrica è troppo rigida — consuma il budget giornaliero prima che qualcuno se ne accorga. Mi è successo.

Il punto di controllo va mantenuto. La chiamata sessions.create() deve passare da lì. Prima dell’avvio della sessione va registrata la stima preliminare; al termine, il dato effettivo ricevuto in event.session.usage.total_cost_usd dal payload del webhook va riconciliato con quella stima.

La migrazione che rimando: l’orchestrazione multiagente

L’orchestrazione multiagente è stata la funzionalità di punta dell’Anthropic Dev Day. Un agente lead scompone il lavoro e assegna i sotto-task ad agenti specialisti, ciascuno con modello, prompt e tool propri. I subagent lavorano in parallelo su un filesystem condiviso, poi il lead aggrega i risultati. Sulla carta coincide esattamente con ciò che fa oggi il mio Manager DO: distribuisce il lavoro in parallelo a Writer, Discovery e Distribution tramite DO RPC, ognuno con il proprio stato SQLite, usando R2 + D1 come “filesystem” condiviso.

Per ora mi fermano tre motivi.

Primo: l’API cambia ancora. L’orchestrazione multiagente è in research preview e richiede un accesso separato. BetaManagedAgentsSearchResultBlock è appena arrivato nella 0.102. La superficie dei tipi di blocco per i risultati multiagente è ancora instabile. Migrare ora significherebbe riscrivere l’integrazione a ogni aggiornamento dell’SDK per le prossime due o tre release. I webhook si sono stabilizzati nella 0.100; il multiagent è ancora in movimento.

Secondo: il filesystem condiviso è effimero e limitato alla singola sessione. All’interno di una sessione Managed Agents, il filesystem condiviso scompare quando la sessione termina. R2 e D1 persistono fra tutte le mie routine, sono interrogabili da qualunque worker e sopravvivono a un crash della sessione. Finché il filesystem condiviso non diventerà persistente — o finché non potrò montare R2 direttamente nel sandbox della sessione — per il mio carico di lavoro questa resta una regressione.

Terzo: la separazione lead/subagent di Anthropic impone una struttura precisa. Il ruolo di agente lead è fisso. Il mio Editorial DO è il lead in alcuni giorni, quando parte una routine di pubblicazione, e un peer in altri, quando l’interfaccia di amministrazione invia un brief ed Editorial entra nella pipeline a metà processo. Adattarmi all’astrazione hosted significherebbe appiattire un’asimmetria utile.

La condizione che mi farebbe cambiare idea è un filesystem condiviso persistente e utilizzabile tra sessioni, oppure la possibilità di montare R2 nel sandbox. Oggi sarebbe un passaggio laterale, non un miglioramento.

Checklist di migrazione esatta per SDK 0.100–0.102

  1. Bloccare la versione dell’SDK

    Bash
    uv add anthropic@0.102.0

    In alternativa, pip install anthropic==0.102.0 per chi non usa ancora uv. Non conviene fermarsi alla 0.100 o alla 0.101, a meno che non esista un motivo specifico legato a Bedrock per scegliere la 0.101.

  2. Registrare il webhook nella Claude Console

    Claude Console → Settings → Webhooks → New endpoint. L’endpoint deve puntare a https://your-worker.example.com/api/admin/webhooks/managed-agents. Copiare il secret whsec_…, mostrato una sola volta alla creazione, e conservarlo nel Cloudflare Secrets Store (oppure in AWS Secrets Manager se si usa Claude Platform on AWS tramite SDK 0.101).

  3. Aggiungere la route del webhook

    Creare /api/admin/webhooks/managed-agents. Verificare la firma con client.webhooks.unwrap(payload, signature, secret) (l’helper è arrivato nella v0.95.x ed è stabile nella 0.100). La chiamata unwrap gestisce in un solo passaggio HMAC, tolleranza del timestamp e parsing del tipo di evento. Non conviene implementare da zero la verifica HMAC: la finestra ammessa per lo scarto temporale non è intuitiva.

  4. Convertire lo step di valutazione

    Sostituire il ciclo judge-and-retry con outcome={rubric: brief.rubric_md, evaluator: "claude-sonnet-4-5-20250929"} in sessions.create(). Eliminare il Critic DO e la relativa orchestrazione dei retry. La rubrica resta in D1: la sua colonna diventa più importante, non meno.

  5. Passare dal polling alle letture su D1

    L’endpoint di stato ora legge da D1, usando come chiave event.session.metadata.brief_id — o qualunque chiave di correlazione sia stata impostata in metadata su sessions.create(). Il webhook scrive, l’endpoint di stato legge. Le chiamate ripetute a workflow.status() non servono più.

  6. Mantenere il punto di controllo dei costi

    callAi.ts rimane. Stimare in anticipo il costo della sessione e generare un NonRetryableError se la stima supera il tetto giornaliero. Nel gestore del webhook, registrare i costi effettivi dopo il completamento da event.session.usage. Ogni settimana, confrontare stime preliminari e dati effettivi; se lo scarto supera il 25%, correggere il margine di sicurezza.

  7. Provare prima la routine meno critica

    Nel mio caso è stata Discovery, perché un malfunzionamento della migrazione non produce output pubblico. Va eseguita per 72 ore in parallelo al vecchio percorso, confrontando i risultati. Solo dopo si migra Writer.

Posso usare SDK 0.100 con la configurazione Anthropic Bedrock esistente?

Sì, ma il client AWS dedicato è arrivato nella 0.101. Chi usa Bedrock dovrebbe superare la 0.100. SDK 0.101 ha inoltre introdotto il supporto alla variabile d’ambiente ANTHROPIC_BEDROCK_SERVICE_TIER (default/flex/priority), assente nella 0.100.

I webhook sostituiscono del tutto l’API di risposta in streaming?

No. I webhook vengono emessi per gli eventi del ciclo di vita della sessione (started, idled, terminated, outcome-evaluation-ended). Le risposte in streaming continuano a passare da messages.create(stream=True) e dal normale protocollo delta. I webhook servono a dire «avvisami quando la sessione di lunga durata è terminata»; lo streaming a «mostrami i token mentre arrivano».

Qual è il formato del signing secret e come si verifica?

Il prefisso è whsec_… e il secret viene mostrato una sola volta alla creazione nella Console. La verifica passa da client.webhooks.unwrap(raw_body, signature_header, secret), che gestisce HMAC, tolleranza del timestamp e parsing del tipo di evento in un’unica chiamata. Il secret grezzo non va registrato nei log né passato come parametro della query. Va conservato nel Cloudflare Secrets Store o in un sistema equivalente.

Posso valutare gli outcome senza Managed Agents, usando solo la Messages API?

No. outcome={rubric, evaluator} è un parametro riservato a Managed Agents in sessions.create(). È possibile costruire lo stesso meccanismo con la Messages API — ed è ciò che fa oggi il mio Critic DO — ma in quel caso si paga la latenza dell’orchestrazione e se ne mantiene il codice. Managed Agents nasce proprio per evitarlo.

Il prompt caching funziona anche in una sessione Managed Agents?

Sì, e in caso di cache hit riduce fino al 90% i costi di input. La diagnostica della cache per la beta del prompt caching è arrivata nella 0.102, quindi ora il payload di risposta mostra anche i tassi di cache hit.

Per Discovery la migrazione richiede un pomeriggio; per Writer, un altro. Il resto viene di conseguenza. Bloccare la 0.102.0. Registrare il webhook. Eliminare il Critic DO. Mantenere il punto di controllo.

Ultimo aggiornamento

5 set 2026

CategoriaBuild

Preferisca questo sito su Google

Aggiungi omidsaffari.com come fonte preferita nella Ricerca Google

Segni omidsaffari.com come fonte preferita e Google lo mette in evidenza per lei in Top Stories, AI Overviews e AI Mode.

Newsletter

Una lettera, ogni domenica. Sistemi che funzionano, non hot take.

Build log, sistemi in produzione e note dal campo da un portafoglio di venture AI.

Settimanale. Niente spam. Si cancella quando vuole.