Usar el mismo workflow como Webhook y Sub-workflow: ¿cómo deberían devolverse los resultados?

Describe el problema/error/pregunta

Estoy intentando tener un flujo de trabajo único que pueda ser llamado ya sea por un Webhook Trigger (para solicitudes HTTP externas) o por un When Executed by Another Workflow (para ser usado por otros flujos dentro de n8n).

El análisis de la entrada funciona bien. Por ejemplo, puedo normalizar mis entradas dentro de un nodo Edit/Set con expresiones como $json.query.parameter ?? $json.parameter y determinar cómo se invocó el flujo de trabajo usando !!$json.query.

El problema es devolver el resultado. Me pregunto si lo que estoy intentando no es compatible, a menos que los webhooks también respondan cuando finaliza el último nodo.

¿Cuál es el mensaje de error (si hay alguno)?

Cuando se llama desde un Webhook Trigger, necesito usar Respond to Webhook.
Cuando se llama como When Executed by Another Workflow, el flujo de trabajo debería simplemente finalizar y devolver la salida del último nodo. Sin embargo, la presencia de un nodo Respond to Webhook lanza el error No Webhook node found in the workflow.

Si añado un nodo IF antes del retorno para determinar si devolver el último resultado a través de Respond to Webhook, entonces el nodo Execute Workflow recibe dos ramas de salida (una vacía y otra con los datos reales), lo que causa problemas porque el flujo de trabajo principal ahora recibe dos ramas en lugar de un único resultado.

Por favor comparte tu flujo de trabajo

Comparte la salida devuelta por el último nodo

Salida
1 Rama | 2 Rama (1 elemento)

Información sobre tu configuración de n8n

  • Versión de n8n: 2.27.4
  • Ejecutando n8n vía (Docker, npm, n8n cloud, aplicación de escritorio): n8n Cloud

@ThomasLu_EarthDaily sí, básicamente lo encontraste. Respond to Webhook necesita un webhook activo en la ejecución, por lo que falla en la ruta del sub-flujo de trabajo, y crear ramificaciones alrededor de él te da el problema de dos salidas. configura la opción Respond del nodo Webhook a “When Last Node Finishes” y elimina el nodo Respond to Webhook. entonces el webhook devuelve la salida del último nodo por sí solo, exactamente como el retorno del sub-flujo de trabajo, así ambos puntos de entrada se comportan igual con una salida limpia. el único compromiso es que pierdes el código de estado personalizado/encabezados que te da Respond to Webhook, si no necesitas esos, este es el camino limpio.

Hola Thomas,

Como Ingeniero de Automatización de IA que construye flujos modulares y multi-tenant en n8n a diario, me encuentro con este desafío arquitectónico constantemente. Construir sub-flujos reutilizables que también funcionen como webhooks independientes es un ahorro de tiempo enorme, pero has identificado exactamente el cuello de botella estructural que ocurre al mezclar contextos de ejecución.

La sugerencia de @achamm es absolutamente el enfoque nativo más limpio si tus requisitos de carga útil son simples: cambiar el modo de respuesta del Webhook Trigger a When Last Node Finishes elimina completamente la necesidad de la rama condicional.

Sin embargo, si estás construyendo esto como una API de grado de producción para clientes y necesitas estrictamente códigos de estado HTTP personalizados o encabezados de respuesta de la ruta de ejecución del webhook, puedes evitar el problema de “dos ramas de salida” en el flujo principal con un rediseño estructural ligero.

Aquí hay las dos mejores formas de manejar esto según tus requisitos:

Método 1: El “Payload Wrap” de Code Node (Mejor para Respuestas HTTP Personalizadas)

Si debes mantener el nodo Respond to Webhook para pasar códigos de estado o encabezados específicos, la razón por la que tu flujo principal está recibiendo una rama vacía es que la transmisión de datos de salida final se está dividiendo. Puedes evitar esto ejecutando una sola línea de Javascript justo antes de que termine tu flujo.

  1. Mantén tu nodo IF que verifica cómo fue invocado el flujo.

  2. En la ruta true (Webhook), envíalo directamente a tu nodo Respond to Webhook.

  3. En la ruta false (Sub-flujo), envíalo a un nodo Code configurado en Run Once for All Items.

  4. Dentro del nodo Code, devuelve los datos estructurados explícitamente:

    JavaScript

    return $input.all();
    
    
  5. En el nodo Execute Workflow de tu flujo principal, asegúrate de apuntar a la salida de este nodo Code específico usando expresiones en lugar de confiar en la salida de nodo predeterminada, o simplemente deja que el sub-flujo termine naturalmente en esa rama única activa.

Método 2: Separa los Triggers de Entrada de la Lógica Central (Mejor Práctica)

Para configuraciones de automatización de gran escala o empresariales, la arquitectura más estable es desacoplar completamente el punto de entrada de la lógica funcional. En lugar de empacar ambos triggers en un lienzo, divídelos en dos micro-flujos y un motor maestro:

  • Flujo A (The Webhook Gateway): Contiene solo el nodo Webhook Trigger $\rightarrow$ Execute Workflow (Motor) $\rightarrow$ Respond to Webhook.

  • Flujo B (The Sub-Workflow Gateway): Contiene solo el trigger “When Executed by Another Workflow” $\rightarrow$ Execute Workflow (Motor).

  • Flujo C (The Core Engine): Contiene los pasos de procesamiento reales, llamadas a API y transformaciones de datos, terminando con una carga útil de datos limpia.

**Por qué vale la pena:

  • Elimina completamente las comprobaciones de lógica condicional dentro de tu flujo central.

  • Si alguna vez necesitas cambiar tus códigos de estado HTTP, solo tocas el flujo Gateway ligero sin riesgo de romper tu motor de automatización central.

  • Depurar ejecuciones en el historial de ejecuciones de n8n se vuelve drásticamente más fácil porque el tráfico de webhook y el tráfico interno de sub-flujos están explícitamente separados.

Si no necesitas encabezados de respuesta sofisticados, ve con la solución de @achamm y cambia a When Last Node Finishes. Si los necesitas, prueba la arquitectura de gateway desacoplada—¡te ahorrarán un montón de dolores de cabeza de mantenimiento en el futuro!