Due varianti di card
Ogni risposta del connettore contiene un camporoute. L’inbox mostra una delle due varianti di card in base a quel route.
draft_reply — messaggio proposto
L’agente è sufficientemente sicuro da suggerire una risposta pronta per l’invio. L’operatore vede la card di bozza AI già esistente:
- Intestazione: ✨ AI draft · proposto ora
- Badge dei metadata: route, intent, confidence, destination/dateWindow/partySize opzionali
- Corpo: il testo del messaggio proposto
- Azioni: Accetta e invia, Modifica, Rifiuta
human_review — anteprima del passaggio a un operatore
L’agente non ha sufficiente confidence (oppure la policy non consente l’invio automatico) e restituisce la conversazione a un operatore umano. L’operatore vede la nuova card ambra di anteprima del passaggio:
- Intestazione: 🧭 Anteprima passaggio all’agente · proposto ora
- Badge: route (Human review), connector (gb-customer-agent), tipo di handoff opzionale
- Sezioni (mostrate solo se popolate):
- Handoff packet — tipo, coda raccomandata, task aperti, verifica richiesta, limite di dry-run
- Azioni di revisione proposte — chip di sola revisione (senza click handler, senza effetti collaterali); ognuno etichettato “Solo revisione”
- Riferimenti a evidenze — fino a 5 visibili, link solo https, ID in stile mono per le evidenze non-link
- Azioni: solo Ignora (nessun Accetta/Invia, nessun bottone per creare task operatore, nessun bottone di assegnazione coda)
Feature flag
La card di anteprima del passaggio è controllata dal feature flaginbox.gbAgentHandoffPreview.
- Default: OFF in tutti i workspace.
- Abilitare per deployment: impostare la env var
NEXT_PUBLIC_FLAG_INBOX_GB_AGENT_HANDOFF_PREVIEW=1sul progetto Vercelapps/app. Il flag entra in vigore al deploy successivo. - Quando è OFF: le bozze con
route === "human_review"continuano a mostrare il badge sottile “Human review” all’interno della card di bozza esistente. Nulla altro cambia. - Quando è ON: viene renderizzata la Variante B per quelle bozze.
Il limite del dry-run
Di default il connettore gb-agent è limitato a proporre — non ad agire. Questo è imposto su tre livelli (UI, worker e schema di risposta) ed è il contratto per Draft with me manuale, bozze connector avviate manualmente, handoffhuman_review e modalità proattiva quando proactive_draft_auto_send_first=false:
L’unica eccezione intenzionale è l’opt-in esplicito documentato sotto:
proactive_draft_auto_send_first=true può accettare e inviare la prima bozza proattiva draft_reply riuscita da trigger Flow/keyword usando lo stesso RPC accept_message_draft_for_dispatch del pulsante operatore. Fuori da quel percorso ristretto, gli effetti restano azioni manuali dell’operatore dentro Switchbord. Se noti qualsiasi altra azione autonoma dell’inbox come risultato di una risposta del connettore, è un bug — segnalalo.
”Draft with me” (assistenza streaming per singola conversazione)
Separatamente dalle due varianti di card sopra, il composer ha un trigger “Draft with me” — una singola pillola violetta (SparklesIcon) sul margine destro del composer, protetta dalla stessa access mode draft_with_me del resto della superficie del connettore (/api/inbox/gb-agent/access). Cliccandolo si avvia lo streaming di una bozza a contesto completo per la conversazione aperta, mostrata in una barra di stato minimizzata sopra il composer; nulla viene mai inviato automaticamente.
A partire dalla v0.18.29, Draft with me è l’unico trigger AI nel composer — la precedente run-action inline
BotMessageSquare e il suo duplicato compatto sono stati ritirati, così gli operatori hanno un unico punto di accesso non ambiguo.Run per conversazione, in background
A partire dalla v0.18.30, un’esecuzione di Draft with me è associata alla sua conversazione, non al componente montato del composer. Lo stato della run (status, phase, trace, testo finale della bozza, motivo dell’handoff) vive in uno store a livello di modulo (gb-agent-draft-runs-store) indicizzato per id di conversazione. In pratica, questo significa che:
- Passare a una chat diversa mentre una bozza è in generazione non la annulla — la run continua lo streaming in background e sarà ancora lì (terminata, passata a un operatore, o fallita) quando l’operatore torna indietro.
- Ogni riga di conversazione, l’intestazione della chat aperta e la striscia delle tab (vedi Funzionalità avanzate dell’inbox) mostrano un badge di stato
BotMessageSquarein tempo reale, colorato in base alla run di quella conversazione — violetto/pulsante durante lo streaming, verde quando una bozza è pronta, ambra su un passaggio a human-review, rosso in caso di errore, e nascosto quando inattivo. - Solo il controllo esplicito ✕ / Stop annulla una run. Smontare il composer (navigando altrove) non la interrompe più.
- Avviare una nuova run per la stessa conversazione sostituisce qualsiasi run in corso precedentemente.
Barra di stato minimizzata
Il panel (v0.18.17) non coprirà mai la chat — viene mostrato come una barra sottile con un punto di stato colorato e un’espansione al click:
Espandendo la barra si rivela il testo della risposta in streaming, una traccia di ragionamento/tool collassabile e (mentre è attiva) un controllo Stop più la ✕ sempre visibile che chiude completamente la barra (annullando una run ancora in streaming).
panelDismissed e panelExpanded si azzerano entrambi al cambio di conversazione e a ogni nuova run, così una barra obsoleta non si sovrappone mai fra chat diverse. Se un nuovo messaggio in entrata arriva a metà run, un banner ambra chiudibile “contesto obsoleto” avvisa l’operatore che la bozza in corso potrebbe rispondere a un messaggio non più attuale — la run non viene annullata automaticamente.
Catena di fallback
A partire dalla v0.18.20, un’esecuzione di Draft with me è una catena di tentativi, non una singola richiesta: streaming → retry dello streaming con backoff con jitter → fallback deterministico non-streamdraft-run. L’operatore ottiene sempre una bozza pronta e utilizzabile oppure un errore esplicito e chiaro — mai un composer vuoto in silenzio. Mentre la catena procede tra i retry o il fallback deterministico, la barra espansa mostra un suggerimento “retrying…” / “falling back…” così l’attesa viene spiegata invece di rimanere silenziosa.
Copy chat → traccia di debug della bozza
Il pulsante Copy chat del pannello della chat (in alto a destra, icona appunti) scrive un export JSON strutturato negli appunti contenente il contesto completo della conversazione (v0.18.13). A partire dalla v0.18.33, se una run di Draft with me è mai stata eseguita per quella conversazione, l’export porta anche con sé un bloccodraftWithMe — omesso interamente quando non è mai stata eseguita alcuna run (status è idle), così le conversazioni per cui non è mai stata generata una bozza restano pulite:
finalDraftTexte ciclo di vita (status/phase, se è stato usato il fallback deterministico)handoffReasonquando la run è stata instradata a human reviewtraceEvents(etichette, tipo di decisione/evento, stato ok/warn) — la stessa traccia di ragionamento mostrata nella barra espansasessionIdeinboundMessageIdper correlare con i log server-sidelastError(messaggio, flagrecoverable, e — a partire dalla v0.18.34 — undetailupstream privo di contenuto sensibile comeAI_APICallError status=429 cause=RateLimitError, limitato a 200 caratteri) quando lo stato terminale della run è stato un fallimento
Bozze proattive per Flow campagna e auto-send-first
Indipendentemente dal trigger manuale “Draft with me”, un workspace può attivare la generazione proattiva delle bozze (v0.18.12, BORD-818): GB-Agent genera una bozza in background e la mette nel composer prima che l’operatore apra la conversazione. Per i Flow di campagna GB, la forma reale in produzione è:- Webhook Meta:
type: "interactive",interactive.type: "nfm_reply",interactive.nfm_reply.name: "flow". - Placeholder visibile nel messaggio:
"Sent". - Messaggio normalizzato in Switchbord:
body = "Sent",payload.messageType = "interactive",payload.replyKind = "interactive_flow", epayload.flowResponseRedactedpresente. - Le conversazioni originate da campagna di solito hanno label
campaign/Campaign, ma il trigger Flow deve basarsi supayload.replyKind = "interactive_flow"; la keywordsentè solo fallback per payload degradati.
Note operative:
proactive_draft_delay_seconds(0–300, default 10) attende dopo il messaggio inbound prima di generare. Un nuovo inbound cancella un job proattivo ancora pending e riavvia il delay sul messaggio più recente.proactive_draft_label_filtersè case-insensitive;campaignmatcha label comeCampaign. Lascia vuoto per consentire qualunque Flow completion.proactive_draft_auto_send_firstè stretto: solo la prima bozza proattivadraft_replyda triggerflow_completion/keywordin una conversazione può essere accettata automaticamente. Job legacyall_inbound, bozzehuman_review, conversazioni con draft già accettato, outbound umano, o blocchi RPC degradano a draft-only.- L’auto-send usa comunque lo stesso RPC
accept_message_draft_for_dispatchdel pulsante Send operatore, preservando idempotenza, audit, gate consenso/finestra servizio e outboxmessage.dispatch.
GB-Agent Insights
/insights ha una tab GB-Agent (v0.18.16, BORD-741) — analytics di sola lettura, scoped al workspace, per il rollout e il perfezionamento, basata su responder_runs (la stessa tabella di telemetria su cui scrivono Draft with me e le bozze proattive). Non c’è nessun gate di controllo dei costi qui; la tab esiste puramente per rendere visibile l’utilizzo di GB-Agent.
La tab mostra:
- Tile di riepilogo — richieste, completamenti, timeout, fallimenti, più i tassi di completamento/timeout/fallimento.
- Suddivisione degli outcome —
sent_unmodified,sent_modified,rejected,abandoned,timeout,failed, con il tasso di modifica derivato (sent_modified / (sent_unmodified + sent_modified)) e il tasso di rifiuto. - Distribuzione della edit-distance — un istogramma a bucket (0–10%, 10–25%, 25–50%, 50–75%, 75%+) di quanto testo di una bozza
sent_modifiedè stato modificato dall’operatore prima dell’invio, più il rapporto medio. - Percentili del tempo di invio — latenza p50 / p90 / p99 / media della decisione operatore (
time_to_action_ms). - Rollup per modalità e per operatore/agente — la stessa suddivisione aggregata raggruppata per
responder_type(Response AI vs. campagna) o peragent_id.
GET /api/insights/gb-agent, che accetta sinceDays (default 30, limitato tra 1–365) oppure from/to espliciti e condivide i selettori SSR di channel/intervallo di date con il resto di /insights. L’accesso è controllato allo stesso modo del resto di /insights (requireOperationsAccess).
Configurare il connettore
La configurazione dell’operatore avviene in Settings → Integrations → gb-agent. (Quando questa superficie sarà rilasciata completamente, la guida in-product ne coprirà i passaggi in dettaglio; questa pagina è la fonte attuale di verità.) Configurazione richiesta:- Endpoint URL — l’endpoint completo di draft-run su cui Switchbord invia il contesto del messaggio in entrata per la valutazione. Per GBCA in produzione, usa
https://gb-customer-agent-production.up.railway.app/api/agent/draft-run, non solo la root del servizio. Deve essere https senza userinfo, query string o fragment. - Tool-surface token — archiviato come secret di workspace nel Supabase Vault, non viene mai restituito in nessuna risposta API. Ruotarlo tramite la UI del Vault.
- Test connection — la pagina Settings esegue un
GETautenticato sicuro all’endpoint configurato e si aspetta che il connettore riporti una capabilitydraft_runprima di mostrare il successo.
Stati di triage
Quando il trigger dell’inbox è disabilitato, il badge indica perché:Vedi anche
- Operations → Runbook — blocco di triage gb-agent
- Operations → Feature Flags — catalogo dei flag
- Security → Vault Architecture — secret di workspace
- Platform → Data Model — struttura di
message_draftseresponder_runs - Features → Advanced Inbox Features — banner di connessione e tab di conversazione che mostrano lo stato di Draft with me