Módulo 5: Sistemas multi-agente: agentes que se delegan tareas
5. Diseñar el equipo: roles, handoffs y contratos entre agentes
Descripción
Al terminar esta lección vas a poder escribir la ficha de rol de un agente especialista —su ámbito, su criterio de salida, qué recibe, qué devuelve, qué puede hacer y qué hace cuando no puede resolver—, vas a poder convertir la respuesta de ese especialista en una salida estructurada que el orquestador pueda interpretar sin adivinar, y vas a poder distinguir los tres tipos de handoff que existen entre agentes, sabiendo cuál soporta n8n de forma nativa y cómo se resuelven los otros dos sin salirse del patrón.
Esto importa porque en la lección 4 conectaste los agentes y todo funcionó — en el camino feliz. Un cliente con un caso claro, un especialista que resuelve, una respuesta limpia. El problema empieza en el segundo día, cuando llegan los casos que no son el camino feliz: el cliente no dio el número de pedido, el especialista consultó y no encontró nada, el caso resultó ser de otro dominio, la acción necesitaba aprobación humana. En todos esos casos el especialista devuelve algo, y ese algo es prosa libre que el orquestador tiene que interpretar. "No pude encontrar el cargo, quizás convendría revisar con otro método de pago" — ¿eso significa que el caso quedó pendiente, que hace falta preguntarle algo al cliente, o que el especialista se rinde? El orquestador lo va a interpretar, y a veces va a interpretarlo mal, y ese es exactamente el tipo de falla que en producción se ve como "el agente respondió cualquier cosa". El contrato es lo que elimina esa adivinanza.
Conexión con el módulo: la lección 4 te dio el cable; esta lección le da forma a lo que viaja por el cable. Es la continuación directa de la lección 5 del Módulo 4 —el contrato de una tool: nombre, descripción, parámetros— llevada al caso donde la tool es un agente y la respuesta ya no es un dato sino un juicio. La lección 6 toma este contrato y usa uno de sus campos, el estado del caso, como condición de parada del sistema completo.
Una orden de trabajo que se puede cumplir sin preguntar
Piensa en dos formas de mandarle trabajo al taller mecánico de la empresa.
La primera: alguien deja una nota sobre el mostrador que dice "la camioneta blanca hace un ruido". El mecánico va a tener que averiguar cuál camioneta blanca de las tres que hay, qué tipo de ruido, cuándo lo hace, quién lo reportó y a dónde mandar el resultado. Va a hacer el trabajo, probablemente bien, pero va a gastar la mitad del tiempo reconstruyendo el encargo — y si adivina mal alguna de esas cosas, va a hacer bien un trabajo que no era.
La segunda: una orden de trabajo con campos. Vehículo: placa ABC-123. Reportado por: logística. Síntoma: ruido metálico al frenar en seco, desde el lunes. Prioridad: alta. Y al pie, un espacio donde el mecánico escribe el resultado con una casilla marcada: reparado / requiere repuesto / no se pudo reproducir.
Esa segunda forma tiene dos mitades y las dos importan. La de arriba es el contrato de entrada: qué tiene que traer un encargo para que se pueda cumplir sin preguntar. La de abajo es el contrato de salida: qué forma tiene el resultado, para que quien lo reciba pueda actuar sin interpretar prosa. La casilla marcada es lo que permite que el sistema entero funcione: quien recibe la orden completada no lee un párrafo y decide qué significa — lee una casilla.
Entre agentes pasa exactamente lo mismo, con un agravante: el modelo del orquestador es muy bueno interpretando prosa, lo cual es una trampa. Va a interpretar cualquier cosa que le devuelvan y va a producir una respuesta que suena bien. La mayoría de las veces acertará. Y las veces que no, no vas a tener forma de detectarlo salvo leyendo la conversación, porque no hubo ningún error.
Las cinco cláusulas del contrato de un agente
Un contrato de agente tiene cinco partes. Las cinco caben en una ficha de media página, y escribirla antes de configurar el nodo ahorra la mitad del trabajo de depuración después.
1. Rol y criterio de salida
Una frase que diga qué ámbito cubre, y una que diga cuándo termina su trabajo. Ya trabajaste esto en la lección 2: el criterio de salida no puede tener un "o" que separe dominios.
Rol: especialista en facturación de TuTienda.
Ámbito: cargos no reconocidos, dudas sobre montos, disputas, estados
de cuenta.
Fuera de ámbito: devoluciones de producto, estado de envíos,
recomendaciones.
Criterio de salida: el cargo quedó explicado, o quedó una disputa
abierta con su número, o quedó registrado qué dato falta
para poder resolverlo.
Ese tercer "o" del criterio de salida es distinto a los que rechazaste en la lección 2: no separa dominios, separa desenlaces del mismo caso. Todo contrato bien escrito tiene al menos un desenlace de fracaso, y escribirlo es lo que evita que el agente invente un final feliz cuando no lo hay.
2. Contrato de entrada
Qué campos mínimos debe traer el encargo para que el especialista pueda empezar. No es una lista de deseos: es lo mínimo sin lo cual no se puede hacer nada.
Entrada mínima:
- customer_id (obligatorio)
- amount (obligatorio: el monto del cargo en disputa)
- approximate_date (obligatorio: cuándo apareció el cargo)
- description (obligatorio: qué dice el cliente que pasó)
Entrada opcional:
- order_id (si el cliente lo relacionó con una compra)
Y aquí hay una decisión de diseño que conviene tomar de forma explícita: ¿el contrato de entrada es un texto o son campos?
- Un solo campo de texto (
task), como en la lección 4. Simple de configurar, flexible, y el modelo del orquestador redacta un encargo en prosa. La disciplina de que traiga todos los datos vive en ladescriptiondel$fromAI(). - Varios campos tipados (
customer_id,amount,approximate_date,description), cada uno con su propio$fromAI(). Más estricto: el orquestador tiene que producir cada campo por separado, y si no encuentra elamounten la conversación, eso queda visible en la traza como un campo vacío en vez de escondido dentro de un párrafo.
La segunda forma es más robusta y es la que conviene cuando el especialista toma decisiones costosas. Se implementa cómodamente con el mecanismo de sub-workflow de la lección 4, donde el Execute Sub-workflow Trigger con Define Using Fields Below declara los campos y sus tipos — el contrato de entrada queda escrito en el nodo, no solo en tu cabeza. Con AI Agent Tool también se puede: pones varias expresiones $fromAI() dentro del texto del prompt, una por campo.
La regla práctica: empieza con task en texto, y pasa a campos tipados en cuanto veas en la traza que los encargos llegan incompletos de forma recurrente.
3. Contrato de salida
Qué devuelve el especialista, con qué campos. Este es el que más rinde y el que más se olvida.
Un contrato de salida útil para un especialista de atención tiene cuatro campos:
{
"status": "resolved | pending_info | out_of_scope | needs_human",
"summary": "Qué encontró y qué hizo, en dos o tres frases, para que el orquestador lo convierta en respuesta al cliente.",
"data": { "campos concretos del resultado, si los hay" },
"missing": ["qué datos faltan, si status es pending_info"]
}
Los cuatro valores de status no son decorativos — cada uno le dice al orquestador exactamente qué hacer después:
status | Qué significa | Qué hace el orquestador |
|---|---|---|
resolved | El caso quedó cerrado en este dominio | Compone la respuesta y cierra, o pasa al siguiente tema |
pending_info | Falta un dato que solo el cliente puede dar | Le pregunta al cliente lo que está en missing; no vuelve a delegar hasta tenerlo |
out_of_scope | El encargo no era de este dominio | Redelega al especialista correcto (una sola vez — lección 6) |
needs_human | Se requiere una persona | Dispara el camino de escalamiento, no reintenta |
Ese cuarto estado merece una nota. needs_human no reemplaza el mecanismo de revisión humana del Módulo 4 —donde una tool sensible queda literalmente detenida hasta que alguien aprueba—. Son dos cosas distintas y complementarias: la revisión humana es una barrera estructural sobre una acción específica; needs_human es un juicio del especialista sobre el caso completo. Un caso puede necesitar un humano sin que haya ninguna acción sensible de por medio: un cliente muy enojado, una situación legal, algo que el especialista no entiende.
Cómo se implementa la salida estructurada. El nodo AI Agent de n8n tiene una opción para exigir un formato de salida específico; al activarla aparece el puerto ai_outputParser, donde conectas un sub-nodo Structured Output Parser con un ejemplo de JSON o un esquema. El agente entonces produce esa forma en vez de texto libre.
Si por alguna razón esa opción no está disponible en el nodo que estás usando, la alternativa —menos garantizada pero funcional— es pedir el formato en el system prompt y ser explícito:
# Fragmento del System Message del especialista (alternativa sin parser)
Responde SIEMPRE con un objeto JSON válido, sin texto antes ni
después, con exactamente estos campos:
{
"status": uno de "resolved" | "pending_info" | "out_of_scope" | "needs_human",
"summary": string,
"data": object,
"missing": array de strings
}
La diferencia entre las dos vías es real: el parser estructurado valida la forma; el prompt solo la pide. Con el prompt vas a ver, ocasionalmente, un JSON con una explicación pegada antes. Usa el parser cuando puedas.
4. Contrato de autoridad
Qué puede hacer este agente por su cuenta y qué no. Es la aplicación directa de los límites de confianza del Módulo 4, ahora con una capa más:
Autoridad de billing_specialist:
Puede solo: lookup_charge, get_customer_profile (lectura)
Puede con registro: open_dispute (acción reversible)
No puede: emitir reembolsos, cambiar el método de pago, cancelar
suscripciones.
Requiere aprobación humana: ninguna de sus tools actuales.
Prohibido por prompt: prometer montos, plazos de resolución o
resultados de la disputa.
Dos cosas que conviene tener claras aquí. Primera: "no puede" y "prohibido por prompt" son cosas distintas y el contrato debe distinguirlas. No puede emitir reembolsos es estructural —esa tool no está conectada a este agente— y no depende de que el modelo obedezca. Prohibido prometer montos es textual, vive en el system prompt, y es fuerte pero no garantizado. Escribir cuál es cuál te obliga a notar si estás confiando en el prompt para algo que debería ser estructural.
Segunda: en un sistema multi-agente, la autoridad se hereda hacia abajo, nunca hacia arriba. El orquestador puede llamar al billing_specialist, pero eso no le da al orquestador la capacidad de abrir disputas por su cuenta — solo la de pedirle a alguien que lo haga, con ese alguien aplicando sus propias reglas. Esa es una propiedad valiosa del patrón: cada barrera se aplica en el lugar donde vive la tool, no en el lugar donde nace la intención.
5. Contrato de falla
Qué devuelve cuando no puede resolver. Es la parte que casi nadie escribe y la que más problemas evita.
Contrato de falla de billing_specialist:
- Si falta un dato obligatorio del encargo → status "pending_info",
con el campo faltante en "missing". No inventa el dato.
- Si el encargo no es de facturación → status "out_of_scope",
con "summary" indicando a qué dominio parece pertenecer.
No usa ninguna tool antes de reportarlo.
- Si lookup_charge falla técnicamente → status "needs_human",
summary describiendo el error. No reintenta más de una vez.
- Si el caso es de facturación pero excede su autoridad (el cliente
exige un reembolso) → status "needs_human".
- Nunca devuelve un "resolved" sin haber ejecutado al menos una
tool de su dominio.
Esa última línea es un pequeño seguro que vale mucho: es el equivalente entre agentes del error común del Módulo 4 —"el agente que dice haber actuado sin haber actuado"—. Un especialista que devuelve resolved sin haber llamado ninguna tool está respondiendo de memoria, y el orquestador no tiene forma de notarlo salvo que se lo prohíbas explícitamente y lo verifiques en la traza.
Ejemplo trabajado: la ficha completa y su implementación
Así se ve la ficha de rol de un especialista, completa, en el formato que conviene guardar junto al workflow:
┌─ FICHA DE ROL ────────────────────────────────────────────────┐
│ Agente: billing_specialist │
│ Tipo: AI Agent Tool │
│ Llamado por: triage_agent │
│ │
│ ROL Y SALIDA │
│ Ámbito: cargos, montos, facturación, disputas. │
│ Fuera: pedidos, envíos, devoluciones, recomendaciones. │
│ Termina cuando: el cargo quedó explicado, o hay una │
│ disputa abierta con número, o quedó registrado el dato │
│ que falta. │
│ │
│ ENTRADA (campo task, texto autocontenido) │
│ Obligatorio: customer_id, amount, approximate_date, │
│ description │
│ Opcional: order_id │
│ │
│ SALIDA (JSON estructurado) │
│ status: resolved | pending_info | out_of_scope | │
│ needs_human │
│ summary: 2-3 frases, sin saludos, para que el orquestador │
│ componga │
│ data: { dispute_id?, charge_found?, matched_order? } │
│ missing: [ ] cuando status = pending_info │
│ │
│ AUTORIDAD │
│ Lectura: lookup_charge, get_customer_profile │
│ Acción: open_dispute │
│ Sin acceso: reembolsos, cambio de método de pago │
│ Prohibido por prompt: prometer montos ni plazos │
│ │
│ FALLA │
│ Falta dato → pending_info (nunca lo inventa) │
│ Otro dominio → out_of_scope, sin usar tools │
│ Error técnico → needs_human, un solo reintento │
│ Excede autoridad → needs_human │
│ Nunca resolved sin haber usado una tool │
│ │
│ LÍMITES │
│ Max Iterations: 6 │
│ Sin memoria propia │
└───────────────────────────────────────────────────────────────┘
Esa ficha se traduce casi línea por línea a la configuración del nodo. El bloque SALIDA se convierte en el Structured Output Parser:
# Sub-nodo: Structured Output Parser
# (conectado al puerto ai_outputParser de billing_specialist,
# después de activar la opción de formato de salida específico)
# Ejemplo de JSON que define la forma esperada:
{
"status": "resolved",
"summary": "El cargo de $1,200 del 18/07 no corresponde a ninguna compra registrada del cliente C-9931. Se abrió la disputa D-8842 con revisión en 48 horas hábiles.",
"data": {
"dispute_id": "D-8842",
"charge_found": false,
"matched_order": null
},
"missing": []
}
Y los bloques FALLA y AUTORIDAD se convierten en las últimas líneas del System Message:
# Fragmento final del System Message de billing_specialist
Reglas de resultado:
- Si te falta customer_id, amount o una fecha aproximada, devuelve
status "pending_info" y lista en "missing" exactamente qué falta.
No inventes ningún dato.
- Si el encargo no es de facturación, devuelve status "out_of_scope"
e indica en "summary" a qué dominio parece pertenecer. No uses
ninguna tool en ese caso.
- Si el cliente exige un reembolso o una compensación, devuelve
status "needs_human". No prometas nada.
- Si una tool falla, reintenta una sola vez; si vuelve a fallar,
devuelve status "needs_human" con el error en "summary".
- Nunca devuelvas status "resolved" sin haber usado al menos una
de tus tools.
Del otro lado, el orquestador necesita saber leer eso. Su system prompt gana una sección:
# Fragmento del System Message de triage_agent
Cómo interpretar la respuesta de un especialista (campo status):
- "resolved": usa el summary para componer tu respuesta al cliente.
- "pending_info": pregúntale al cliente exactamente lo que aparece
en "missing", en tono natural. No vuelvas a delegar hasta que el
cliente responda.
- "out_of_scope": delega al especialista que indique el summary.
Si ya redelegaste una vez por este mismo tema, no lo intentes de
nuevo: dile al cliente que vas a escalar el caso.
- "needs_human": no reintentes ni delegues a otro. Informa al
cliente que un miembro del equipo va a dar seguimiento y cierra
el turno.
Qué esperar. Un cliente escribe: "me cobraron algo raro el mes pasado". El orquestador delega a billing_specialist con un task que dice, honestamente, que el cliente reporta un cargo desconocido pero no dio ni el monto ni la fecha. El especialista, siguiendo su contrato de falla, no llama ninguna tool —no tiene con qué buscar— y devuelve:
{
"status": "pending_info",
"summary": "El cliente reporta un cargo desconocido pero no indicó el monto ni la fecha aproximada; sin esos datos no es posible buscar el cargo.",
"data": {},
"missing": ["amount", "approximate_date"]
}
El orquestador lee pending_info, mira missing, y le responde al cliente: "Claro, te ayudo con eso. ¿Recuerdas más o menos de cuánto fue el cargo y en qué fecha apareció?". No delegó otra vez, no inventó un monto, no dijo que estaba revisando. Y sobre todo: esa decisión no salió de que el modelo interpretara bien un párrafo — salió de leer un campo con un valor de una lista cerrada de cuatro.
Compara eso con lo que habría pasado sin contrato. El especialista habría devuelto algo como "No encontré ningún cargo con la información disponible. Sería útil conocer el monto exacto." El orquestador lo habría interpretado, probablemente bien. O habría concluido que no hay ningún cargo raro y se lo habría dicho al cliente, que es una respuesta plausible para ese texto y completamente equivocada.
Handoffs: los tres tipos
"Handoff" es el momento en que el trabajo pasa de un agente a otro. Hay tres formas distintas y conviene no confundirlas, porque n8n soporta una de forma nativa y las otras dos se construyen encima de esa.
Tipo 1 — Delegación y retorno
El orquestador llama al especialista, el especialista trabaja, devuelve un resultado, y el control vuelve al orquestador. Es el único que ocurre de forma nativa cuando conectas un AI Agent Tool, porque es lo que hace cualquier tool: se llama, devuelve, y quien llamó sigue.
triage_agent ──llama──► billing_specialist
◄─resultado──
(sigue razonando)
Cuándo aplica. Siempre, por defecto. Es el 90% de los handoffs de un sistema de atención.
Tipo 2 — Redirección
El especialista determina que el caso no es suyo y lo reporta; el orquestador redelega al que corresponde. No es un handoff directo entre especialistas: pasa por el orquestador.
triage_agent ──llama──► order_specialist
◄─ out_of_scope: "esto es de facturación" ──
triage_agent ──llama──► billing_specialist
◄─resultado──
Cómo se implementa. Con el campo status: "out_of_scope" del contrato de salida, más la instrucción en el prompt del orquestador de qué hacer con él. No hace falta ningún nodo extra.
Por qué pasa por el orquestador y no directo. Porque el camino directo —que order_specialist tenga a billing_specialist como tool— crea la posibilidad de ciclos: A llama a B, B decide que era de A, A llama a B otra vez. La lección 6 se ocupa de eso. La regla de arranque de la lección 3 —los trabajadores no delegan en otros trabajadores— existe precisamente para hacer esta redirección segura por construcción: si toda redirección pasa por el orquestador, el orquestador puede contar cuántas van y cortar.
Tipo 3 — Transferencia de control
El especialista toma el control de la conversación y se queda con ella durante varios turnos, sin volver al orquestador en cada mensaje. Es un patrón que existe en algunos frameworks de agentes escritos en código, donde el "handoff" cambia quién atiende de forma persistente.
En n8n, esto no ocurre de forma nativa, y conviene decirlo con claridad en vez de inventar sintaxis. Un AI Agent Tool no puede quedarse con la conversación: es una tool, se llama y devuelve. Si de verdad necesitas ese comportamiento —un especialista que guía un proceso de siete pasos durante varios turnos— tienes dos caminos honestos:
Camino A: emularlo con estado en la memoria del orquestador. El orquestador guarda un campo del tipo "modo actual de la conversación" y su system prompt dice: mientras ese modo esté activo, delega todos los mensajes a ese especialista sin volver a evaluar. El especialista devuelve, junto con su resultado, si el modo sigue activo o terminó. Funciona, es visible en la traza, y el orquestador nunca pierde la capacidad de intervenir —lo cual normalmente es bueno.
Camino B: preguntarte si de verdad lo necesitas. En la enorme mayoría de los sistemas de atención, la transferencia de control no aporta nada frente a delegación y retorno: el orquestador vuelve a delegar al mismo especialista en el turno siguiente y el efecto es el mismo, con la ventaja de que puede cambiar de opinión si el cliente cambia de tema a mitad de camino. La transferencia de control se paga con rigidez.
La tabla de handoffs
| Tipo | ¿Nativo en n8n? | Cómo se implementa | Cuándo usarlo |
|---|---|---|---|
| Delegación y retorno | Sí | Conectar el especialista al puerto ai_tool | Por defecto, siempre |
| Redirección | Sí, sobre el anterior | Campo status: "out_of_scope" + política en el prompt del orquestador | Cuando los dominios tienen fronteras difusas |
| Transferencia de control | No | Estado en la memoria del orquestador (camino A) | Procesos guiados largos; verifica primero que lo necesitas |
Quién es dueño del estado durante un handoff
Una última pieza, corta pero decisiva. Cuando el trabajo pasa de un agente a otro, ¿qué pasa con lo que se sabe hasta ahora?
La regla es la de la lección 3, y ahora tiene nombre: el orquestador es la única fuente de verdad del estado de la conversación. El especialista no acumula estado entre llamadas. Todo lo que sabe, lo sabe porque venía en el encargo.
Las consecuencias prácticas son tres, y las tres son buenas:
- Un especialista se puede llamar dos veces con dos encargos distintos sin que se confundan. No hay contaminación entre llamadas.
- Se puede probar aislado. Le mandas un encargo, ves qué devuelve. Reproducible.
- Cuando algo sale mal, hay un solo lugar donde mirar el estado. No tienes que reconstruir qué creía cada agente.
Y el costo es uno solo: el orquestador tiene que hacer el trabajo de incluir en cada encargo lo que haga falta. Ese trabajo se paga en tokens —el encargo es más largo— y es exactamente el tipo de gasto que la lección 7 te va a enseñar a medir y a acotar.
Errores comunes
Escribir el contrato de salida sin un desenlace de fracaso (conceptual). Qué pasa: alguien define status con dos valores, resolved y error. El especialista, ante un caso donde le falta un dato, tiene que elegir entre esos dos: error suena demasiado grave para "falta el monto", así que devuelve resolved con un summary que dice que no encontró nada. El orquestador lee resolved y le informa al cliente que todo está bien. Por qué pasa: al diseñar se piensa en el camino feliz y en la falla técnica, y se olvidan los estados intermedios, que en atención al cliente son la mayoría. Cómo detectarlo: revisa qué valores de status aparecieron realmente en cien ejecuciones; si el 100% son resolved, tu enumeración es demasiado pobre para describir lo que pasa. Cómo corregirlo: los cuatro estados de esta lección —resolved, pending_info, out_of_scope, needs_human— cubren bien un sistema de atención; agrega otros si tu dominio los pide, pero nunca dejes menos de tres.
Dejar que el especialista devuelva prosa "porque el orquestador la entiende" (conceptual). Qué pasa: funciona en las pruebas, funciona en la demo, y falla en producción en casos donde la prosa es ambigua. Lo peor es que falla de forma silenciosa y no reproducible: el mismo texto puede interpretarse distinto en dos corridas. Por qué pasa: el modelo del orquestador es genuinamente bueno interpretando, y en las veinte pruebas que hiciste acertó veinte veces. Cómo detectarlo: toma las salidas de texto libre de tu especialista y pregúntate, para cada una, si un lector cuidadoso podría interpretarla de dos formas distintas; las que sí, son bombas de tiempo. Cómo corregirlo: salida estructurada con un campo status de valores cerrados; el summary en prosa sigue existiendo, pero solo para redactar la respuesta al cliente, nunca para decidir el flujo.
Confundir needs_human con el mecanismo de revisión humana del Módulo 4 (conceptual). Qué pasa: alguien implementa needs_human como campo de salida y da por resuelto el problema de las acciones sensibles, sin poner ninguna tool detrás de una revisión real. El día que el modelo decida llamar a una tool de reembolso, nada la detiene — el campo needs_human solo existe si el modelo lo produce. Por qué pasa: los dos mecanismos se llaman parecido y persiguen fines relacionados. Cómo detectarlo: pregúntate qué pasa si el modelo se equivoca; si la respuesta es "devuelve otro status y la acción se ejecuta igual", tu barrera es textual, no estructural. Cómo corregirlo: las dos cosas conviven — la revisión humana del Módulo 4 protege acciones específicas y no depende del criterio del modelo; needs_human es un juicio sobre el caso completo que sirve para enrutar, no para bloquear.
Poner el contrato en la cabeza y no en el archivo (práctico). Qué pasa: el contrato existe, funciona, y vive repartido entre el system prompt del especialista, la description del $fromAI() y el prompt del orquestador. Tres meses después alguien cambia una de esas tres cosas sin saber que las otras dos dependían de ella, y el sistema empieza a fallar de una forma que nadie relaciona con ese cambio. Por qué pasa: el contrato no tiene un lugar propio en n8n; está implícito en tres campos distintos. Cómo detectarlo: pregúntale a alguien del equipo cuáles son los cuatro valores posibles de status de un especialista; si tiene que abrir tres nodos para contestar, el contrato no está documentado. Cómo corregirlo: guarda la ficha de rol —la del ejemplo trabajado— junto al workflow, en una nota del canvas de n8n o en el repositorio donde versionas los flujos, y trátala como la fuente de verdad de la que salen los tres campos.
Pedirle al especialista campos que no puede llenar (práctico). Qué pasa: el contrato de salida incluye un campo estimated_resolution_days, y el especialista lo llena siempre, porque un modelo al que le pides un número produce un número. Ese número es inventado. Por qué pasa: al diseñar el contrato es fácil incluir campos que serían útiles sin verificar si alguna tool los provee. Cómo detectarlo: para cada campo de tu contrato de salida, señala de qué tool sale su valor; el que no salga de ninguna, sale del modelo, y probablemente sea una alucinación con formato. Cómo corregirlo: cada campo del contrato de salida debe poder trazarse a un resultado de tool o a un juicio explícito que el prompt autoriza; si no, quítalo o márcalo como opcional y anulable.
Ejercicios
Ejercicio 1 — Escribe la ficha de rol. TuTienda agrega un shipping_specialist que maneja todo lo relacionado con el envío en curso: rastrear el paquete con la transportadora, gestionar cambios de dirección antes del despacho y reportar paquetes perdidos. Tiene tres tools: track_shipment (lectura, consulta la API de la transportadora), update_delivery_address (acción, solo funciona si el paquete no salió del centro de distribución) y report_lost_package (acción, abre una investigación con la transportadora). Escribe su ficha de rol completa con las cinco cláusulas.
Ver solución
┌─ FICHA DE ROL ────────────────────────────────────────────────┐
│ Agente: shipping_specialist Tipo: AI Agent Tool │
│ │
│ ROL Y SALIDA │
│ Ámbito: rastreo de envíos en curso, cambio de dirección │
│ antes del despacho, paquetes perdidos o no entregados. │
│ Fuera: devoluciones, garantías, cobros, recomendaciones. │
│ Termina cuando: el cliente sabe dónde está su paquete, o │
│ la dirección quedó actualizada, o quedó abierta una │
│ investigación por paquete perdido, o quedó registrado │
│ qué dato falta. │
│ │
│ ENTRADA │
│ Obligatorio: customer_id, order_id o tracking_number, │
│ intent (rastrear | cambiar_dirección | │
│ reportar_perdido) │
│ Opcional: new_address (obligatorio si intent es │
│ cambiar_dirección) │
│ │
│ SALIDA │
│ status: resolved | pending_info | out_of_scope | │
│ needs_human │
│ summary: 2-3 frases, sin saludos │
│ data: { shipment_status?, eta?, new_address_confirmed?, │
│ investigation_id? } │
│ missing: [ ] │
│ │
│ AUTORIDAD │
│ Lectura: track_shipment │
│ Acción: update_delivery_address (solo antes del │
│ despacho), report_lost_package │
│ Sin acceso: reembolsos, cancelación de pedido, reenvío │
│ Prohibido por prompt: prometer una fecha exacta de entrega │
│ (solo puede repetir la estimación que dé la │
│ transportadora, citándola como estimación) │
│ │
│ FALLA │
│ Falta order_id / tracking_number → pending_info │
│ Intent = cambiar_dirección pero el paquete ya salió → │
│ resolved con summary explicando que no se pudo, o │
│ needs_human si el cliente insiste │
│ Falta new_address cuando intent lo exige → pending_info │
│ API de la transportadora no responde tras un reintento → │
│ needs_human │
│ Encargo de otro dominio → out_of_scope, sin usar tools │
│ Nunca resolved sin haber usado al menos una tool │
│ │
│ LÍMITES │
│ Max Iterations: 5 Sin memoria propia │
└───────────────────────────────────────────────────────────────┘
Dos decisiones que vale la pena notar. Primera: update_delivery_address "solo antes del despacho" no es una regla que el prompt deba hacer cumplir por su cuenta — si la tool misma rechaza el cambio cuando el paquete ya salió, la barrera es estructural y mucho mejor. El prompt describe la regla; la tool la impone.
Segunda: el caso "el paquete ya salió y no se puede cambiar la dirección" es resolved, no un fracaso. El caso quedó cerrado: la respuesta es que no se puede. Marcar como fracaso todo lo que no le gusta al cliente es un error común que hace que el estado resolved pierda significado.
Por qué funciona: la ficha te obliga a decidir cosas que si no las decides ahora las va a decidir el modelo en producción, una por una y de forma distinta cada vez.
Ejercicio 2 — Interpreta el status. El orquestador recibe estas cuatro respuestas de especialistas. Para cada una, di qué debe hacer el orquestador a continuación y qué NO debe hacer:
(a) {"status": "pending_info", "missing": ["order_id"], "summary": "El cliente menciona un pedido pero no dio el número."}
(b) {"status": "out_of_scope", "summary": "El cliente pregunta por un cargo en su tarjeta, no por un envío. Corresponde a facturación."}
(c) {"status": "needs_human", "summary": "El cliente amenaza con acciones legales por el retraso."}
(d) {"status": "resolved", "summary": "El paquete está en tránsito, entrega estimada el 24/07.", "data": {"eta": "2026-07-24"}}
Ver solución
(a) Debe pedirle al cliente el número de pedido, en tono natural: "¿Me compartes el número de pedido? Suele empezar con #." No debe volver a delegar al mismo especialista con el mismo encargo —el resultado sería idéntico— ni intentar adivinar el pedido consultando otra cosa.
(b) Debe delegar al billing_specialist con un encargo reformulado para ese dominio. No debe reenviarle el mismo task tal cual —estaba redactado para envíos— ni volver a llamar al especialista que reportó el out_of_scope. Y debe contar esta redelegación: si ya hubo una por este mismo tema, la política es cerrar y escalar (lección 6).
(c) Debe informarle al cliente que el caso pasa a una persona del equipo, y disparar el camino de escalamiento que tenga el sistema. No debe reintentar, no debe delegar a otro especialista buscando una respuesta mejor, y no debe intentar resolver el fondo del reclamo por su cuenta.
(d) Debe componer la respuesta al cliente con el summary en su propia voz, y si el mensaje original tenía otro tema pendiente, delegar ese. No debe citar el JSON, no debe inventar precisión que el data no tiene ("llega el 24 a las 3 p. m."), y no debe prometer la fecha como certeza si el especialista la marcó como estimación.
Por qué funciona: en los cuatro casos la decisión del orquestador salió de leer un campo, no de interpretar prosa. Ese es todo el valor del contrato de salida — y fíjate que en tres de los cuatro casos, lo que NO debe hacer es reintentar, que es exactamente el comportamiento que produce los bucles de la lección 6.
Ejercicio 3 — Encuentra los campos alucinados. Un equipo propone este contrato de salida para un warranty_specialist que tiene dos tools: lookup_purchase (devuelve fecha de compra, producto y precio) y create_repair_request (crea una solicitud de reparación y devuelve su número). Señala qué campos no se pueden llenar de forma confiable y por qué.
{
"status": "resolved",
"summary": "...",
"data": {
"warranty_valid": true,
"days_remaining": 143,
"repair_request_id": "R-2291",
"estimated_repair_cost": 0,
"estimated_repair_days": 7,
"customer_satisfaction_risk": "low"
}
}
Ver solución
Trazables a una tool, y por lo tanto legítimos:
warranty_validydays_remaining— salen de la fecha de compra que devuelvelookup_purchasemás la duración de la garantía, que es una regla de negocio conocida. Legítimos, aunque el cálculo de fechas convendría hacerlo en un sub-workflow determinista y no dejárselo al modelo (Módulo 4, lección 6): un modelo restando fechas es un riesgo innecesario.repair_request_id— sale directo decreate_repair_request. Legítimo.
Alucinados o no confiables:
estimated_repair_cost— ninguna de las dos tools devuelve un costo. Si la garantía cubre, el valor 0 podría ser una regla de negocio válida, pero entonces hay que escribirla explícitamente en el prompt y limitarla a ese caso; si no cubre, el modelo va a inventar una cifra.estimated_repair_days— ninguna tool lo provee. El modelo va a producir un número plausible, típicamente 7, 10 o 15, y el orquestador se lo va a decir al cliente como si fuera un dato.customer_satisfaction_risk— es un juicio subjetivo sin ninguna fuente. Podría ser legítimo si el prompt define explícitamente el criterio ("alto si el cliente menciona insatisfacción previa o amenaza con irse") y si el orquestador lo usa solo para enrutar, nunca para decirle algo al cliente. Tal como está, es un campo que suena a dato y es una opinión.
La corrección: quitar estimated_repair_cost y estimated_repair_days, o conseguir una tool que los provea de verdad; y si customer_satisfaction_risk se queda, definir su criterio por escrito y marcarlo como interno.
Por qué funciona: la prueba de "¿de qué tool sale este valor?" es rápida y detecta el problema antes de que un cliente reciba una fecha de reparación inventada. Un modelo nunca deja un campo vacío si le pides que lo llene.
Resumen y siguiente paso
Ya sabes diseñar el equipo, no solo conectarlo. Un contrato de agente tiene cinco cláusulas: rol y criterio de salida (con al menos un desenlace de fracaso), contrato de entrada (los campos mínimos, en texto autocontenido o en campos tipados), contrato de salida (status de valores cerrados, summary para componer, data para lo concreto, missing para lo que falta), contrato de autoridad (qué es estructural y qué es textual), y contrato de falla (qué devuelve cuando no puede, incluida la prohibición de devolver resolved sin haber usado ninguna tool). El status es la pieza que hace que el orquestador decida leyendo un campo en vez de interpretando prosa. Y de los tres tipos de handoff, n8n soporta de forma nativa la delegación con retorno; la redirección se construye sobre ella con out_of_scope; y la transferencia de control no existe de forma nativa y casi nunca hace falta.
Antes de avanzar deberías poder: escribir una ficha de rol de cinco cláusulas para un especialista nuevo; enumerar los cuatro estados de salida y decir qué debe hacer el orquestador con cada uno; distinguir una restricción estructural de una textual en el contrato de autoridad; y detectar un campo del contrato de salida que ninguna tool puede llenar.
Lo que queda pendiente es el peligro que este contrato hace posible. Ahora que un especialista puede decir out_of_scope y el orquestador puede redelegar, existe un camino por el cual el sistema se pasa el mismo caso de un agente a otro sin llegar nunca a una respuesta. Y ahora que cada especialista tiene su propio bucle agéntico dentro del bucle del orquestador, existe la posibilidad de que uno de ellos itere hasta agotar su presupuesto sin que nadie se entere. Las condiciones de parada de un sistema multi-agente son el tema completo de la lección 6.
Recursos
- Structured Output Parser — n8n Docs — el sub-nodo con el que se implementa el contrato de salida; cómo definir la forma con un ejemplo de JSON o un esquema.
- AI Agent Tool node — n8n Docs — los parámetros donde viven las cinco cláusulas:
Description, el prompt del encargo, el System Message y las opciones. - Execute Sub-workflow Trigger — n8n Docs —
Define Using Fields Below, la forma más explícita de declarar un contrato de entrada con campos y tipos. - Human-in-the-loop for tools — n8n Docs — la barrera estructural del Módulo 4, que convive con el estado
needs_humansin reemplazarlo. - Use AI for parameters ($fromAI) — n8n Docs — la referencia para escribir contratos de entrada con varios campos tipados en lugar de un solo
taskde texto.