L'articolo precedente ha coperto cosa sono i dynamic workflow di Claude Opus 4.8 — l'architettura, i benchmark, i prezzi e il rischio di token explosion. Questo articolo è il companion implementativo: come eseguire concretamente un workflow, cosa configurare prima di farlo, e come replicare la stessa pipeline in Python quando serve controllo programmatico. L'esempio pratico è una code review di una pipeline dati: ogni modulo riceve il suo agente dedicato, gli agenti girano in parallelo, e l'orchestratore aggrega i risultati in un report strutturato.
Esistono due modi distinti per usare i workflow di Claude Opus 4.8 in produzione. Non sono intercambiabili — ognuno ha un modello di controllo diverso, una superficie di integrazione diversa e failure mode diversi. Scegliere quello sbagliato per il proprio contesto è l'errore più comune che i team fanno quando adottano i workflow agentici per la prima volta.
- Claude decide come orchestrare
- Fino a 16 agenti concorrenti, 1.000 per run
- Fornisci la direzione, non il codice di coordinamento
- Ideale per: task open-ended su codebase
- Tempo di setup: minuti (AGENTS.md + un comando)
- Visibilità costi:
usage.iterationsnell'output
- Sei tu a scrivere il codice di orchestrazione
- Concorrenza limitata dal tuo Semaphore + rate limit
- Controllo totale: retry logic, kill switch, routing personalizzato
- Ideale per: pipeline strutturate e ripetibili
- Tempo di setup: ore (orchestrator class + telemetria)
- Visibilità costi: oggetto
usageesplicito per chiamata
Il caso d'uso — code review di una pipeline Python
L'esempio di codebase in questo articolo è un progetto Python ETL standard: quattro moduli, ciascuno con problemi noti che una code review dovrebbe rilevare — error handling mancante, nessuna type annotation, concatenazione SQL non sicura e casi limite non testati. L'obiettivo è assegnare a ogni modulo un agente dedicato, con generazione di test e proposte di fix prodotte in parallelo, poi aggregate in un unico report.
etl_pipeline/ ├── AGENTS.md # agent instructions (shared by both tracks) ├── src/ │ ├── extractors/ │ │ └── api_extractor.py # fetches data from external API │ ├── transformers/ │ │ └── data_transformer.py # normalises and validates raw records │ ├── loaders/ │ │ └── db_loader.py # writes to PostgreSQL via SQLAlchemy │ └── validators/ │ └── schema_validator.py # validates Pydantic schemas against data └── tests/ # empty — agents will populate this
Track A — Claude Code CLI con ultracode
Prerequisiti
I dynamic workflow richiedono Claude Code v2.1.154 o superiore. Verifica la versione con claude --version e aggiorna con claude update (oppure npm update -g @anthropic-ai/claude-code se preferisci npm). Devi anche passare a Opus 4.8 all'interno della sessione — il motore di workflow si attiva solo sui modelli che supportano l'effort xhigh (Anthropic, 2026b).
Disponibilità per piano: i workflow sono attivi per default sui piani Max e Team. Gli utenti Pro possono attivarli manualmente da /config. I piani Enterprise hanno i workflow disabilitati per default e richiedono l'abilitazione da parte dell'amministratore attraverso le impostazioni gestite.
Step 1 — Scrivi AGENTS.md
AGENTS.md è il documento che Claude legge prima di iniziare qualsiasi lavoro. Scrivilo prima di attivare il workflow — Claude lo usa per pianificare l'orchestrazione, allocare gli agenti e rispettare i vincoli. Istruzioni vaghe producono orchestrazioni vaghe; istruzioni specifiche producono output circoscritti e revisionabili.
# AGENTS.md — ETL Pipeline Code Review ## Context Python ETL pipeline. Four modules in src/. Tests in tests/ are empty and must be populated. The pipeline runs in production on AWS Lambda with a 15-second timeout per invocation. ## Review criteria (apply to every module) 1. Security: SQL injection, secrets in code, unsafe deserialization, unvalidated inputs 2. Error handling: all IO operations must have try/except with specific exception types 3. Type annotations: all public functions must have full signatures (PEP 484) 4. Testability: functions with side effects must be injectable (no hard-coded dependencies) ## Output format per module For each file, produce three artefacts: - ISSUES.md — numbered list of issues with severity (critical / high / medium) - tests/test_[module].py — pytest file that fails on the identified issues - PATCH.diff — unified diff that fixes all issues and makes the tests pass ## Forbidden - Do NOT modify files outside src/ and tests/ - Do NOT add external dependencies not already in requirements.txt - Do NOT rewrite a module from scratch — patch the existing code ## Concurrency note Each module is independent. All four can be reviewed in parallel. Assign one primary agent and one adversarial reviewer per module.
Step 2 — Avvia il workflow
# 1. Navigate to the project root (where AGENTS.md lives) cd etl_pipeline/ # 2. Start a Claude Code session claude # 3. Inside the session: switch to Opus 4.8 /model claude-opus-4-8 # 4. Set ultracode effort — activates xhigh reasoning + workflow engine /effort ultracode # 5. Trigger the workflow — include "workflow" anywhere in the prompt Create a workflow to review all four Python modules in src/ following AGENTS.md, producing ISSUES.md, a test file, and a PATCH.diff for each module. Modules are independent — run reviews in parallel. # Claude will now plan the orchestration, confirm the approach, # then dispatch agents. Each wave runs up to 16 agents concurrently. # Track spend in real time: /usage
Dopo l'invio del prompt, Claude Code entra in modalità pianificazione: legge AGENTS.md, esplora la directory src/ e scrive uno script JavaScript di coordinamento interno che gestisce loop, branching e decisioni sul numero di agenti. Lancia poi gli agenti a ondate fino a 16 concorrenti per volta — il limite è pensato per proteggere le risorse CPU locali. Per questo task a quattro moduli vedrai: un agente di pianificazione che mappa le dipendenze tra moduli, quattro agenti di review primari (uno per modulo), quattro revisori avversariali che controllano ogni review alla ricerca di problemi mancati, e un agente di sintesi che produce un SUMMARY.md finale. Claude Code mostra il progresso nel terminale — il comando /usage visualizza la spesa in token per iterazione (Anthropic, 2026b).
Quando il workflow termina, torna subito all'effort standard: /effort high. Ultracode applica il ragionamento xhigh a ogni messaggio della sessione — incluse le domande di follow-up banali dopo il completamento del workflow.
Track B — Orchestrazione con il Python SDK
L'approccio CLI funziona bene per task one-off dove Claude può esplorare liberamente il codebase. Per pipeline pianificate, integrazione CI/CD, o workflow che necessitano di retry logic personalizzata e contabilità dei costi, serve un orchestratore Python — una classe che gestisce le chiamate API Anthropic, applica i limiti di concorrenza, tiene traccia della spesa in token e gestisce la compattazione nelle sessioni lunghe.
Perché costruire il proprio orchestratore
L'SDK Python ti dà tre cose che la CLI non può offrire: comportamento deterministico di retry sugli errori API, un token budget kill switch imposto nel tuo codice (non dipendente dai guardrail opzionali di Anthropic), e output strutturato che alimenta direttamente i sistemi downstream — un database, una notifica Slack, un gate CI — senza intervento manuale.
La classe orchestratore
import asyncio import anthropic from dataclasses import dataclass, field from pathlib import Path from typing import Optional @dataclass class ReviewResult: file_path: str issues: str = "" test_code: str = "" patch: str = "" tokens_used: int = 0 error: Optional[str] = None class AsyncWorkflowOrchestrator: """Parallel code review orchestrator with token budget enforcement.""" SYSTEM_PROMPT = """You are a senior Python engineer performing a code review. For the file provided, return a JSON object with three keys: "issues": markdown list of issues with severity labels "test_code": complete pytest file that fails on the issues you found "patch": unified diff that fixes all issues and makes the tests pass Return ONLY the JSON — no prose before or after.""" def __init__( self, model: str = "claude-opus-4-8", token_budget: int = 200_000, # kill switch threshold max_concurrency: int = 5, # respect API rate limits ): self.client = anthropic.AsyncAnthropic() self.model = model self.token_budget = token_budget self.tokens_spent = 0 self._killed = False self._semaphore = asyncio.Semaphore(max_concurrency) self._lock = asyncio.Lock() # guards tokens_spent counter async def _charge_tokens(self, tokens: int) -> bool: """Thread-safe token accounting. Returns False if budget exceeded.""" async with self._lock: self.tokens_spent += tokens if self.tokens_spent > self.token_budget: self._killed = True return False return True async def review_file(self, path: Path) -> ReviewResult: result = ReviewResult(file_path=str(path)) if self._killed: result.error = "Workflow killed: token budget exceeded" return result async with self._semaphore: try: content = path.read_text(encoding="utf-8") response = await self.client.messages.create( model=self.model, max_tokens=8192, thinking={"type": "enabled", "budget_tokens": 10_000}, system=[{ "type": "text", "text": self.SYSTEM_PROMPT, "cache_control": {"type": "ephemeral", "ttl": "1h"} }], messages=[{ "role": "user", "content": f"Review this file ({path.name}):\n\n```python\n{content}\n```" }] ) # Charge tokens — kill if over budget total = response.usage.input_tokens + response.usage.output_tokens result.tokens_used = total if not await self._charge_tokens(total): result.error = f"Budget exceeded after {self.tokens_spent:,} tokens" return result # Extract the text block (skip thinking blocks) text = next( b.text for b in response.content if b.type == "text" ) import json data = json.loads(text) result.issues = data.get("issues", "") result.test_code = data.get("test_code", "") result.patch = data.get("patch", "") except Exception as e: result.error = str(e) return result async def run(self, src_dir: Path) -> list[ReviewResult]: files = list(src_dir.rglob("*.py")) tasks = [self.review_file(f) for f in files] return await asyncio.gather(*tasks)
Eseguire l'orchestratore
import asyncio from pathlib import Path from orchestrator import AsyncWorkflowOrchestrator async def main(): src = Path("etl_pipeline/src") out = Path("review_output") out.mkdir(exist_ok=True) orchestrator = AsyncWorkflowOrchestrator( model="claude-opus-4-8", token_budget=300_000, # ~$1.50 at Standard tier — adjust to your comfort max_concurrency=4, # 4 files in parallel, one API call each ) print(f"Reviewing {src} — kill switch at {orchestrator.token_budget:,} tokens") results = await orchestrator.run(src) # Write artefacts and print summary errors, reviewed = [], [] for r in results: name = Path(r.file_path).stem if r.error: errors.append(r) print(f" ✗ {name}: {r.error}") continue (out / f"{name}_ISSUES.md").write_text(r.issues) (out / f"test_{name}.py").write_text(r.test_code) (out / f"{name}.patch").write_text(r.patch) reviewed.append(r) print(f" ✓ {name}: {r.tokens_used:,} tokens") total = orchestrator.tokens_spent cost = (total / 1_000_000) * 5.00 # Standard tier input rate print(f"\nTotal: {len(reviewed)} reviewed, {len(errors)} failed") print(f"Tokens: {total:,} | Estimated cost: ${cost:.4f}") print(f"Output: {out}/") asyncio.run(main())
Un tipico modulo Python da 150–300 righe costa circa 2.000–4.000 token di input passato con il system prompt (che viene messo in cache dopo la prima chiamata). Quattro moduli in parallelo: circa 8.000–16.000 token di input totali, più l'output. Al prezzo Standard ($5,00/M input, $25,00/M output), la review completa di un progetto a quattro moduli costa meno di $0,15. Il token_budget=300_000 nell'esempio è una rete di sicurezza conservativa — al prezzo Standard equivale a $1,50 di esposizione massima prima che il kill switch scatti.
Il system prompt condiviso viene messo in cache per 1 ora dopo che il primo agente lo scrive. Gli agenti 2–4 leggono dalla cache e vengono fatturati $0,50/M invece di $5,00/M su quei token — un risparmio del 90% sul blocco di input più costoso. Per questo impostare la cache del system prompt prima di inviare gli agenti paralleli vale ampiamente l'overhead di una riga di codice.
Gestione delle sessioni lunghe — compattazione nell'orchestratore Python
Per le pipeline che girano continuamente — una review notturna su una codebase grande, o un agente di monitoraggio che accumula contesto per ore — è necessario gestire la compattazione nell'orchestratore. Il pattern della guida tecnica si applica direttamente: abilita pause_after_compaction, intercetta la stop reason, persisti il riassunto e riprendi (Anthropic, 2026d).
async def call_with_compaction( client: anthropic.AsyncAnthropic, messages: list, vector_store, session_id: str, **kwargs, ) -> anthropic.types.Message: """Wrap a beta messages call; handles compaction transparently.""" response = await client.beta.messages.create( betas=["compact-2026-01-12"], context_management={ "edits": [{ "strategy": "compact_20260112", "trigger": {"type": "token_count", "threshold": 80_000}, "instructions": "Preserve all file paths, issue IDs, and patch hunks verbatim.", "pause_after_compaction": True, }] }, messages=messages, **kwargs, ) if response.stop_reason == "compaction": block = next(b for b in response.content if b.type == "compaction") summary = block.content or "" # guard against null (known edge case) if summary: await vector_store.upsert(session_id, summary) # Resume with empty messages — server has already replaced history return await call_with_compaction(client, [], vector_store, session_id, **kwargs) return response
Scegliere tra i due approcci
| Punto di decisione | Usa Claude Code CLI | Usa Python SDK |
|---|---|---|
| Struttura del task | Open-ended — lo scope non è completamente definito a priori | Strutturato — sai esattamente quali file ricevono quale trattamento |
| Trigger | Manuale, interattivo, o pianificato via cron + shell script | Qualsiasi evento Python: CI webhook, schedule, API call, queue message |
| Output | File scritti su disco; Claude Code li formatta | Dati strutturati (JSON, dataclass) che il tuo codice elabora |
| Error handling | Claude Code riprova internamente; visibilità limitata | Controllo totale: exponential backoff, retry parziale, skip selettivo |
| Visibilità costi | /usage nella sessione; non facilmente esportabile |
Oggetto usage per chiamata — logga in qualsiasi sistema di osservabilità |
| Compattazione | Automatica; non puoi fermarti e ispezionare il riassunto | pause_after_compaction esplicito — controlli la persistenza |
Un approccio ibrido funziona bene per i team maturi: usa Claude Code CLI per le run esplorative (nuove codebase, task ambigui, proof-of-concept), poi codifica il pattern riuscito in un orchestratore Python per l'uso pianificato in produzione. Il file AGENTS.md viaggia invariato tra i due approcci — è la specifica stabile che sia Claude Code che i tuoi agenti Python leggono.
Checklist di produzione prima del go-live
max_concurrency=4, solo una delle quattro chiamate parallele scrive la cache — le altre sono letture istantanee. Imposta 'ttl': '1h' se tutti gli agenti finiranno entro un'ora.json.loads() in un try/except e loga la risposta raw in caso di fallimento — non scartarla silenziosamente. Un ReviewResult con error impostato è molto più utile di un file silenziosamente vuoto.anthropic.RateLimitError, attendi 2tentativo secondi (con cap a 60s) e riprova. Il Semaphore nell'orchestratore limita la concorrenza al momento del dispatch; il backoff gestisce i limiti transitori durante l'esecuzione./effort high dopo la fine di un workflow significa che il tuo prossimo "quali file hai modificato?" brucia token di ragionamento xhigh. Questa è una fonte comune di picchi di costo inspiegabili nei deployment di team.- Anthropic. (2026a). Introducing Claude Opus 4.8. anthropic.com/news/claude-opus-4-8
- Anthropic. (2026b). Introducing dynamic workflows in Claude Code. claude.com/blog/introducing-dynamic-workflows-in-claude-code
- Anthropic. (2026c). Python SDK — Claude API Docs. platform.claude.com/docs/en/api/sdks/python
- Anthropic. (2026d). Compaction — Claude API Docs. platform.claude.com/docs/en/build-with-claude/compaction
- Anthropic. (2026e). Prompt caching — Claude API Docs. platform.claude.com/docs/en/build-with-claude/prompt-caching
- Anthropic. (2026f). CLI reference — Claude Code Docs. code.claude.com/docs/en/cli-reference