\n\n\n\n Riparo i miei flussi di lavoro Agentic: Ecco come - AgntDev \n

Riparo i miei flussi di lavoro Agentic: Ecco come

📖 12 min read2,326 wordsUpdated Apr 3, 2026

Ciao a tutti, Leo qui da agntdev.com. Spero che stiate tutti vivendo una settimana produttiva!

Oggi voglio esplorare qualcosa che mi preoccupa molto negli ultimi tempi, soprattutto da quando ho lavorato a qualche progetto personale che coinvolge flussi di lavoro agenti più complessi e multi-fase. Parliamo molto della costruzione di agenti, dei LLM stessi e delle cose interessanti che possono fare. Ma che dire dell’aspetto meno glamour, ma assolutamente cruciale, di assicurarci che i nostri agenti funzionino realmente in modo affidabile ed efficiente nel tempo?

Più precisamente, parlo di osservabilità degli agenti. Non si tratta solo di logging; si tratta di comprendere davvero cosa fa il tuo agente, perché lo fa e di rilevare i problemi prima che diventino ingestibili. In un mondo in cui gli agenti interagiscono con API esterne, prendono decisioni basate su input dinamici e possono potenzialmente funzionare per lunghi periodi, navigare al buio è una ricetta per il disastro. L’ho imparato a mie spese, come spiegherò.

Il “Bug Misterioso” Che Mi Ha Insegnato Tutto

Qualche mese fa stavo sviluppando un agente di assistente personale. Chiamiamolo “Progetto Chronos.” Il suo ruolo era monitorare il mio calendario, i miei feed di notizie e specifici canali Slack, quindi proporre in modo proattivo orari per riunioni, riepilogare aggiornamenti chiave o persino redigere risposte iniziali a domande comuni. Un funzionamento piuttosto standard sulla superficie.

Lo ho costruito, testato con alcuni scenari ed sembrava funzionare correttamente. L’ho configurato per funzionare durante la notte, pensando di svegliarmi con un riepilogo perfettamente organizzato. Invece, mi sono svegliato con… nulla. O meglio, un riepilogo parziale che si è interrotto bruscamente, seguito da un messaggio di errore criptico nei miei log di sistema che diceva sostanzialmente “qualcosa è andato storto.”

Debuggare questo è stato un incubo. Chronos doveva fare diverse cose: recuperare eventi dal calendario, interrogare un’API di notizie, toccare un’API Slack, elaborare i dati e poi generare un riepilogo. Quale fase è fallita? Perché? Ha anche tentato tutte le fasi? Era un limite di rate dell’API? Un prompt malformato? Un timeout? Non avevo idea.

Il mio logging iniziale era basilare: “Fase X avviata,” “Fase Y completata,” e poi l’output finale o un errore. Non era sufficiente. Era come cercare di diagnosticare un problema di un’auto sapendo solo che è partita e poi si è spenta, senza alcuna informazione sulla temperatura del motore, sulla pressione del carburante o sui difetti elettrici.

Questa esperienza ha sottolineato un punto: se sei serio riguardo allo sviluppo di agenti, hai bisogno di una buona osservabilità fin dal primo giorno. Non è una riflessione postuma; è un componente fondamentale.

Oltre al Logging di Base: Cosa Significa “Osservabilità” per gli Agenti?

Per me, l’osservabilità degli agenti si scompone in alcuni ambiti chiave, ognuno dei quali offre una prospettiva diversa sul funzionamento del tuo agente:

1. Monitoraggio dell’Esecuzione Fase per Fase

Questo è il più critico. Devi sapere esattamente cosa sta facendo il tuo agente a ogni fase della sua esecuzione. Pensalo come un filo d’Arianna dettagliato. Per il Progetto Chronos, avevo bisogno di vedere:

  • Quando ha iniziato a recuperare gli eventi dal calendario.
  • I parametri che ha usato per la chiamata API del calendario (ad esempio, l’intervallo di date).
  • La risposta grezza dall’API del calendario.
  • Come ha elaborato quella risposta.
  • Il prompt esatto che ha inviato al LLM per riassumere le informazioni del calendario.
  • La risposta del LLM.
  • Tutti gli strumenti chiamati, con i loro input e output.
  • I messaggi di errore, non solo “qualcosa è andato storto”, ma un errore specifico con contesto (ad esempio, “L’API del calendario ha restituito 401 Unauthorized per l’utente X”).

Questo livello di dettaglio è inestimabile per ricreare problemi e comprendere i punti di decisione. I miei log iniziali dicevano solo “Recupero dei dati dal calendario…” e poi “Riepilogo dei dati dal calendario…” senza nulla in mezzo. Non è utile quando il recupero dei dati stesso è fallito silenziosamente.

2. Monitoraggio di Prompt e Risposte

Il LLM è il cervello del tuo agente. Se non sai quali prompt riceve e quali risposte restituisce, stai navigando al buio. Questo include:

  • Il prompt completo inviato al LLM (sistema, utente e tutte le descrizioni delle chiamate di funzione).
  • La temperatura, top_p e altri parametri di generazione.
  • La risposta grezza del LLM, compresi tutti i richiami agli strumenti che ha deciso di fare.
  • Utilizzo dei token (ingresso, uscita, totale) per il monitoraggio dei costi e l’analisi delle prestazioni.

Questo è cruciale per l’ingegneria dei prompt. Se un agente restituisce risposte senza senso, vedere il prompt esatto che ha ricevuto ti aiuta a fare debugging se il contesto di input era errato o se il prompt stesso era mal strutturato.

3. Monitoraggio delle Chiamate agli Strumenti

Gli agenti interagiscono spesso con strumenti esterni o API. Ogni interazione rappresenta un potenziale punto di fallimento o un comportamento inatteso. Devi registrare:

  • Quale strumento è stato chiamato.
  • Gli argomenti esatti passati allo strumento.
  • La risposta grezza dello strumento.
  • Tutti gli errori restituiti dallo strumento o durante la sua esecuzione.

Per Chronos, se stava cercando di chiamare l’API Slack per postare un riepilogo, avevo bisogno di sapere il canale mirato, il contenuto del messaggio e se l’API restituiva ad esempio un errore 403 Forbidden. La mia configurazione precedente si limitava a dirmi “Tentativo di postare su Slack.”

4. Catture di Stato

Molti agenti mantengono uno stato interno – un taccuino, una memoria, una lista di fatti che hanno raccolto. Catturare regolarmente questo stato può essere incredibilmente utile per il debugging. Se un agente si ritrova bloccato in un ciclo o prende una decisione errata, vedere i suoi “pensieri” interni in vari momenti può rivelare dove la sua comprensione è andata fuori strada.

Questo riguarda meno il logging di ogni cambiamento di variabile e più la cattura degli stati chiave di decisione. Per Chronos, questo potrebbe essere “Comprensione attuale dell’orario dell’utente,” o “Punti chiave dei feed di notizie fino ad ora.”

Approcci Pratici: Integrare l’Osservabilità

Va bene, come implementiamo tutto questo senza annegare nei log? Ecco alcune strategie pratiche e frammenti di codice.

Strategia 1: Logging Strutturato con Contesto

Dimentica le dichiarazioni `print()`. Usa una libreria di logging appropriata (come il modulo `logging` di Python). È fondamentale arricchire i tuoi messaggi di logging con dati strutturati (JSON, dizionari) piuttosto che con semplici stringhe. Questo rende i log analizzabili, ricercabili e molto più utili.

Ecco un esempio semplificato in Python:


import logging
import json
import uuid
from datetime import datetime

# Configurazione di base del logger (in una vera applicazione, lo configureresti in modo più solido)
logger = logging.getLogger(__name__)
logger.setLevel(logging.INFO)
handler = logging.StreamHandler()
formatter = logging.Formatter('%(levelname)s: %(message)s')
handler.setFormatter(formatter)
logger.addHandler(handler)

def log_agent_step(agent_id: str, step_name: str, status: str, details: dict = None):
 log_data = {
 "timestamp": datetime.now().isoformat(),
 "agent_id": agent_id,
 "step_name": step_name,
 "status": status, # ad esempio, "iniziato", "completato", "fallito"
 "details": details if details is not None else {}
 }
 logger.info(json.dumps(log_data))

class MyAgent:
 def __init__(self, agent_id: str = None):
 self.agent_id = agent_id if agent_id else str(uuid.uuid4())
 self.memory = [] # Memoria interna semplice

 def _fetch_calendar_events(self, user_id: str, date_range: str):
 log_agent_step(self.agent_id, "fetch_calendar_events", "started", 
 {"user_id": user_id, "date_range": date_range})
 try:
 # Simulare una chiamata API
 if "error" in date_range:
 raise ValueError("Errore simulato dell'API calendario")
 
 events = [
 {"title": "Riunione di team", "time": "10:00 AM"},
 {"title": "Riunione con il cliente", "time": "02:00 PM"}
 ]
 log_agent_step(self.agent_id, "fetch_calendar_events", "completed", 
 {"num_events": len(events), "data_preview": events[0]})
 self.memory.append(f"Eventi del calendario: {events}")
 return events
 except Exception as e:
 log_agent_step(self.agent_id, "fetch_calendar_events", "failed", 
 {"error": str(e), "traceback": "..."}) # Nella vita reale, catturare la traccia
 raise

 def _summarize_with_llm(self, prompt_text: str):
 log_agent_step(self.agent_id, "summarize_with_llm", "started", 
 {"prompt_length": len(prompt_text), "prompt_preview": prompt_text[:100]})
 try:
 # Simulare una chiamata LLM
 if "fail_llm" in prompt_text:
 raise RuntimeError("Errore simulato dell'API LLM")
 
 response = f"Riassunto LLM di: {prompt_text[:50]}..."
 token_usage = {"input": len(prompt_text) // 4, "output": len(response) // 4}
 log_agent_step(self.agent_id, "summarize_with_llm", "completed", 
 {"response_length": len(response), "token_usage": token_usage, 
 "llm_response_preview": response[:100]})
 self.memory.append(f"Riassunto prodotto da LLM: {response}")
 return response
 except Exception as e:
 log_agent_step(self.agent_id, "summarize_with_llm", "failed", 
 {"error": str(e), "traceback": "..."})
 raise

 def run_daily_briefing(self, user_id: str):
 log_agent_step(self.agent_id, "run_daily_briefing", "started", {"user_id": user_id})
 try:
 calendar_data = self._fetch_calendar_events(user_id, "today")
 news_summary = self._summarize_with_llm("Riassumere le principali notizie di oggi...")
 
 final_briefing_prompt = (
 f"Creare un briefing quotidiano basato su:\n"
 f"Calendario: {json.dumps(calendar_data)}\n"
 f"Notizie: {news_summary}"
 )
 final_briefing = self._summarize_with_llm(final_briefing_prompt)
 
 log_agent_step(self.agent_id, "run_daily_briefing", "completed", 
 {"final_briefing_length": len(final_briefing)})
 return final_briefing
 except Exception as e:
 log_agent_step(self.agent_id, "run_daily_briefing", "failed", 
 {"error": str(e), "current_memory": self.memory}) # Catturare la memoria in caso di errore
 raise

# Esempio di utilizzo
if __name__ == "__main__":
 agent = MyAgent()
 print(f"\n--- Esecuzione dell'agente {agent.agent_id} (Caso di successo) ---")
 try:
 briefing = agent.run_daily_briefing("leo_g")
 print(f"Briefing: {briefing[:100]}...")
 except Exception as e:
 print(f"L'esecuzione dell'agente è fallita: {e}")

 agent_fail = MyAgent()
 print(f"\n--- Esecuzione dell'agente {agent_fail.agent_id} (Caso di fallimento del calendario) ---")
 try:
 # Simulare un fallimento del calendario passando "error" in date_range
 agent_fail._fetch_calendar_events("leo_g", "error_today") 
 except Exception as e:
 print(f"L'esecuzione dell'agente è fallita come previsto: {e}")

 agent_llm_fail = MyAgent()
 print(f"\n--- Esecuzione dell'agente {agent_llm_fail.agent_id} (Caso di fallimento LLM) ---")
 try:
 # Simulare un fallimento LLM
 agent_llm_fail._summarize_with_llm("fail_llm_please")
 except Exception as e:
 print(f"L'esecuzione dell'agente è fallita come previsto: {e}")

Nota come `log_agent_step` cattura l’ID dell’agente, il nome del passo, lo stato e un dizionario di dettagli pertinenti. Questo facilita il filtraggio dei log per ID dell’agente, il tracciamento di un’esecuzione unica o la ricerca di tutti i passi “falliti”.

Strategia 2: Osservabilità centralizzata con una libreria/servizio dedicato

Per agenti più complessi o ambienti di produzione, supererai rapidamente il semplice logging su file. È qui che gli strumenti specializzati brillano. Librerie come `LangSmith` di LangChain (o simili per altri framework) forniscono tracciamento integrato, visualizzazione e debug per le applicazioni LLM.

Anche se non utilizzi LangChain, il concetto è trasferibile. Puoi creare il tuo wrapper attorno all’esecuzione del tuo agente che invia eventi strutturati a un servizio di logging (Datadog, Splunk, stack ELK, o anche un semplice bucket S3 con elaborazione Lambda). L’essenziale è standardizzare lo schema degli eventi.

Il mio progetto Chronos migliorato utilizza ora una classe `TraceManager` personalizzata che avvolge le operazioni critiche. Questo gestore invia eventi strutturati a un database locale per lo sviluppo e a un servizio di logging nel cloud in produzione. Questo mi permette di vedere un “tracciato” completo di ogni esecuzione dell’agente, con passi annidati e tutti i dati associati (richiesta, risposte, ingressi/uscite degli strumenti, errori).

Strategia 3: Intercettazione delle chiamate LLM e degli strumenti

Molti SDK LLM ti consentono di configurare callback o intercettori per le chiamate API. Usali! Invece di fare manualmente il logging prima e dopo ogni richiesta LLM, puoi avere un unico intercettore che logga automaticamente:

  • L’endpoint API esatto utilizzato.
  • Le intestazioni e il corpo della richiesta (in particolare la richiesta).
  • Le intestazioni e il corpo della risposta (il completamento).
  • La latenza.
  • Tutte le eccezioni.

Allo stesso modo, incapsula le tue chiamate agli strumenti. Se hai uno strumento `search_web`, il wrapper dovrebbe loggare la richiesta di ricerca, il motore di ricerca utilizzato e i N migliori risultati restituiti, insieme a tutti gli errori.

Consigli Azionabili per il Tuo Prossimo Progetto di Agente

  1. Progetta prima per l’Osservabilità: Non considerarlo una riflessione successiva. Pensa a cosa avresti bisogno per fare debugging prima di scrivere il tuo primo passo dell’agente.
  2. Adotta il Logging Strutturato: Abbandona `print()` e `console.log()` per il codice di produzione. Usa una libreria di logging appropriata e restituisci dati strutturati (JSON) per ogni evento significativo.
  3. Trace Tutto ciò che è Importante: Fai il logging dell’inizio e della fine di ogni passo maggiore, tutte le richieste e risposte LLM (inclusi i parametri e i conteggi dei token), e ogni chiamata di strumento con le sue entrate e uscite.
  4. Cattura lo Stato in Caso di Fallimento: Quando un agente fallisce, logga il suo stato interno o la sua memoria in quel momento. Questo fornisce un contesto cruciale per comprendere perché ha fallito.
  5. Utilizza ID Specifici per l’Agente: Assegna un ID unico a ogni esecuzione dell’agente (ad esempio, un UUID). Questo ti consente di filtrare e tracciare facilmente un percorso di esecuzione unico attraverso i tuoi log.
  6. Visualizza i Tuoi Tracciati: Se possibile, utilizza o crea uno strumento che può visualizzare questi log strutturati come una sequenza di eventi. Vedere il flusso rende il debugging infinitamente più facile rispetto a trattare del testo grezzo. LangSmith lo fa magnificamente, ma anche uno script personalizzato può generare una semplice cronologia HTML.
  7. Monitora i Costi: L’uso dei token LLM rappresenta un costo diretto. Loggalo. Questo ti aiuta a capire dove va il tuo denaro e a ottimizzare le tue richieste.

Costruire agenti è entusiasmante, ma costruire agenti affidabili è dove si trova il vero lavoro (e il vero valore). E l’affidabilità inizia con la comprensione di ciò che accade dietro le quinte. La mia esperienza dolorosa con il progetto Chronos mi ha ben insegnato questa lezione. Non aspettare il tuo “bug misterioso” per convincerti. Inizia a loggare in modo intelligente fin da oggi.

Quali sono le tue strategie di osservabilità preferite per gli agenti? Scrivimi nei commenti o sui social media. Sono sempre interessato a sapere come gli altri affrontano queste sfide!

🕒 Published:

✍️
Written by Jake Chen

AI technology writer and researcher.

Learn more →
Browse Topics: Agent Frameworks | Architecture | Dev Tools | Performance | Tutorials
Scroll to Top