> ## Documentation Index
> Fetch the complete documentation index at: https://docs.lerian.studio/llms.txt
> Use this file to discover all available pages before exploring further.

# Guía de diseño de workflows

> Diseña workflows de Flowker: tipos de nodo, aristas, patrones reales, transiciones de estado y mejores prácticas para una orquestación confiable.

Esta guía recorre los tipos de nodo, las aristas, los patrones reales, las transiciones de estado, los límites técnicos y las mejores prácticas.

## Tipos de nodo

***

Cada workflow se compone de nodos. Cada nodo tiene un `type` que define cómo lo procesa Flowker en tiempo de ejecución.

### trigger

Un nodo disparador es un punto de entrada de ejecución. Los workflows en borrador pueden estar incompletos, pero la activación requiere al menos un nodo disparador. Cuando una ejecución empieza por un disparador, el motor entra en ese nodo y enruta desde allí.

Los ejemplos de esta página muestran solo la topología de nodos. Un nodo disparador real también lleva un `triggerType` y la configuración de ese disparador en su `data`. Consulta [Configurar un disparador de webhook](/es/products/flowker/configuring-a-webhook-trigger) o [Ejecutar un workflow según una programación](/es/products/flowker/running-a-workflow-on-a-schedule).

```json theme={null}
{
  "id": "node-trigger",
  "type": "trigger",
  "name": "Payment Received"
}
```

### executor

Llama a un servicio externo a través de una configuración de proveedor. Este nodo es el punto de integración principal para motores de fraude, proveedores de pago, servicios de notificación y otros sistemas externos.

Los ejemplos de esta página muestran solo la topología de nodos. Un nodo ejecutor real también lleva un `providerConfigId` en su `data`, más un `executorId` que nombra al ejecutor del catálogo que invoca. Un nodo que llama a una operación de un documento OpenAPI cargado omite el `executorId` y lleva `operation_path` y `operation_method` en su lugar. Consulta la [Guía de integración](/es/products/flowker/integration-guide).

```json theme={null}
{
  "id": "node-fraud-check",
  "type": "executor",
  "name": "Check Fraud Score"
}
```

### conditional

Evalúa una condición contra el contexto de ejecución y enruta a distintas ramas según el resultado. Usa nodos condicionales para implementar lógica de ramificación, por ejemplo, enrutar a una vía de aprobación cuando el riesgo es alto, o continuar directo cuando es bajo.

La condición vive en el `data.condition` del nodo. Una expresión de texto libre se evalúa como booleano y produce el handle de salida `true` o `false`. Cada arista saliente declara qué handle sigue mediante `sourceHandle`. Los nodos condicionales creados en la Console usan una condición estructurada por casos, donde cada caso enruta a su propio handle de salida. Consulta el [Editor de canvas](/es/products/flowker/console/canvas-editor).

```json theme={null}
{
  "id": "node-risk-decision",
  "type": "conditional",
  "name": "Evaluate Risk Score",
  "data": { "condition": "node-fraud-check.riskScore < 70" }
}
```

### action

Representa una operación interna síncrona `set_output`. Puede escribir un valor de salida interpolado y, de forma opcional, sobrescribir el estado de la respuesta HTTP síncrona. No provee una pausa integrada, una emisión genérica de eventos ni una operación genérica de cambio de estado.

```json theme={null}
{
  "id": "node-record-approval",
  "type": "action",
  "name": "Record Approval Decision"
}
```

## Aristas

***

Las aristas conectan nodos y definen las vías de ejecución. Cada arista incluye los siguientes campos:

| Campo          | Descripción                                                                                                                                                                                                      |
| -------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `id`           | Identificador único de la arista.                                                                                                                                                                                |
| `source`       | ID del nodo de origen.                                                                                                                                                                                           |
| `target`       | ID del nodo de destino.                                                                                                                                                                                          |
| `sourceHandle` | Handle de salida del nodo de origen que sigue esta arista. Obligatorio para enrutar fuera de un nodo condicional: debe coincidir con el resultado de la rama (`true` o `false` en una condición de texto libre). |
| `condition`    | Campo heredado de texto libre que se mantiene por compatibilidad con versiones anteriores. No se evalúa para el enrutamiento — déjalo vacío en los workflows nuevos.                                             |
| `label`        | Etiqueta legible que se usa para visualización y depuración.                                                                                                                                                     |

### Ejemplo de arista

```json theme={null}
{
  "id": "edge-approved",
  "source": "node-risk-decision",
  "target": "node-process-payment",
  "sourceHandle": "true",
  "label": "Approved"
}
```

El enrutamiento depende del tipo del nodo de origen. Un nodo condicional evalúa su `data.condition` y sigue la única arista saliente cuyo `sourceHandle` coincide con el resultado de la rama. Si ninguna arista coincide, esa rama termina. Todos los demás tipos de nodo siguen todas sus aristas salientes cuando se completan con éxito.

## Transiciones de estado

***

Los workflows siguen un ciclo de vida bien definido.

<Frame>
  <img src="https://mintcdn.com/lerian-49cb71fc/RAVxFNT8MNA4GWjO/images/es/d2/flowker-workflow-status-transitions.svg?fit=max&auto=format&n=RAVxFNT8MNA4GWjO&q=85&s=3598cbd440b5b4c93467cf32094efb1f" alt="Diagrama de transición de estados del workflow que muestra tres estados: draft, active e inactive. Una flecha etiquetada 'activate' apunta de draft a active. Una flecha etiquetada 'deactivate' apunta de active a inactive. Una flecha etiquetada 'draft' apunta de inactive de vuelta a draft." width="817" height="327" data-path="images/es/d2/flowker-workflow-status-transitions.svg" />
</Frame>

* **draft**: el estado inicial. Puedes agregar nodos, editar aristas y cambiar la configuración solo en el estado `draft`.
* **active**: un workflow que activaste. Flowker puede ejecutarlo. No acepta modificaciones mientras está activo.
* **inactive**: un workflow que desactivaste. Flowker ya no puede ejecutarlo, pero puedes devolverlo a `draft` para editarlo.

### Reglas

* Solo puedes activar un workflow en `draft` (transición: `draft → active`).
* Solo puedes desactivar un workflow en `active` (transición: `active → inactive`).
* Solo puedes devolver a borrador un workflow en `inactive` (transición: `inactive → draft`).
* Intentar una transición inválida devuelve el error `FLK-0102`.
* Intentar modificar un workflow que no está en `draft` devuelve el error `FLK-0103`.

### Devolver a borrador un workflow inactivo

Si desactivaste un workflow y quieres editarlo de nuevo, devuélvelo a `draft` llamando a [`POST /v1/workflows/{id}/draft`](/es/reference/products/flowker/move-workflow-to-draft). Así el workflow queda editable sin necesidad de clonarlo.

Usa esto cuando desactivaste un workflow por error, o cuando quieres iterar sobre un workflow existente en lugar de crear una copia.

<Note>
  Solo puedes pasar a borrador los workflows inactivos. Si necesitas modificar un workflow activo sin sacarlo de servicio, usa el enfoque de clonación que se describe abajo.
</Note>

### Iterar de forma segura con la clonación

Para modificar un workflow activo, clónalo primero. La clonación crea un nuevo `draft` desde cualquier estado y copia todos los nodos y aristas. Luego puedes actualizarlo, probarlo y activarlo sin afectar la versión actual.

Usa este enfoque para el versionado en producción.

## Límites técnicos

***

| Límite                                     | Valor | Código de error |
| ------------------------------------------ | ----- | --------------- |
| Máximo de nodos por workflow               | 100   | `FLK-0113`      |
| Máximo de aristas por workflow             | 200   | `FLK-0114`      |
| Payload máximo de entrada de una ejecución | 1 MB  | `FLK-0506`      |

Los workflows con más de \~50 nodos suelen indicar que se recomienda dividir el flujo en workflows más pequeños y componibles.

## Patrones comunes

***

### Secuencial

El patrón más simple. Los nodos se ejecutan en una secuencia lineal. Usa esto cuando cada paso depende del anterior y no necesita ramificación.

<Frame>
  <img src="https://mintcdn.com/lerian-49cb71fc/RAVxFNT8MNA4GWjO/images/es/d2/flowker-pattern-sequential.svg?fit=max&auto=format&n=RAVxFNT8MNA4GWjO&q=85&s=e9513225c46c45740192faa63a5a50dd" alt="Patrón de workflow secuencial: un nodo disparador se conecta a un primer nodo ejecutor, que se conecta a un segundo nodo ejecutor, que se conecta a un tercer nodo ejecutor. Todas las conexiones son flechas dirigidas simples que forman una línea recta." width="957" height="268" data-path="images/es/d2/flowker-pattern-sequential.svg" />
</Frame>

**Ejemplo: orquestación de pagos**

```json theme={null}
{
  "nodes": [
    { "id": "n1", "type": "trigger",  "name": "Payment Initiated" },
    { "id": "n2", "type": "executor", "name": "Validate Payment Data" },
    { "id": "n3", "type": "executor", "name": "Route to Provider" },
    { "id": "n4", "type": "executor", "name": "Send Confirmation Notification" }
  ],
  "edges": [
    { "id": "e1", "source": "n1", "target": "n2", "label": "Start" },
    { "id": "e2", "source": "n2", "target": "n3", "label": "Valid" },
    { "id": "e3", "source": "n3", "target": "n4", "label": "Routed" }
  ]
}
```

### Ramificación condicional

Un nodo `conditional` evalúa su condición y enruta la ejecución en consecuencia. El resultado de la rama selecciona la arista saliente que sigue el nodo, emparejada por `sourceHandle`.

<Frame>
  <img src="https://mintcdn.com/lerian-49cb71fc/RAVxFNT8MNA4GWjO/images/es/d2/flowker-pattern-conditional.svg?fit=max&auto=format&n=RAVxFNT8MNA4GWjO&q=85&s=dac1a2bfa74753708427d7e1105e83d2" alt="Patrón de workflow con ramificación condicional: un nodo disparador se conecta a un nodo ejecutor, que se conecta a un nodo condicional. El nodo condicional tiene dos flechas salientes: una etiquetada 'Path A' que apunta a un primer nodo ejecutor, y otra etiquetada 'Path B' que apunta a un segundo nodo ejecutor." width="999" height="394" data-path="images/es/d2/flowker-pattern-conditional.svg" />
</Frame>

**Ejemplo: verificación antifraude**

```json theme={null}
{
  "nodes": [
    { "id": "n1", "type": "trigger",     "name": "Transaction Received" },
    { "id": "n2", "type": "executor",    "name": "Get Fraud Score" },
    {
      "id": "n3",
      "type": "conditional",
      "name": "Evaluate Score",
      "data": { "condition": "n2.fraudScore < 70" }
    },
    { "id": "n4", "type": "executor",    "name": "Approve Transaction" },
    { "id": "n5", "type": "executor",    "name": "Reject Transaction" }
  ],
  "edges": [
    { "id": "e1", "source": "n1", "target": "n2", "label": "Start" },
    { "id": "e2", "source": "n2", "target": "n3", "label": "Score received" },
    {
      "id": "e3",
      "source": "n3",
      "target": "n4",
      "sourceHandle": "true",
      "label": "Approved"
    },
    {
      "id": "e4",
      "source": "n3",
      "target": "n5",
      "sourceHandle": "false",
      "label": "Rejected"
    }
  ]
}
```

## Ejemplos reales

***

### Verificación antifraude

Llega una transacción, un nodo ejecutor obtiene la puntuación de fraude y un nodo condicional enruta la ejecución a la aprobación o al rechazo.

```json theme={null}
{
  "nodes": [
    { "id": "n1", "type": "trigger",     "name": "Transaction Received" },
    { "id": "n2", "type": "executor",    "name": "Get Fraud Score" },
    {
      "id": "n3",
      "type": "conditional",
      "name": "Evaluate Fraud Score",
      "data": { "condition": "n2.fraudScore < 70" }
    },
    { "id": "n4", "type": "executor",    "name": "Approve Transaction" },
    { "id": "n5", "type": "executor",    "name": "Reject and Notify" }
  ],
  "edges": [
    { "id": "e1", "source": "n1", "target": "n2", "label": "Start" },
    { "id": "e2", "source": "n2", "target": "n3", "label": "Score received" },
    {
      "id": "e3",
      "source": "n3",
      "target": "n4",
      "sourceHandle": "true",
      "label": "Low risk"
    },
    {
      "id": "e4",
      "source": "n3",
      "target": "n5",
      "sourceHandle": "false",
      "label": "High risk"
    }
  ]
}
```

### Orquestación de pagos

Un flujo lineal que valida los datos de pago entrantes, los enruta al proveedor adecuado y envía una confirmación.

```json theme={null}
{
  "nodes": [
    { "id": "n1", "type": "trigger",  "name": "Payment Initiated" },
    { "id": "n2", "type": "executor", "name": "Validate Payment Data" },
    { "id": "n3", "type": "executor", "name": "Route to Payment Provider" },
    { "id": "n4", "type": "executor", "name": "Send Confirmation" }
  ],
  "edges": [
    { "id": "e1", "source": "n1", "target": "n2", "label": "Start" },
    { "id": "e2", "source": "n2", "target": "n3", "label": "Valid" },
    { "id": "e3", "source": "n3", "target": "n4", "label": "Payment routed" }
  ]
}
```

### Onboarding de KYC

Usa un workflow para enviar una verificación de documentos a un sistema de aprobación externo. Flowker no tiene una pausa integrada: para la revisión humana asíncrona, empieza más tarde una ejecución de workflow separada, después de que tu sistema de aprobación publique su decisión.

### Flujo de aprobación manual

Un nodo ejecutor envía la solicitud a revisión. Un ejecutor recupera la decisión de la revisión desde el sistema externo. Después, un nodo condicional enruta a la vía aprobada o a la rechazada. Las ejecuciones de Flowker corren de principio a fin sin detenerse. Flowker no tiene un paso de pausa integrado, así que una decisión humana debe venir de un sistema externo que el workflow consulta.

```json theme={null}
{
  "nodes": [
    { "id": "n1", "type": "trigger",     "name": "Request Submitted" },
    { "id": "n2", "type": "executor",    "name": "Submit for Review" },
    { "id": "n3", "type": "executor",    "name": "Get Approval Decision" },
    {
      "id": "n4",
      "type": "conditional",
      "name": "Decision Received",
      "data": { "condition": "n3.decision == 'approved'" }
    },
    { "id": "n5", "type": "executor",    "name": "Process Approved Request" },
    { "id": "n6", "type": "executor",    "name": "Notify Rejection" }
  ],
  "edges": [
    { "id": "e1", "source": "n1", "target": "n2", "label": "Start" },
    { "id": "e2", "source": "n2", "target": "n3", "label": "Submitted" },
    { "id": "e3", "source": "n3", "target": "n4", "label": "Decision received" },
    {
      "id": "e4",
      "source": "n4",
      "target": "n5",
      "sourceHandle": "true",
      "label": "Approved"
    },
    {
      "id": "e5",
      "source": "n4",
      "target": "n6",
      "sourceHandle": "false",
      "label": "Rejected"
    }
  ]
}
```

## Mejores prácticas

***

### Convenciones de nombres de nodos

Usa nombres descriptivos y orientados a la acción que comuniquen lo que hace el nodo, no de qué tipo es.

* **correcto**: `Validate Payment Data`, `Get Fraud Score`, `Notify Customer`, `Get Approval Decision`
* **incorrecto**: `executor1`, `conditional node`, `node3`

Los buenos nombres hacen que los workflows se lean sin abrir la configuración del nodo. También aparecen en los registros de ejecución y en las trazas.

### Expresiones de condición

Flowker evalúa las condiciones de texto libre de los nodos condicionales contra el contexto de ejecución en tiempo de ejecución. Mantenlas simples y explícitas:

* Usa comparaciones directas de campos: `<nodeId>.status == 'approved'`
* Usa comparaciones numéricas: `<nodeId>.riskScore < 70`
* Usa campos booleanos: `<nodeId>.reviewRequired == true`
* Combina con `AND` / `OR` cuando haga falta: `<nodeId>.score < 70 AND <nodeId>.verified == true`

Evita las expresiones complejas. Hacen que el workflow sea difícil de leer y de depurar. Si la lógica no es trivial, dale al nodo `conditional` un nombre claro que encapsule la decisión.

Una condición ausente hace fallar la ejecución, y lo mismo pasa con una condición que no se puede evaluar en tiempo de ejecución (`FLK-0105` identifica una expresión condicional inválida). Prueba siempre las condiciones antes de activar un workflow.

### Estrategias de manejo de errores

Diseña los workflows para manejar el fallo de forma explícita:

* Agrega vías de rechazo desde los nodos `conditional` para cada punto de decisión que pueda fallar.
* Usa nodos `executor` separados para la lógica de reintento o los proveedores de respaldo.
* Nombra las vías de error con claridad (por ejemplo, `Reject and Notify`, `Fallback to Manual Review`) para que los registros de ejecución se expliquen solos.

### Evitar ciclos

Flowker usa una protección contra ciclos basada en DFS en tiempo de ejecución. Cuando esa protección encuentra un ciclo durante la ejecución, el workflow falla con `FLK-0508`. Los ciclos no se detectan en tiempo de diseño, así que valida la estructura de tus aristas antes de activar.

Reglas para prevenir ciclos:

* Las aristas siempre deben apuntar hacia adelante en el flujo, nunca de vuelta a un nodo ya ejecutado.
* Revisa el grafo de forma visual antes de activar cualquier workflow con vías que se ramifican o se unen.
* Si necesitas un reintento o un bucle, modélalo como una invocación de workflow separada, no como una arista de retorno en el grafo actual.

### Versionado mediante clonación

Nunca edites directamente un workflow activo. En su lugar:

<Steps>
  <Step>
    Clona el workflow (crea un nuevo `draft` con todos los nodos y aristas copiados).
  </Step>

  <Step>
    Haz tus cambios en el borrador.
  </Step>

  <Step>
    Valida o previsualiza el borrador. Actívalo antes de correr pruebas de ejecución.
  </Step>

  <Step>
    Activa la nueva versión.
  </Step>

  <Step>
    Desactiva la versión anterior si ya no la necesitas.
  </Step>
</Steps>

Esto preserva el historial de ejecución de la versión activa y te da una vía de rollback limpia si la nueva versión tiene problemas.

## Referencia de errores

***

Los siguientes códigos de error son relevantes para el diseño y la ejecución de workflows:

| Código     | Descripción                                                             |
| ---------- | ----------------------------------------------------------------------- |
| `FLK-0102` | Transición de estado inválida                                           |
| `FLK-0103` | El workflow no se puede modificar — no está en borrador                 |
| `FLK-0105` | Expresión condicional inválida                                          |
| `FLK-0113` | Demasiados nodos — el máximo es 100                                     |
| `FLK-0114` | Demasiadas aristas — el máximo es 200                                   |
| `FLK-0506` | Payload de entrada de la ejecución demasiado grande — el máximo es 1 MB |
| `FLK-0508` | Ciclo detectado durante la ejecución del workflow                       |
