> ## 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.

# Guia de design de workflows

> Projete workflows do Flowker: tipos de nó, arestas, padrões reais, transições de status e boas práticas para uma orquestração confiável.

Este guia percorre tipos de nó, arestas, padrões reais, transições de status, limites técnicos e boas práticas.

## Tipos de nó

***

Todo workflow é formado por nós. Cada nó tem um `type` que define como o Flowker o processa em tempo de execução.

### trigger

Um nó de gatilho é um ponto de entrada de execução. Workflows em draft podem estar incompletos, mas a ativação exige pelo menos um nó de gatilho. Quando uma execução começa por um gatilho, o motor entra nesse nó e roteia a partir dele.

Os exemplos desta página mostram apenas a topologia dos nós. Um nó de gatilho real também carrega um `triggerType` e a configuração desse gatilho em seu `data`. Veja [Configurando um gatilho de webhook](/pt/products/flowker/configuring-a-webhook-trigger) ou [Rodando um workflow em um agendamento](/pt/products/flowker/running-a-workflow-on-a-schedule).

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

### executor

Chama um serviço externo por meio de uma configuração de provedor. Este nó é o principal ponto de integração para motores antifraude, provedores de pagamento, serviços de notificação e outros sistemas externos.

Os exemplos desta página mostram apenas a topologia dos nós. Um nó executor real também carrega um `providerConfigId` em seu `data`, além de um `executorId` que nomeia o executor do catálogo que ele invoca. Um nó que chama uma operação de um documento OpenAPI enviado omite o `executorId` e carrega `operation_path` e `operation_method` no lugar. Veja o [Guia de integração](/pt/products/flowker/integration-guide).

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

### conditional

Avalia uma condição em relação ao contexto de execução e roteia para ramos diferentes conforme o resultado. Use nós condicionais para implementar lógica de ramificação, por exemplo, roteando para um caminho de aprovação quando o risco é alto, ou seguindo direto quando ele é baixo.

A condição fica no `data.condition` do nó. Uma expressão de texto livre é avaliada como booleano e produz o conector de saída `true` ou `false`. Cada aresta de saída declara qual conector ela segue por meio de `sourceHandle`. Nós condicionais criados no Console usam uma condição estruturada, baseada em casos, na qual cada caso roteia para o próprio conector de saída. Veja o [Editor de canvas](/pt/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 uma operação interna síncrona `set_output`. Ele pode escrever um valor de saída interpolado e, opcionalmente, sobrescrever o status da resposta HTTP síncrona. Ele não oferece pausa embutida, emissão genérica de eventos nem operação genérica de mudança de estado.

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

## Arestas

***

Arestas conectam nós e definem caminhos de execução. Cada aresta inclui os campos a seguir:

| Campo          | Descrição                                                                                                                                                                                                        |
| -------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `id`           | Identificador único da aresta.                                                                                                                                                                                   |
| `source`       | ID do nó de origem.                                                                                                                                                                                              |
| `target`       | ID do nó de destino.                                                                                                                                                                                             |
| `sourceHandle` | Conector de saída do nó de origem que esta aresta segue. Obrigatório para rotear a partir de um nó condicional: ele deve corresponder ao resultado do ramo (`true` ou `false` para uma condição de texto livre). |
| `condition`    | Campo legado de texto livre mantido por compatibilidade retroativa. Ele não é avaliado para roteamento — deixe-o vazio em novos workflows.                                                                       |
| `label`        | Rótulo legível usado para visualização e depuração.                                                                                                                                                              |

### Exemplo de aresta

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

O roteamento depende do tipo do nó de origem. Um nó condicional avalia seu `data.condition` e segue a única aresta de saída cujo `sourceHandle` corresponde ao resultado do ramo. Se nenhuma aresta corresponder, esse ramo termina. Todos os outros tipos de nó seguem todas as suas arestas de saída quando terminam com sucesso.

## Transições de status

***

Workflows seguem um ciclo de vida bem definido.

<Frame>
  <img src="https://mintcdn.com/lerian-49cb71fc/vdBt8wfgjsNRO1rf/images/pt/d2/flowker-workflow-status-transitions.svg?fit=max&auto=format&n=vdBt8wfgjsNRO1rf&q=85&s=d9828dc789f5e48d064e941a3af9d0c5" alt="Diagrama de transição de status do workflow mostrando três estados: draft, active e inactive. Uma seta rotulada 'activate' aponta de draft para active. Uma seta rotulada 'deactivate' aponta de active para inactive. Uma seta rotulada 'draft' aponta de inactive de volta para draft." width="817" height="327" data-path="images/pt/d2/flowker-workflow-status-transitions.svg" />
</Frame>

* **draft**: o estado inicial. Você pode adicionar nós, editar arestas e mudar a configuração apenas no status `draft`.
* **active**: um workflow que você ativou. O Flowker pode executá-lo. Ele não aceita modificação enquanto está ativo.
* **inactive**: um workflow que você desativou. O Flowker não pode mais executá-lo, mas você pode movê-lo de volta para `draft` para editar.

### Regras

* Você pode ativar apenas um workflow em `draft` (transição: `draft → active`).
* Você pode desativar apenas um workflow `active` (transição: `active → inactive`).
* Você pode mover de volta para draft apenas um workflow `inactive` (transição: `inactive → draft`).
* Tentar uma transição inválida retorna o erro `FLK-0102`.
* Tentar modificar um workflow que não está em `draft` retorna o erro `FLK-0103`.

### Movendo um workflow inativo de volta para draft

Se você desativou um workflow e quer editá-lo de novo, mova-o de volta para `draft` chamando [`POST /v1/workflows/{id}/draft`](/pt/reference/products/flowker/move-workflow-to-draft). Isso torna o workflow editável sem precisar cloná-lo.

Use isso quando você desativou um workflow por engano, ou quando quer iterar sobre um workflow existente em vez de criar uma cópia.

<Note>
  Você pode mover para draft apenas workflows inativos. Se precisar modificar um workflow ativo sem tirá-lo do ar, use a abordagem de clone descrita abaixo.
</Note>

### Iterando com segurança usando clone

Para modificar um workflow ativo, clone-o primeiro. A clonagem cria um novo `draft` a partir de qualquer status, copiando todos os nós e arestas. Você pode então atualizá-lo, testá-lo e ativá-lo sem impactar a versão atual.

Use esta abordagem para versionamento em produção.

## Limites técnicos

***

| Limite                                | Valor | Código de erro |
| ------------------------------------- | ----- | -------------- |
| Máximo de nós por workflow            | 100   | `FLK-0113`     |
| Máximo de arestas por workflow        | 200   | `FLK-0114`     |
| Payload máximo de entrada da execução | 1 MB  | `FLK-0506`     |

Workflows com mais de \~50 nós costumam indicar que o fluxo deveria ser dividido em workflows menores e combináveis.

## Padrões comuns

***

### Sequencial

O padrão mais simples. Os nós executam em uma sequência linear. Use quando cada passo depende do anterior e não precisa de ramificação.

<Frame>
  <img src="https://mintcdn.com/lerian-49cb71fc/vdBt8wfgjsNRO1rf/images/pt/d2/flowker-pattern-sequential.svg?fit=max&auto=format&n=vdBt8wfgjsNRO1rf&q=85&s=73607c3892907dd0055973e52530ca81" alt="Padrão de workflow sequencial: um nó de gatilho se conecta a um primeiro nó executor, que se conecta a um segundo nó executor, que se conecta a um terceiro nó executor. Todas as ligações são setas direcionadas simples formando uma linha reta." width="957" height="268" data-path="images/pt/d2/flowker-pattern-sequential.svg" />
</Frame>

**Exemplo: orquestração de pagamento**

```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" }
  ]
}
```

### Ramificação condicional

Um nó `conditional` avalia sua condição e roteia a execução conforme o resultado. O resultado do ramo seleciona a aresta de saída que o nó segue, casada pelo `sourceHandle`.

<Frame>
  <img src="https://mintcdn.com/lerian-49cb71fc/vdBt8wfgjsNRO1rf/images/pt/d2/flowker-pattern-conditional.svg?fit=max&auto=format&n=vdBt8wfgjsNRO1rf&q=85&s=9e04bca7fc5e470c47e3677b4ab9527a" alt="Padrão de workflow com ramificação condicional: um nó de gatilho se conecta a um nó executor, que se conecta a um nó condicional. O nó condicional tem duas setas de saída: uma rotulada 'Path A' apontando para um primeiro nó executor, e outra rotulada 'Path B' apontando para um segundo nó executor." width="999" height="394" data-path="images/pt/d2/flowker-pattern-conditional.svg" />
</Frame>

**Exemplo: verificação 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"
    }
  ]
}
```

## Exemplos reais

***

### Verificação antifraude

Uma transação chega, um nó executor obtém a pontuação de fraude e um nó condicional roteia a execução para a aprovação ou a rejeição.

```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"
    }
  ]
}
```

### Orquestração de pagamento

Um fluxo linear que valida os dados de pagamento recebidos, roteia para o provedor adequado e envia uma confirmação.

```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

Use um workflow para enviar uma verificação de documento a um sistema de aprovação externo. O Flowker não tem pausa embutida: para revisão humana assíncrona, comece depois uma execução de workflow separada, após o seu sistema de aprovação publicar a decisão dele.

### Fluxo de aprovação manual

Um nó executor envia a requisição para revisão. Um executor busca a decisão da revisão no sistema externo. Um nó condicional então roteia para o caminho aprovado ou para o rejeitado. As execuções do Flowker correm direto até o fim. O Flowker não tem passo de pausa embutido, então uma decisão humana deve vir de um sistema externo que o 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"
    }
  ]
}
```

## Boas práticas

***

### Convenções de nomes de nós

Use nomes descritivos e orientados a ação, que comuniquem o que o nó faz, não de que tipo ele é.

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

Bons nomes deixam os workflows legíveis sem abrir a configuração do nó. Eles também aparecem nos registros de execução e nos traces.

### Expressões de condição

O Flowker avalia condições de texto livre em nós condicionais em relação ao contexto de execução, em tempo de execução. Mantenha-as simples e explícitas:

* Use comparações diretas de campo: `<nodeId>.status == 'approved'`
* Use comparações numéricas: `<nodeId>.riskScore < 70`
* Use campos booleanos: `<nodeId>.reviewRequired == true`
* Combine com `AND` / `OR` quando precisar: `<nodeId>.score < 70 AND <nodeId>.verified == true`

Evite expressões complexas. Elas deixam o workflow difícil de ler e de depurar. Se a lógica não for trivial, dê ao nó `conditional` um nome claro que resuma a decisão.

Uma condição ausente faz a execução falhar, e o mesmo acontece com uma condição que não consegue ser avaliada em tempo de execução (`FLK-0105` identifica uma expressão condicional inválida). Sempre teste as condições antes de ativar um workflow.

### Estratégias de tratamento de erros

Projete workflows para tratar a falha de forma explícita:

* Adicione caminhos de rejeição a partir de nós `conditional` para cada ponto de decisão que pode falhar.
* Use nós `executor` separados para a lógica de nova tentativa ou para provedores de fallback.
* Nomeie os caminhos de erro com clareza (por exemplo, `Reject and Notify`, `Fallback to Manual Review`) para que os registros de execução se expliquem sozinhos.

### Evitando ciclos

O Flowker usa uma proteção contra ciclos baseada em DFS em tempo de execução. Quando essa proteção encontra um ciclo durante a execução, o workflow falha com `FLK-0508`. Ciclos não são detectados em tempo de design, então valide a estrutura das suas arestas antes de ativar.

Regras para evitar ciclos:

* As arestas devem sempre apontar para frente no fluxo, nunca de volta para um nó já executado.
* Revise o grafo visualmente antes de ativar qualquer workflow com caminhos de ramificação ou de junção.
* Se você precisar de uma nova tentativa ou de um laço, modele isso como uma invocação de workflow separada, não como uma aresta de retorno no grafo atual.

### Versionamento via clone

Nunca edite um workflow ativo diretamente. Em vez disso:

<Steps>
  <Step>
    Clone o workflow (cria um novo `draft` com todos os nós e arestas copiados).
  </Step>

  <Step>
    Faça suas mudanças no draft.
  </Step>

  <Step>
    Valide ou pré-visualize o draft. Ative-o antes de rodar testes de execução.
  </Step>

  <Step>
    Ative a nova versão.
  </Step>

  <Step>
    Desative a versão antiga se você não precisar mais dela.
  </Step>
</Steps>

Isso preserva o histórico de execução da versão ativa e dá a você um caminho de rollback limpo se a nova versão tiver problemas.

## Referência de erros

***

Os códigos de erro a seguir são relevantes para o design e a execução de workflows:

| Código     | Descrição                                                      |
| ---------- | -------------------------------------------------------------- |
| `FLK-0102` | Transição de status inválida                                   |
| `FLK-0103` | O workflow não pode ser modificado — não está em status draft  |
| `FLK-0105` | Expressão condicional inválida                                 |
| `FLK-0113` | Nós demais — o máximo é 100                                    |
| `FLK-0114` | Arestas demais — o máximo é 200                                |
| `FLK-0506` | Payload de entrada da execução grande demais — o máximo é 1 MB |
| `FLK-0508` | Ciclo detectado durante a execução do workflow                 |
