> ## Documentation Index
> Fetch the complete documentation index at: https://docs.mattone.co/llms.txt
> Use this file to discover all available pages before exploring further.

# Standard: un solo numero, zero chiamate perse

> Procedura replicabile per far convergere tutti i contatti ospite su un unico numero WhatsApp/voce e costruire la rete di sicurezza che impedisce di perdere una chiamata.

Un ospite non deve mai chiedersi dove scriverti. Questo standard fa convergere **ogni** punto di contatto ospite su **un solo numero** (stesso numero per WhatsApp, SMS e voce) e ci costruisce sopra una rete di sicurezza in tre strati perché nessuna chiamata resti senza risposta.

È stato implementato per primo su **Cosmica Dubai** il 22 agosto 2026 ed è la procedura da replicare su Cosmica Italia e su ogni workspace studente.

<Note>
  Perché conta: un recapito che non risponde non produce un errore. Produce silenzio. L'ospite ci prova, non ottiene risposta e non ti dice nulla — lo scopri dalla recensione. Tutti i guasti trovati durante la prima implementazione erano di questo tipo: attivi, verdi in dashboard, e completamente muti.
</Note>

## Il principio

* **Un numero solo, ovunque.** Stesso numero per chat WhatsApp, SMS e chiamate: è il **numero frontend**. Nessun secondo recapito ospite. Il **numero backend** su cui vive il voice agent non è un secondo recapito: l'ospite non lo vede mai, e riceve le chiamate per inoltro dal frontend ([Numero backend e numero frontend](/integrazioni/conduit/telefonia-waba#numero-backend-e-numero-frontend)).
* **Detto, non solo presente.** Il numero va pronunciato e ripetuto: benvenuto, pre-arrivo, giorno del check-in, durante il soggiorno.
* **Ogni chiamata persa genera un'azione**, non un buco: alert al team più risposta automatica all'ospite.

## Prerequisiti

Prima di iniziare devi avere:

* Il numero definitivo già collegato come **sender WhatsApp** e come **sender SMS di default** del workspace.
* Il numero definitivo come numero pubblico ospite (il **frontend**), con l'**inoltro delle chiamate** verso il numero backend dove risponde il VoiceAI. Non è un'opzione, è lo standard: il voice agent resta sempre sul backend, così un cambio di numero pubblico non tocca l'agente vocale.
* Un canale Slack dove il team riceve le escalation.

Verifica il primo punto prima di toccare qualsiasi altra cosa:

```bash theme={null}
curl -s "https://api.conduit.ai/v1/workspaces/$WS/senders" \
  -H "Authorization: Bearer $CONDUIT_TOKEN"
```

Se il numero nuovo non compare tra i sender `whatsapp` e `sms`, fermati: tutto il resto poggia su questo.

<Note>
  **Stai cambiando il numero frontend?** Lato voce cambia **solo l'inoltro**, dal numero nuovo verso lo stesso backend: il voice agent, le sue istruzioni e il suo fallback non si toccano. Questa pagina è il lato ospite: portare il numero nuovo ovunque c'era il vecchio.
</Note>

## Ordine di esecuzione

L'ordine non è arbitrario. Prima si mette in sicurezza ciò che è già rotto, poi si aggiunge il nuovo.

<Steps>
  <Step title="Censisci ogni recapito che raggiunge l'ospite">
    Non fidarti della memoria né della dashboard. Estrai e cerca il numero vecchio in **tutte** queste superfici:

    | Superficie | Come estrarla | Cosa cercare |
    | - | - | - |
    | Workflow | `GET /v1/workspaces/{ws}/workflows` poi `GET /v1/workflows/{id}` per ognuno | `provider`, `aiProvider`, testi dei messaggi |
    | Knowledge base | `POST /v1/kb/nodes/search` con `include_body: true` | numeri nel body di ogni nodo |
    | Agent | `GET /v1/agents` | `instructions` e **tutte** le guardrail |
    | Skill | `GET /v1/skills` | `body` |
    | Voice agent | `list_voice_agents` (MCP) | `instructions`, `fallback_phone_number` |
    | Template WhatsApp | `GET /v1/workspaces/{ws}/whatsapp-templates` | `body` dei template approvati |
    | Guest portal | `GET /v1/workspaces/{ws}/portal-guides` | testi rivolti all'ospite |

    Fai il grep su un dump locale, non a occhio in dashboard. Su Dubai questa passata ha trovato 162 nodi KB, 41 guardrail e 15 workflow: nessuno di questi elenchi è ispezionabile a mano.
  </Step>

  <Step title="Ripara i sender morti prima di aggiungere qualsiasi cosa">
    Uno step `SEND_MESSAGE` che punta a un sender WhatsApp non più collegato **non fallisce in modo visibile**: il workflow resta `ACTIVE`, `enabled: true`, e il messaggio non parte. È la categoria peggiore di guasto.

    Per ogni step trovato al passo 1, sostituisci `provider` con il nuovo sender (`whatsapp:+<numero>`).

    Controlla anche `runOnData`: se vale `{"type": "direct", "contactId": "..."}` il messaggio va **sempre a quel contatto**, mai all'ospite del trigger. Il valore corretto per un messaggio all'ospite è `{"type": "trigger"}`.
  </Step>

  <Step title="Riscrivi il nodo KB del contatto ospite">
    Deve esistere **un solo** nodo che dichiara il numero, con scope workspace (`entity_ids: []`), perché è un fatto valido per tutti i listing. Se il workspace ospita listing di un'altra città o paese con un numero diverso, l'eccezione va scritta **dentro lo stesso nodo**, non in un nodo parallelo: due nodi sullo stesso tema confondono la ricerca semantica.

    Il nodo deve contenere quattro sezioni:

    1. Il numero unico e i canali che copre.
    2. La frase standard da dire all'ospite, con i momenti in cui ripeterla.
    3. **L'elenco esplicito dei numeri che non vanno mai dati** (vecchio numero, **numero backend** del voice agent, cellulari del team).
    4. Le eccezioni per listing di altre aree.

    Il punto 3 è quello che di solito manca ed è quello che evita che l'AI ripeschi il numero vecchio da una conversazione passata.
  </Step>

  <Step title="Aggiorna guardrail e skill dell'agente">
    Il nodo KB dice *qual è* il numero. Le guardrail dicono *cosa deve fare* l'agente. Servono entrambe.

    Trasforma la guardrail sui contatti da permissiva a **prescrittiva**: non "può condividere il numero" ma "deve darlo, chiaramente e più di una volta". Aggiungi nella stessa guardrail il divieto esplicito sui numeri ritirati.

    Rileggi tutte le skill: quelle che invitano l'ospite a spostarsi su WhatsApp contengono spesso il numero scritto a mano.

    <Warning>
      `PATCH /v1/agents/{id}` sostituisce l'intero array `guardrails`. Fai read-modify-write dell'array completo e verifica il conteggio dopo la scrittura, altrimenti ne perdi silenziosamente una parte.
    </Warning>
  </Step>

  <Step title="Fai dire il numero nei messaggi, non solo scriverlo nella KB">
    Nei punti di contatto lungo il soggiorno il numero va detto a voce alta:

    * **Step `SEND_AI_MESSAGE` e `AGENT_INJECTION_MESSAGING`**: appendi alle istruzioni una riga obbligatoria del tipo "chiudi sempre con: *Per qualsiasi cosa scrivici o chiamaci qui: +XX XXX XXX XXXX — rispondiamo 24/7*", specificando di tradurre la frase ma **non** il numero.
    * **Step `AGENT_INJECTION_PHONE` e voice agent**: scrivi il numero **in lettere**, cifra per cifra (es. "tre, nove, uno, ..."), perché la sintesi vocale non lo legga come un numero intero.

    <Warning>
      **I template WhatsApp non sono modificabili da Conduit.** Sono Content Template Twilio già approvati: dall'API puoi solo leggerli (`GET /whatsapp-templates`) e mappare le variabili. Se il numero deve comparire nel testo del template serve un nuovo template e una nuova approvazione Meta. Nel frattempo il numero è comunque il mittente, quindi rispondere al thread arriva al posto giusto.

      Quali template devono esistere in un workspace, con quale categoria e con quale testo: [Template WhatsApp, il set minimo](/integrazioni/conduit/template-whatsapp).
    </Warning>
  </Step>

  <Step title="Configura il gruppo di chiamata">
    Il gruppo di chiamata è ciò che fa squillare le persone reali quando l'AI non basta.

    ```bash theme={null}
    curl -s -X POST "https://api.conduit.ai/v1/call-groups" \
      -H "Authorization: Bearer $CONDUIT_TOKEN" \
      -H "Content-Type: application/json" \
      -d '{
        "workspace_id": "'"$WS"'",
        "name": "Guest Line — Overflow",
        "strategy": "simultaneous",
        "member_user_ids": ["<user_id>", "..."],
        "phone_number_ids": ["<phone_number_config_id>"]
      }'
    ```

    Usa `simultaneous`: squillano tutti insieme, è la strategia che massimizza la probabilità di risposta. `longest_idle` distribuisce il carico ma allunga i tempi.

    Gli `member_user_ids` sono i campi `id` (non `member_id`) di `GET /v1/workspaces/{ws}/users`.

    <Warning>
      **Trappola verificata.** L'API pubblica non espone alcun endpoint per elencare i numeri del workspace: `phone_number_ids` vuole un `phoneNumberConfig` id che non puoi enumerare. L'unico id ottenibile via API è quello di un numero già trasformato in voice agent (è il campo `id` di `list_voice_agents`). Per gli altri numeri l'id va preso dalla dashboard. Un id sbagliato produce un generico `400 One or more member or phone number ids are invalid`, senza dire quale.
    </Warning>
  </Step>

  <Step title="Crea il workflow chiamata persa">
    Trigger `CALL_MISSED`, due step in catena:

    1. `SEND_SLACK_MESSAGE` al canale escalation, con nome, numero del chiamante, numero chiamato, sommario, link alla conversazione e **l'SLA di richiamata**.
    2. `SEND_MESSAGE` all'ospite dal numero unico.

    Configura il trigger con `inboxTypeId: "global"` e `incomingPreference: "incoming"`: `"guest"` scarterebbe le chiamate da chi non è ancora mappato come ospite, cioè proprio quelle che non vuoi perdere.

    <Warning>
      **`SEND_MESSAGE` non supporta WhatsApp a testo libero.** I tipi ammessi sono `last_message`, `ota`, `pms`, `line_oa`, `whatsapp_template` / `sms_template` (che richiedono un `contentSid` approvato), `sms`, `email`, `slack`. Per la risposta automatica alla chiamata persa usa quindi **`sms` dal numero unico**: il chiamante ha appena composto quel numero, riceve l'SMS dallo stesso numero, e non c'è nessuna finestra di 24 ore da rispettare. Aggiungi lo step `whatsapp_template` solo quando hai un template approvato per il caso "chiamata persa" (nel set minimo è `missed_call_callback_dxb`, vedi [Template WhatsApp](/integrazioni/conduit/template-whatsapp)).
    </Warning>

    Imposta `skipUnavailableChannel: true`: le chiamate con numero nascosto non hanno un recapito e lo step va saltato, non fatto fallire.
  </Step>

  <Step title="Popola il fallback del voice agent">
    Se l'agente vocale non sa risolvere o l'ospite chiede una persona, il trasferimento deve avere una destinazione:

    * `escalation_enabled: true`
    * `escalation_type: "static"`
    * `fallback_phone_number`: il cellulare del referente on-ground

    Verifica anche `schedule`. `schedule: null` significa **sempre attivo**: è quello che vuoi. Uno schedule con finestre orarie manda in vuoto tutto ciò che arriva fuori orario. Se l'inoltro dal frontend è attivo solo in certe fasce, lo `schedule` deve coprire **almeno** quelle stesse ore.
  </Step>
</Steps>

## Come si verifica

Non dichiarare fatto senza aver rieseguito la ricerca. Quattro controlli, tutti da eseguire davvero:

1. **Nessun residuo.** Riesegui il dump del passo 1 e cerca il numero vecchio. Gli unici risultati ammessi sono le regole negative che hai scritto tu ("non dare mai questo numero") e l'eventuale caller ID in uscita.

2. **Recupero semantico.** Interroga la KB con la domanda di un ospite vero:

   ```bash theme={null}
   # MCP: semantic_knowledge_search
   { "query": "what number can I call you on, how do I reach you on WhatsApp" }
   ```

   Il nodo del numero unico deve essere il primo risultato con un punteggio alto (su Dubai: `0.906`). Se non lo è, il nodo è scritto male o ce n'è un altro che gli fa concorrenza.

3. **Rilettura dopo ogni scrittura.** Ogni `PUT /v1/workflows/{id}` crea una **nuova versione con nuovi id di step**: gli id che avevi in mano prima della scrittura non valgono più. Rileggi il workflow dal server e conta le occorrenze del numero nuovo e di quello vecchio.

4. **Prova dei canali.** Chiamata e WhatsApp al numero frontend, ed escalation, da un telefono del team: è la [verifica finale dei canali](/integrazioni/conduit/telefonia-waba#verifica-finale-dei-canali). La configurazione letta dice che il percorso esiste; solo la prova dice che arriva a qualcuno.

Non inviare messaggi di prova a ospiti reali. Per i workflow, la verifica si fa leggendo la configurazione e, se serve, aspettando il primo evento vero su `GET /v1/workflows/{id}/executions`.

## Errori che abbiamo già fatto

* **Fidarsi dello stato del workflow.** `ACTIVE` + `enabled: true` non dice nulla sul fatto che il messaggio parta. Su Dubai due workflow in produzione puntavano a un sender WhatsApp scollegato.
* **`runOnData` cablato.** Se il destinatario di uno step è un contatto fisso invece di quello della prenotazione, il workflow manda il messaggio sempre alla stessa persona, con dentro i dati di ospiti diversi. Non produce nessun errore e nessun alert: lo vedi solo aprendo le esecuzioni. Controlla il destinatario di ogni step che invia.
* **Nome host cablato nel template.** Le variabili dei template con un nome di persona scritto a mano restano lì anche quando la persona non lavora più con noi. Controllale a ogni giro.
* **Lasciare un numero ritirato come caller ID in uscita.** Se il concierge chiama da un numero diverso da quello unico, l'ospite richiama **quel** numero. Se non ha né voice agent né inoltro, la chiamata si perde in silenzio. Se per qualsiasi ragione il caller ID resta diverso, aggancia comunque quel numero al gruppo di chiamata e assicurati che il workflow chiamata persa lo copra.

## Replicare su Italia e sugli studenti

La procedura è identica; cambiano solo tre cose.

| Elemento | Da adattare |
| - | - |
| Numero frontend | Uno per workspace. Mai riusare il numero di un altro workspace in un nodo KB. |
| Contatti interni | I riferimenti di escalation sono locali: chi risponde a Dubai non risponde in Italia. Riscrivi il nodo dei contatti interni, non copiarlo. |
| Template WhatsApp | I `contentSid` sono per workspace. Un `contentSid` di un altro workspace non esiste qui: i template vanno ricreati e riapprovati sul workspace dello studente, partendo dal [set minimo](/integrazioni/conduit/template-whatsapp). |

Per gli studenti, i passi 3, 4, 5, 7 e 8 sono automatizzabili in fase di provisioning: sono tutte chiamate API con lo stesso payload, parametrizzato sul numero e sul canale Slack dello studente. Il passo 6 richiede oggi un passaggio in dashboard per recuperare l'id del numero.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.