El manifiesto es un JSON con esta forma:
{ "version": 1, "app": "tu-web", "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 | Qué es |
|---|---|
version | Siempre 1 (el número del contrato que este manual describe). |
app | Un id corto de tu aplicación, informativo. |
sdkMinVersion | La versión mínima del SDK del copiloto que este manifiesto necesita — como mínimo 1.1.0 si tu web usa el atributo neutro data-copilot-anchor (apartado 4); 1.0.0 basta si solo usas el atributo anterior. |
screens | Hasta 200 pantallas. Cada una: id, path (ruta relativa de tu propia web, nunca una URL absoluta ni externa), label y hasta 100 anchors. |
5.1 Tipos de ancla
Sección titulada «5.1 Tipos de ancla»kind | Qué hace el copiloto con ella |
|---|---|
field | Puede rellenarla (modo «lo hacemos juntos»). Lleva fieldType. |
action | Puede pulsarla. Lleva effect. |
region | Solo puede resaltarla (guiar) — nunca la rellena ni la pulsa. Útil para selects con opciones que dependen de tus propios datos (no se pueden declarar «cerradas»). |
fieldType | Nota |
|---|---|
text · textarea · number · email · phone · date · datetime · select · checkbox |
Importante — No existe
fieldType: "password"Un manifiesto que intente declarar un campo de contraseña se rechaza en el servidor con el motivo exacto. Además, aunque lo intentaras camuflar con otro tipo, el SDK nunca escribe en un
<input type="password">real de tu página — lo comprueba contra el elemento del DOM, no contra lo que tú digas en el JSON.
effect de una acción | Consecuencia |
|---|---|
navigate | Abre otra pantalla o revela algo en la misma. Sin confirmación. |
read | Solo consulta. Sin confirmación. |
write | Guarda un cambio. Confirmación siempre — el servidor la exige aunque el plan no la pida. |
send | Envía algo a un tercero (p. ej. responder a un cliente). Confirmación siempre. |
destructive | Borra algo. Confirmación siempre, en tono destructivo. |
5.2 Reglas de forma (el servidor las exige, sin excepción)
Sección titulada «5.2 Reglas de forma (el servidor las exige, sin excepción)»- Ids de pantalla y de ancla:
^[a-z0-9][a-z0-9._-]{0,63}$— minúsculas, números, punto, guion y guion bajo. Nada de mayúsculas ni espacios (el «e» deappointmentTypese rechaza;appointment-typesí vale). pathes siempre una ruta relativa de tu propio dominio (/leads/new) — nunca una URL absoluta, nuncajavascript:, nunca un dominio externo.- Etiquetas: texto plano, máximo 80 caracteres, sin
<>{}[]ni caracteres de control. Si tu manifiesto es para la Plataforma o su consola interna necesitas los tres idiomas; para tu propia web basta con uno. - Un
fieldde tiposelecttiene que declarar susoptions— una lista cerrada. Si el valor depende de datos que cambian (una etapa, un responsable, un catálogo propio de cada cliente), no es unselect: usaregiony deja que el copiloto solo lo señale. - Límites totales: ≤ 200 pantallas, ≤ 100 anclas por pantalla, ≤ 256 KB el JSON completo, ≤ 30 pasos por plan (esto último lo decide el servidor al validar cada plan, no tu manifiesto).
Nota — Campos de teléfono: pon el formato en la propia etiqueta
En pruebas reales, un asistente rellenó un teléfono con el prefijo «+» porque nada en la etiqueta decía lo contrario, y el propio formulario lo rechazó (el sistema falló cerrado, correctamente). La forma de evitar esa vuelta atrás innecesaria es que la etiqueta del ancla lo diga explícitamente: «Teléfono (solo dígitos, sin espacios ni prefijo)» en vez de solo «Teléfono». El asistente solo tiene ese texto para saber qué formato esperas.
5.3 Manifiesto: qué declarar y qué no
Sección titulada «5.3 Manifiesto: qué declarar y qué no»Reglas aprendidas construyendo los propios manifiestos de la Plataforma (el de su panel principal y los de sus dos consolas internas) que conviene tener en cuenta al escribir el tuyo:
- Si tu web puede mostrar varias instancias del mismo tipo a la vez (varios canales de WhatsApp abiertos a la vez, varias tarjetas de la misma integración…), no declares controles por instancia. El mismo
data-copilot-anchorexistiría repetido en la página y el SDK siempre resolvería contra el primero que encuentre — no necesariamente el que la persona tiene delante. Declara solo lo que sea seguro de anclar sin ambigüedad (una pantalla de alta de una sola instancia, por ejemplo) y deja el resto sin declarar, o comoregionguía sobre el listado entero. - Un campo cuyas opciones dependen de datos que cambian (un catálogo propio de cada cliente, un modelo de IA que varía según el plan, una etapa de embudo que la propia persona personaliza) no es un
select— sería declarar como lista cerrada algo que en realidad no lo es. Decláralo comoregion: el copiloto lo señala, y la persona elige. pathcon un?final para pantallas sin ruta propia: si dos de tus pantallas comparten la misma URL base (por ejemplo, un formulario que vive en la misma ruta que su listado, sin un identificador propio en la URL), añade un?vacío al final delpathde la que no tenga su propio deep-link — evita que el SDK confunda cuál de las dos resolver al navegar por la URL actual.- Deep-links reactivos: si usas un parámetro de la URL para abrir un modal o una vista concreta (por ejemplo
?copilotOpen=new), léelo de forma reactiva — que reaccione a cambios de la URL dentro de la misma sesión de navegación, no solo al montar el componente — porque si no, un segundo plan del copiloto que reutiliza una pantalla ya abierta no volverá a disparar la apertura del modal.
