Torna al blog

Triage dei task bloccati nello sviluppo parallelo

Adesso puoi far girare 10 agenti AI di coding in parallelo. Assegna a ciascuno una issue, puntali a un database beads condiviso e lasciali lavorare. Gli agenti creano sotto-task, segnalano bug che scoprono, aggiornano stati e chiudono issue quando hanno finito. E genuinamente produttivo.

Finche qualcosa non si blocca.

Quando un umano e bloccato, lo dice. Posta su Slack, lo segnala allo standup, va alla scrivania di qualcuno. Gli agenti non fanno nulla di tutto questo. Un agente incontra una dipendenza che non riesce a risolvere e o si blocca silenziosamente oppure inizia ad aggirare il problema in modi che creano altri problemi. Tre agenti possono essere bloccati sullo stesso task upstream non risolto e tu non lo saprai finche non ti chiederai perche nulla e stato rilasciato nelle ultime quattro ore.

Questo e il problema del triage per lo sviluppo con agenti. Non "come facciamo standup migliori" ma "come vediamo cosa e bloccato su una flotta di lavoratori autonomi che non si lamentano." Ecco cosa abbiamo imparato costruendo Beadbox, una dashboard in tempo reale per beads che ti mostra esattamente cosa stanno facendo i tuoi agenti, su cosa sono bloccati e cosa e appena diventato disponibile.

Vai a cio che ti interessa:

Come gli agenti creano catene di blocco

Gli agenti generano problemi di dipendenza in modo diverso dai team umani. Capire le modalita di fallimento conta perche le risposte di triage sono diverse.

Gli agenti non modellano le dipendenze in anticipo. Un architetto umano scompone una funzionalita in task e pensa all'ordinamento. Un agente di coding riceve un task, inizia a lavorare e scopre a meta implementazione di aver bisogno di qualcosa che non esiste ancora. Potrebbe creare una nuova issue per quella dipendenza. Potrebbe provare a costruirla inline e creare un pasticcio. Potrebbe semplicemente fermarsi. Nessuno di questi risultati e visibile a meno che tu non stia guardando il database delle issue.

Gli agenti lavorano piu velocemente di quanto i grafi delle dipendenze si aggiornino. Agent-3 chiude un task che Agent-7 stava aspettando, ma Agent-7 non lo sa perche ha controllato i blocchi 10 minuti fa. Nel frattempo Agent-7 e ancora fermo o sta lavorando su qualcosa a priorita piu bassa. Lo sblocco e avvenuto, ma l'informazione non si e propagata.

Dipendenze circolari emergono dalla decomposizione parallela. Quando piu agenti scompongono il lavoro contemporaneamente, possono creare cicli che nessun singolo agente vede. Agent-1 crea il Task A che dipende dal Task B. Agent-2 crea il Task B che dipende dal Task C. Agent-3 crea il Task C che dipende dal Task A. Ogni dipendenza aveva senso localmente. Il ciclo e visibile solo dall'alto.

La contesa sulle risorse e invisibile. Due agenti devono entrambi modificare lo stesso file, o entrambi hanno bisogno dell'ambiente di staging, o entrambi hanno bisogno che la stessa libreria condivisa sia in uno stato stabile. Non c'e nessuna dipendenza registrata perche nessuno dei due agenti sa che l'altro esiste. Entrambi semplicemente rallentano e nessuno dei due riferisce perche.

Il filo conduttore: gli agenti producono situazioni di blocco piu velocemente di quanto le segnalino. Il supervisore (tu) ha bisogno di strumenti che evidenzino i blocchi automaticamente, non di strumenti che aspettano che qualcuno alzi la mano.

Rilevamento automatico delle dipendenze

La soluzione sono dati di dipendenza espliciti e interrogabili, creati al momento del task e verificati continuamente. Ecco come appare con beads, l'issue tracker Git-native su cui gestiamo la nostra flotta di agenti.

Gli agenti registrano le dipendenze quando creano i task:

# L'agente crea un task e scopre di aver bisogno di un'API che non esiste
API_TASK=$(bd create \
  --title "Implement /api/v2/orders endpoint" \
  --type task --priority 2 --json | jq -r '.id')

# L'agente crea il proprio task e dichiara la dipendenza
UI_TASK=$(bd create \
  --title "Build order history page" \
  --type task --priority 2 --json | jq -r '.id')

bd dep add "$UI_TASK" "$API_TASK"

Quel bd dep add e una singola chiamata CLI. Qualsiasi agente AI di coding (Claude Code, Cursor, Copilot Workspace) puo eseguirla. Nessuna libreria client API, nessun balletto di autenticazione. La dipendenza e ora un dato strutturato, interrogabile da qualsiasi altro agente o script.

Il rilevamento dei cicli gira automaticamente:

# beads controlla l'intero grafo delle dipendenze per cicli
bd dep cycles

# Output quando esistono cicli:
# CYCLE DETECTED: beads-a1b -> beads-c3d -> beads-e5f -> beads-a1b

Su un grafo di 5.000 dipendenze, ci vogliono ~70ms. Eseguilo come hook post-commit o su un cron a 5 minuti. Quando tre agenti creano indipendentemente un ciclo di dipendenze, lo intercetti in minuti invece di scoprirlo ore dopo quando tutti e tre sono in stallo.

Evidenzia ogni task bloccato in un solo comando:

bd blocked --json | jq -r '.[] |
  "BLOCKED: \(.id) \(.title)\n  waiting on: \(.blocked_by | join(", "))\n  assignee: \(.owner // "unassigned")\n"'

Output:

BLOCKED: beads-x7q Build order history page
  waiting on: beads-m2k Implement /api/v2/orders endpoint
  assignee: agent-3

BLOCKED: beads-r4p Deploy staging environment
  waiting on: beads-j9w Fix Docker build, beads-n1c Update TLS certificates
  assignee: agent-7

Ora sai che Agent-3 e Agent-7 sono bloccati, su cosa sono bloccati e cosa deve succedere per sbloccarli. L'intera query ha richiesto 30ms su un database da 10K issue.

Rileva PR bloccate dalle convenzioni di naming dei branch:

#!/bin/bash
# blocked-prs.sh: trova PR le cui dipendenze non sono state mergiate

for pr in $(gh pr list --json number,headRefName --jq '.[].headRefName'); do
  ISSUE_ID=$(echo "$pr" | grep -oE 'beads-[a-z0-9]+')
  [ -z "$ISSUE_ID" ] && continue

  BLOCKERS=$(bd show "$ISSUE_ID" --json | jq -r '.blocked_by[]' 2>/dev/null)
  for blocker in $BLOCKERS; do
    BLOCKER_STATUS=$(bd show "$blocker" --json | jq -r '.status')
    if [ "$BLOCKER_STATUS" != "closed" ]; then
      echo "PR ($pr) blocked: $ISSUE_ID waiting on $blocker ($BLOCKER_STATUS)"
    fi
  done
done

Venti righe di shell. Gira in locale, legge dati locali, ti dice quali PR dei tuoi agenti non possono ancora essere mergiate e perche.

Un workflow di triage CLI-first

Il triage in un workflow con agenti non e una riunione. E uno script che gira in loop. Il supervisore (umano o agente) guarda cosa e bloccato e prende una decisione per ogni elemento.

Ecco lo script di triage che usiamo davvero:

#!/bin/bash
# triage.sh: triage dei blocchi della flotta di agenti

echo "========================================="
echo "TRIAGE REPORT: $(date +%Y-%m-%d %H:%M)"
echo "========================================="

# 1. Cosa e bloccato?
echo -e "\n--- TASK BLOCCATI ---"
bd blocked --json | jq -r '.[] |
  "[\(.priority)] \(.id) \(.title)
    blocked by: \(.blocked_by | join(", "))
    assignee: \(.owner // "unassigned")\n"'

# 2. Cosa e disponibile per gli agenti?
echo -e "\n--- PRONTI (sbloccati, aperti) ---"
bd ready --json | jq -r '.[] |
  "[\(.priority)] \(.id) \(.title) (\(.owner // "unassigned"))"'

# 3. Quali agenti sono diventati silenziosi?
echo -e "\n--- IN_PROGRESS STANTII (nessun aggiornamento da 2h) ---"
CUTOFF=$(date -v-2H +%Y-%m-%dT%H:%M:%S 2>/dev/null || date -d '2 hours ago' --iso-8601=seconds)
bd list --status=in_progress --json | jq -r --arg cutoff "$CUTOFF" '.[] |
  select(.updated_at < $cutoff) |
  "STALE: \(.id) \(.title) (last update: \(.updated_at), assignee: \(.owner // "unknown"))"'

# 4. Salute delle dipendenze
echo -e "\n--- CICLI DI DIPENDENZA ---"
bd dep cycles 2>&1 || echo "No cycles detected."

echo -e "\n--- STATISTICHE FLOTTA ---"
bd stats

Per i team umani, "stantio" significa 48 ore senza aggiornamento. Per gli agenti, 2 ore di silenzio su un task in-progress sono un segnale d'allarme. O l'agente e bloccato e non lo sta segnalando, o e crashato. In entrambi i casi, devi controllare.

L'albero decisionale per ogni elemento bloccato:

  1. Un altro agente puo sbloccarlo? Ripriorizza il task bloccante, assegna un agente disponibile.
  2. La dipendenza e falsa? A volte gli agenti dichiarano dipendenze troppo conservative durante la pianificazione. Se il blocco non e reale, rimuovilo: bd dep remove beads-x7q beads-m2k (rimuove la dipendenza di x7q da m2k, sbloccando istantaneamente x7q).
  3. Il lavoro puo essere diviso? Fai fare all'agente bloccato le parti che non necessitano della dipendenza. Crea un task di follow-up per il resto.
  4. E un blocco esterno? Qualcosa che solo un umano puo risolvere (chiave API, decisione di design, concessione di accesso). Taggalo, annota la risoluzione prevista e riassegna l'agente ad altro lavoro pronto.

L'opzione 2 accade costantemente con gli agenti. Modellano le dipendenze basandosi sulla loro comprensione del codebase al momento della pianificazione. Una volta che l'implementazione inizia, la vera forma del lavoro rivela che meta di quelle dipendenze erano inutili.

Visibilita in tempo reale sul lavoro degli agenti

Eseguire uno script di triage ogni 30 minuti lascia gap. Quando gli agenti lavorano velocemente, succede molto tra un controllo e l'altro. La domanda diventa: puoi vedere i blocchi formarsi in tempo reale?

Come lo fa Beadbox:

Il database beads vive in una directory .beads/ sul tuo filesystem. Ogni bd update, bd create o bd close che un agente esegue scrive in quella directory. Beadbox la monitora con fs.watch() e invia le modifiche alla UI via WebSocket in pochi millisecondi.

L'effetto pratico: Agent-5 esegue bd update beads-x7q --status=closed in un terminale. La dashboard di Beadbox mostra immediatamente quel task come chiuso, e qualsiasi task che era bloccato su di esso si illumina come appena disponibile. Vedi la cascata senza eseguire alcun comando.

Questo conta perche il lavoro degli agenti crea burst. Un agente potrebbe chiudere tre task in 90 secondi, ognuno che sblocca lavoro downstream diverso. Una dashboard basata su polling con un intervallo di refresh di 30 secondi ti mostrerebbe uno stato intermedio confuso. La propagazione sotto il secondo ti mostra il quadro completo nel momento in cui accade.

Se non usi Beadbox, i filesystem watch funzionano comunque:

# Monitora il database beads per modifiche, avvisa su nuovi blocchi
# Nota: fswatch si attiva ad ogni scrittura. In produzione dovresti fare debounce
# (es. sleep 2 dopo ogni attivazione) per evitare rumore durante le scritture a burst.
fswatch -o .beads/ | while read; do
  BLOCKED_COUNT=$(bd blocked --json | jq length)
  if [ "$BLOCKED_COUNT" -gt 0 ]; then
    echo "$(date): $BLOCKED_COUNT tasks currently blocked"
    # Invia a ntfy, webhook Slack o qualsiasi sistema di notifica
  fi
done

Chiudi il ciclo con la CI:

# Nel tuo step post-build della CI: chiudi automaticamente la issue quando la build passa
if [ "$BUILD_STATUS" = "success" ]; then
  ISSUE_ID=$(echo "$BRANCH_NAME" | grep -oE 'beads-[a-z0-9]+')
  if [ -n "$ISSUE_ID" ]; then
    bd update "$ISSUE_ID" --status=closed
    bd comments add "$ISSUE_ID" --author ci \
      "Build passed. Commit: $COMMIT_SHA. Closing automatically."
  fi
fi

Quando la CI chiude quella issue, tutto cio che era bloccato diventa sbloccato. Se un agente sta monitorando bd ready per nuovo lavoro, prende il task sbloccato automaticamente. Nessun umano nel loop per gli sblocchi di routine.

Questa e la differenza tra strumenti che tracciano lo stato e strumenti che lo propagano. La maggior parte dei software di project management fa la prima cosa: aggiorni una card, la card cambia colore. La propagazione significa che gli effetti a valle (sbloccare i dipendenti, evidenziare il lavoro disponibile, aggiornare i progressi) avvengono senza che nessuno clicchi nulla.

Valutare gli strumenti di triage per workflow con agenti

Se stai cercando strumenti per gestire una flotta di agenti, i requisiti sono diversi da quelli di un team umano.

Indispensabile: CLI che gli agenti possano chiamare. Se il tuo issue tracker ha solo una UI web, gli agenti non possono usarlo. Devono poter eseguire comandi shell. bd create, bd update, bd blocked sono tutti one-liner che qualsiasi agente di coding sa gia eseguire. Anche le API REST funzionano, ma richiedono token di autenticazione, client HTTP e gestione errori. Le pipe Unix sono piu semplici.

Indispensabile: grafo delle dipendenze interrogabile. "Bloccato" come etichetta di stato e inutile per l'automazione. Ti serve A dipende da B come dato strutturato cosi gli script possono attraversare il grafo, rilevare cicli e calcolare cosa e pronto.

Indispensabile: letture locali sotto il secondo. Quando gli agenti interrogano per lavoro disponibile, il tempo di risposta conta. Un round-trip API di 2 secondi per query, moltiplicato per 10 agenti che interrogano ogni minuto, crea overhead misurabile. beads restituisce i risultati di bd ready in 30ms su un database da 10K issue perche tutto e locale.

Buono a sapersi: propagazione dei cambiamenti in tempo reale. Se gli agenti creano e risolvono 50 issue all'ora, hai bisogno di vedere lo stato mentre cambia, non su un intervallo di refresh.

Segnale d'allarme: "rilevamento blocchi alimentato dall'AI." Gli strumenti che affermano di rilevare i blocchi analizzando le descrizioni delle issue producono falsi positivi e mancano blocchi reali che non sono mai stati scritti. Le dichiarazioni esplicite bd dep add battono l'inferenza.

Segnale d'allarme: strumenti che richiedono un browser per il triage. Sbloccare un task tramite una UI web richiede 5-15 secondi di click. Tramite la CLI, bd dep remove impiega 18ms. Su 50 task bloccati, sono 1 minuto contro 12 minuti. Quando supervisioni agenti che si muovono velocemente, la velocita di triage e il tuo collo di bottiglia.

Come gestiscono il blocco gli strumenti comuni

Capacita Jira Linear GitHub Issues beads + Beadbox
Tracciamento dipendenze Plugin (Advanced Roadmaps) Relazioni (parziale) Riferimenti tasklist bd dep add di prima classe
Stato bloccato automatico Manuale Manuale Manuale Automatico dalle dipendenze
Rilevamento cicli No No No Integrato (bd dep cycles)
CLI per agenti Jira CLI (terze parti) Linear CLI (limitata) gh (no dipendenze) Completa (bd blocked, bd ready)
Propagazione in tempo reale Webhook (lato server) Webhook (lato server) Webhook (lato server) fs.watch (sotto il secondo, locale)
Funziona offline / locale No No No Si (modalita embedded)
Scriptabile dagli agenti API + token auth API + token auth CLI gh CLI bd (pipe Unix)

Il loop del supervisore

Ecco il workflow che eseguiamo ogni giorno, gestendo piu di 10 agenti AI su un singolo progetto:

  1. Gli agenti dichiarano le dipendenze al momento della creazione del task. Ogni bd create che ha un prerequisito riceve un bd dep add immediatamente. E una singola chiamata CLI aggiuntiva per task.

  2. Un agente supervisore esegue bd blocked ogni 30 minuti. Se qualcosa e appena stato bloccato, lo risolve da solo (ripriorizza, riassegna) o lo segnala all'umano.

  3. Beadbox gira sullo schermo dell'umano. La dashboard mostra l'intero grafo delle dipendenze con i task bloccati evidenziati in tempo reale. La maggior parte delle volte, l'automazione gestisce gli sblocchi di routine. Quando non ci riesce (dipendenza esterna, decisione architetturale, concessione di accesso), l'umano vede il problema immediatamente e interviene.

  4. I task stantii vengono segnalati aggressivamente. Un agente che non ha aggiornato il suo task in-progress da 2 ore e bloccato o crashato. Il supervisore controlla e o stimola l'agente, riassegna il lavoro o indaga.

  5. Le false dipendenze vengono potate continuamente. Gli agenti dichiarano troppe dipendenze durante la pianificazione. Man mano che l'implementazione rivela la vera forma del lavoro, il supervisore (o gli agenti stessi) rimuovono le dipendenze che si sono rivelate inutili. Un grafo pulito e un grafo utile.

Il principio sottostante: gli agenti sono veloci ma non auto-consapevoli. Non sanno cosa stanno facendo gli altri agenti, non notano quando i blocchi si risolvono e non si lamentano quando sono bloccati. Il lavoro del supervisore e essere il sistema nervoso che collega tutto questo. Dati di dipendenza strutturati, interrogati automaticamente e renderizzati visivamente, sono cio che rende possibile tutto questo.


Beadbox e gratis durante la beta. Ti mostra cosa stanno facendo i tuoi agenti, cosa e bloccato e cosa e appena diventato disponibile, in tempo reale.

brew tap beadbox/cask && brew install --cask beadbox

Se usi gia beads, Beadbox legge la tua directory .beads/ esistente senza nessun passaggio di importazione. Provalo.