4.4 KiB
Contrato de integración con n8n — WebChatV2
El frontend hace un POST al webhook de n8n con el mensaje del usuario y el historial,
y espera una respuesta JSON con el texto del asistente y, opcionalmente, KeyNotes
(resumen / To-Do) que se insertan automáticamente en el panel derecho y que el usuario
puede editar después.
1. Configuración de la URL
La URL del webhook se resuelve en tiempo de ejecución (no se "hornea" al compilar), para que puedas cambiarla sin reconstruir la imagen Docker:
public/config.js→ definewindow.APP_CONFIG.N8N_WEBHOOK_URL(prioridad alta).- Si no existe, se usa la variable de entorno
VITE_N8N_WEBHOOK_URL(definida al compilar).
En Docker, edita el archivo config.js servido por nginx (o monta un volumen sobre
/usr/share/nginx/html/config.js) y recarga la página.
2. Request — POST {N8N_WEBHOOK_URL}
Content-Type: application/json
{
"themeId": "theme_abc123",
"subThemeId": "sub_def456",
"themeTitle": "Tema Principal",
"subThemeTitle": "Subtema 1",
"history": [
{ "role": "user", "content": "Hola" },
{ "role": "assistant", "content": "¿En qué puedo ayudarte?" }
],
"message": "Explícame cómo funciona esto"
}
| Campo | Tipo | Descripción |
|---|---|---|
themeId |
string | ID del MainTheme activo. Útil para guardar contexto en n8n/DB. |
subThemeId |
string | ID del SubTheme activo (la conversación actual). |
themeTitle |
string | Título del tema (legible). |
subThemeTitle |
string | Título del subtema (legible). |
history |
array | Mensajes previos {role, content} (orden cronológico). |
message |
string | Texto que el usuario acaba de escribir (NO está incluido en history). |
role es "user" | "assistant".
3. Response — 200 OK (JSON)
{
"reply": "Respuesta en **Markdown** del asistente…",
"keyNotes": [
{
"type": "summary",
"title": "Resumen de la conversación",
"content": "Puntos clave tratados…"
},
{
"type": "todo",
"title": "Tareas pendientes",
"items": [
{ "text": "Revisar la documentación", "done": false },
{ "text": "Configurar el webhook", "done": true }
]
}
]
}
Reglas
reply(obligatorio,string): texto de respuesta. Se renderiza como Markdown (soporta GFM: listas, tablas, bloques de código, etc.).keyNotes(opcional,array): notas que se añaden al SubTheme activo consource: "n8n". El usuario puede editarlas/eliminarlas libremente.
Tipos de KeyNote
type |
Requiere |
|---|---|
summary |
title + content (string, Markdown plano) |
todo |
title + items[] con { text: string, done?: boolean } |
free |
title + content |
done es opcional y por defecto false.
4. Errores y timeouts
- Cualquier status HTTP fuera del rango 2xx se trata como error y se marca el mensaje
como
status: "error". El usuario puede pulsar Reintentar. - Timeout por defecto: 120 s. La solicitud puede cancelarse con el botón Detener
(usa
AbortController), lo que aborta el fetch hacia n8n.
5. Ejemplo de workflow n8n (orientativo)
Webhook (POST /webhook/chat)
→ Set (extraer body.message, body.history, body.themeTitle…)
→ [tu LLM / lógica]
→ Set (construir JSON { reply, keyNotes })
→ Respond to Webhook (JSON, 200)
En n8n usa el nodo Respond to Webhook con
Respond With: JSONy enResponse Bodypega el objeto{ "reply": ..., "keyNotes": [...] }.
6. Evolución futura (streaming / persistencia en DB)
- Streaming: el contrato queda preparado para añadir SSE (
text/event-stream) más adelante sin romper la UI (el indicador "escribiendo…" ya existe). - Persistencia: el estado vive hoy en
localStorage. Para sincronizar con una DB vía n8n, añade endpointsGET/POST /webhook/statey reemplaza el adapter ensrc/store/persistence.ts(punto único de intercambio).