<!--
  Tradotto dall'agente docs da content-src/es/api/copilot-sdk/05-escribir-el-manifiesto-v1.md
  (source_hash bc88037f8c77). Se quel source_hash spagnolo cambia, ricontrolla questa traduzione.
-->

Il manifesto è un JSON con questa forma:

```
{
  "version": 1,
  "app": "il-tuo-sito",
  "sdkMinVersion": "1.1.0",
  "screens": [
    {
      "id": "leads.new",
      "path": "/leads/new",
      "label": { "es": "Nuevo lead", "en": "New lead", "it": "Nuovo lead" },
      "anchors": [
        { "id": "name", "kind": "field", "fieldType": "text", "required": true,
          "label": { "es": "Nombre", "en": "Name", "it": "Nome" } },
        { "id": "phone", "kind": "field", "fieldType": "phone",
          "label": { "es": "Teléfono (sin espacios, sin +, solo dígitos)",
                     "en": "Phone (digits only, no spaces, no +)",
                     "it": "Telefono (solo cifre)" } },
        { "id": "save", "kind": "action", "effect": "write",
          "label": { "es": "Guardar", "en": "Save", "it": "Salva" } }
      ]
    }
  ]
}
```

| Campo | Cos'è |
| --- | --- |
| `version` | Sempre `1` (il numero del contratto descritto da questo manuale). |
| `app` | Un id breve della tua applicazione, informativo. |
| `sdkMinVersion` | La versione minima dell'SDK del copilota richiesta da questo manifesto — almeno `1.1.0` se il tuo sito usa l'attributo neutro `data-copilot-anchor` (paragrafo 4); `1.0.0` basta se usi solo l'attributo precedente. |
| `screens` | Fino a 200 schermate. Ognuna: `id`, `path` (percorso relativo del tuo sito, mai un URL assoluto o esterno), `label` e fino a 100 `anchors`. |

## 5.1 Tipi di ancora

| `kind` | Cosa fa il copilota con essa |
| --- | --- |
| `field` | Può compilarla (modalità «lo facciamo insieme»). Porta `fieldType`. |
| `action` | Può premerla. Porta `effect`. |
| `region` | Può solo evidenziarla (guidare) — non la compila né la preme mai. Utile per select con opzioni che dipendono dai tuoi stessi dati (non si possono dichiarare «chiuse»). |

| `fieldType` | Nota |
| --- | --- |
| `text` · `textarea` · `number` · `email` · `phone` · `date` · `datetime` · `select` · `checkbox` |   |

> **Importante — Non esiste `fieldType: "password"`**
>
> Un manifesto che tenti di dichiarare un campo password viene rifiutato sul server con il motivo esatto. Inoltre, anche se provassi a camuffarlo con un altro tipo, l'SDK non scrive mai in un `<input type="password">` reale della tua pagina — lo verifica contro l'elemento del DOM, non contro ciò che dichiari nel JSON.

| `effect` di un'azione | Conseguenza |
| --- | --- |
| `navigate` | Apre un'altra schermata o rivela qualcosa nella stessa. Senza conferma. |
| `read` | Consulta solamente. Senza conferma. |
| `write` | Salva una modifica. **Conferma sempre** — il server la richiede anche se il piano non la chiede. |
| `send` | Invia qualcosa a terzi (per esempio, rispondere a un cliente). Conferma sempre. |
| `destructive` | Elimina qualcosa. Conferma sempre, con tono distruttivo. |

## 5.2 Regole di forma (il server le impone, senza eccezioni)

- Id di schermata e di ancora: `^[a-z0-9][a-z0-9._-]{0,63}$` — minuscole, numeri, punto, trattino e underscore. Niente maiuscole né spazi (la «T» di `appointmentType` viene rifiutata; `appointment-type` va bene).
- `path` è sempre un percorso relativo del tuo stesso dominio (`/leads/new`) — mai un URL assoluto, mai `javascript:`, mai un dominio esterno.
- Etichette: testo semplice, massimo 80 caratteri, senza `<>{}[]` né caratteri di controllo. Se il tuo manifesto è per la Piattaforma o la sua console interna servono tutte e tre le lingue; per il tuo sito ne basta una.
- Un `field` di tipo `select` deve dichiarare le sue `options` — un elenco chiuso. Se il valore dipende da dati che cambiano (una fase, un responsabile, un catalogo proprio di ogni cliente), non è un `select`: usa `region` e lascia che il copilota lo segnali soltanto.
- Limiti totali: ≤ 200 schermate, ≤ 100 ancore per schermata, ≤ 256 KB il JSON completo, ≤ 30 passi per piano (quest'ultimo lo decide il server convalidando ogni piano, non il tuo manifesto).

> **Nota — Campi telefono: metti il formato nell'etichetta stessa**
>
> In test reali, un assistente ha compilato un numero di telefono con il prefisso «+» perché nulla nell'etichetta diceva il contrario, e il modulo stesso lo ha rifiutato (il sistema ha fallito chiuso, correttamente). Il modo per evitare quel passo indietro inutile è che l'etichetta dell'ancora lo dica esplicitamente: «Telefono (solo cifre, senza spazi né prefisso)» invece di solo «Telefono». L'assistente ha solo quel testo per sapere quale formato ti aspetti.

## 5.3 Manifesto: cosa dichiarare e cosa no

Regole apprese costruendo i manifesti propri della Piattaforma (quello del suo pannello principale e quelli delle sue due console interne) da tenere presenti quando scrivi il tuo:

- **Se il tuo sito può mostrare più istanze dello stesso tipo contemporaneamente** (più canali WhatsApp aperti insieme, più schede della stessa integrazione…), **non dichiarare controlli per istanza**. Lo stesso `data-copilot-anchor` esisterebbe ripetuto nella pagina e l'SDK risolverebbe sempre contro il primo che trova — non necessariamente quello che la persona ha davanti. Dichiara solo ciò che è sicuro ancorare senza ambiguità (una schermata di creazione a istanza singola, per esempio) e lascia il resto non dichiarato, oppure come `region` che guida sull'intero elenco.
- **Un campo le cui opzioni dipendono da dati che cambiano** (un catalogo proprio di ogni cliente, un modello di IA che varia in base al piano, una fase di funnel che la persona stessa personalizza) **non è un `select`** — dichiararlo come elenco chiuso sarebbe inesatto, dato che in realtà non lo è. Dichiaralo come `region`: il copilota lo segnala, e la persona sceglie.
- **`path` con un `?` finale per schermate senza percorso proprio**: se due delle tue schermate condividono la stessa URL di base (per esempio, un modulo che vive sullo stesso percorso del suo elenco, senza un identificativo proprio nell'URL), aggiungi un `?` vuoto alla fine del `path` di quella senza un proprio deep-link — evita che l'SDK confonda quale delle due risolvere navigando sull'URL attuale.
- **Deep-link reattivi**: se usi un parametro dell'URL per aprire una modale o una vista specifica (per esempio `?copilotOpen=new`), leggilo in modo **reattivo** — che reagisca ai cambiamenti dell'URL all'interno della stessa sessione di navigazione, non solo al montaggio del componente — perché altrimenti, un secondo piano del copilota che riutilizza una schermata già aperta non farà scattare di nuovo l'apertura della modale.