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

# Executando um workflow em um agendamento

> Inicie um workflow do Flowker em uma cadência, leia as ocorrências que ele planeja executar e decida o que acontece com uma ocorrência que não pôde ser executada no horário.

Um trigger de schedule inicia um workflow em uma cadência que você escreve como uma expressão cron. O Flowker registra cada disparo como uma ocorrência, então um disparo que não pôde acontecer no horário não é perdido: ele espera em uma lista de ocorrências retidas até que você o execute ou o descarte.

Use esta página para escrever o trigger, confirmar a cadência e trabalhar a lista de ocorrências retidas.

## Antes de começar

***

* Um workflow em status `draft`. Somente um workflow em draft aceita uma edição, portanto escreva o trigger antes de ativá-lo. Veja [Primeiros passos com o Flowker](/pt/reference/flowker/flowker-api-quick-start) para o caminho de criação e ativação.
* O binário worker em execução com o scheduler habilitado. `SCHEDULER_ENABLED` é resolvido como `true` a menos que você o defina como `false`, e a fila precisa de `SCHEDULER_REDIS_HOST`: sem host, o binário worker não inicia e nenhum workflow agendado dispara. Verifique essa variável primeiro quando os seus agendamentos nunca disparam. Veja [Variáveis do scheduler](/pt/flowker/flowker-environment-variables#scheduler).
* A permissão `read` sobre o recurso `workflows` para listar ocorrências e contagens, e `update` sobre o mesmo recurso para executar ou descartar uma.

## Passo 1: Escreva o node do trigger de schedule

***

Os triggers já vêm incluídos. Você os descobre no catálogo e nunca cria um. [Obter um trigger do catálogo](/pt/reference/flowker/get-catalog-trigger) retorna o JSON Schema do trigger de schedule direto da instância em execução:

```bash theme={null}
curl -s http://localhost:4021/v1/catalog/triggers/schedule | jq -r '.schema' | jq .
```

O trigger de schedule é um node com `type: "trigger"` e estes campos no seu `data`:

| Campo         | Quando você define | Valor                                                                                                             |
| ------------- | ------------------ | ----------------------------------------------------------------------------------------------------------------- |
| `triggerType` | Sempre             | `"schedule"`.                                                                                                     |
| `cron`        | Sempre             | A cadência, como uma expressão cron padrão de 5 campos: `minuto hora dia-do-mês mês dia-da-semana`.               |
| `timezone`    | Opcional           | O identificador IANA do fuso a que os campos do cron pertencem, por exemplo `"America/Sao_Paulo"`. Padrão: `UTC`. |
| `enabled`     | Opcional           | `false` impede que o agendamento dispare enquanto o workflow continua ativo. Padrão: `true`.                      |

### O que a expressão cron aceita

Cinco campos separados por espaços. Cada campo aceita `*`, um valor, uma lista (`0,30`), um intervalo (`9-17`) ou um passo (`*/15`, `9-17/2`). O dia da semana vai de `0` a `7`, e tanto `0` quanto `7` significam domingo. Quando você restringe o dia do mês e o dia da semana ao mesmo tempo, o agendamento dispara em um dia que satisfaz qualquer um dos dois campos: `0 9 13 * 5` dispara no dia 13 e em todas as sextas-feiras.

Um minuto é a cadência mais fina que uma expressão de 5 campos consegue expressar. Para algo mais rápido, atenda a chamada no momento em que ela chega com um [trigger de webhook](/pt/flowker/configuring-a-webhook-trigger).

O Flowker verifica a expressão quando você salva o workflow e novamente quando você o ativa, e responde `FLK-0117` quando ela não se sustenta. Estas formas não se sustentam:

* Uma expressão de seis campos, como `*/30 * * * * *`.
* Uma macro, como `@daily` ou `@every 5m`.
* Um dia ou um mês com nome, como `MON`, `MON-FRI` ou `sun`.
* Um token `L` ou `#`, como `0 9 L * *` ou `0 9 * * 5#2`.
* Um valor fora do intervalo do seu campo, como `60` minutos, `24` horas, dia do mês `0` ou `32`, mês `13` ou dia da semana `8`.
* Um passo `/0`.

### Como o fuso horário funciona

Os campos do cron são hora de relógio de parede no fuso que você nomeia, e toda hora que a API retorna é UTC. Um agendamento `0 9 * * *` em `America/Sao_Paulo` reporta `12:00Z`. Um fuso que observa horário de verão mantém a hora de relógio de parede na virada: a mesma expressão em `America/New_York` reporta `14:00Z` no inverno e `13:00Z` no verão.

<CodeGroup>
  ```json diário theme={null}
  {
    "id": "trigger-1",
    "type": "trigger",
    "name": "Liquidação diária",
    "position": { "x": 0, "y": 0 },
    "data": {
      "triggerType": "schedule",
      "cron": "0 9 * * *",
      "timezone": "America/Sao_Paulo"
    }
  }
  ```

  ```json a cada 15 minutos theme={null}
  {
    "id": "trigger-1",
    "type": "trigger",
    "name": "Consultar novos extratos",
    "position": { "x": 0, "y": 0 },
    "data": {
      "triggerType": "schedule",
      "cron": "*/15 * * * *"
    }
  }
  ```

  ```json dias úteis, em pausa theme={null}
  {
    "id": "trigger-1",
    "type": "trigger",
    "name": "Conciliação em dias úteis",
    "position": { "x": 0, "y": 0 },
    "data": {
      "triggerType": "schedule",
      "cron": "30 7 * * 1-5",
      "timezone": "America/Sao_Paulo",
      "enabled": false
    }
  }
  ```

  ```json mensal theme={null}
  {
    "id": "trigger-1",
    "type": "trigger",
    "name": "Lote de abertura do mês",
    "position": { "x": 0, "y": 0 },
    "data": {
      "triggerType": "schedule",
      "cron": "0 3 1 * *",
      "timezone": "UTC"
    }
  }
  ```
</CodeGroup>

## Passo 2: Ative o workflow e leia a cadência

***

<Steps>
  <Step title="Salve o workflow">
    Envie o node com o resto do seu workflow para [Criar um workflow](/pt/reference/flowker/create-workflow), ou para [Atualizar um workflow](/pt/reference/flowker/update-workflow) se o draft já existir. O Flowker valida o cron aqui.
  </Step>

  <Step title="Confira a cadência antes de assumi-la">
    [Listar próximas ocorrências agendadas](/pt/reference/flowker/list-upcoming-scheduled-occurrences) calcula os próximos disparos direto do trigger, então você pode lê-los enquanto o workflow ainda é um draft.

    ```bash theme={null}
    curl -s "http://localhost:4021/v1/workflows/019c96a0-0ac0-7de9-9f53-9cf842a2ee5a/schedule/upcoming?limit=3" | jq .
    ```

    ```json theme={null}
    {
      "occurrences": [
        { "scheduledFor": "2026-08-01T12:00:00Z" },
        { "scheduledFor": "2026-08-02T12:00:00Z" },
        { "scheduledFor": "2026-08-03T12:00:00Z" }
      ]
    }
    ```

    `limit` aceita de `1` a `50` e o padrão é `10`. Um valor fora desse intervalo responde `FLK-0304`.
  </Step>

  <Step title="Ative-o">
    Chame [Ativar um workflow](/pt/reference/flowker/activate-workflow). Em menos de um minuto o engine registra a próxima ocorrência e a enfileira para o horário dela.

    ```bash theme={null}
    curl -s -X POST http://localhost:4021/v1/workflows/019c96a0-0ac0-7de9-9f53-9cf842a2ee5a/activate | jq .
    ```
  </Step>
</Steps>

O Flowker registra apenas o próximo disparo, nunca um calendário de disparos futuros. Quando essa ocorrência é executada, o engine registra o disparo seguinte, então a cadência se sustenta sozinha, uma ocorrência por vez.

## Passo 3: Veja quais ocorrências não foram executadas

***

Uma ocorrência fica **retida** quando o engine chega até ela mais de um minuto depois do horário dela e ninguém pediu que aquele horário fosse executado: o serviço estava fora, a fila estava atrasada, o processo reiniciou. O Flowker nunca executa uma ocorrência retida por conta própria — ele a guarda para a sua decisão, no estado `pending-review`. Reter é o único resultado que não é terminal: uma ocorrência retida continua acionável até você executá-la ou descartá-la.

O Flowker nunca preenche um horário que passou. Então a lista de retidas guarda os disparos que o Flowker já havia registrado e não conseguiu executar — não uma entrada para cada horário que passou durante uma indisponibilidade — e a cadência em si retoma a partir do próximo horário futuro.

Uma ocorrência é **ignorada** quando o engine a assumiu e a encerrou sem executar o workflow. Uma ocorrência ignorada é terminal e carrega um `skipReason`:

| `skipReason`          | O que aconteceu                                                                                                                        |
| --------------------- | -------------------------------------------------------------------------------------------------------------------------------------- |
| `active-run`          | Outra execução deste workflow ainda estava em andamento. Um agendamento executa uma ocorrência por vez, então este disparo se afastou. |
| `workflow-gone`       | O workflow foi excluído, ou não estava ativo quando a ocorrência chegou ao engine.                                                     |
| `execution-duplicate` | O trabalho daquele horário já havia sido executado, então o engine não o executou duas vezes.                                          |

As duas classes não se separam pelo momento do disparo. Uma coisa esse momento decide: um horário atrasado que você nunca pediu para executar aparece na lista de retidas, nunca na de ignoradas. Depois que você pede que um horário retido seja executado, a idade dele para de segurá-lo. O engine então o assume como qualquer outra ocorrência, e os três motivos acima podem encerrá-lo. Então um `scheduledFor` bem antigo é normal na lista de ignoradas, e não significa que o horário disparou em tempo. O [Passo 4](#passo-4-execute-ou-descarte-uma-ocorrência-retida) cobre em que a sua própria execução pode terminar.

Três leituras cobrem o quadro completo:

<Steps>
  <Step title="Liste as ocorrências retidas de um workflow">
    [Listar ocorrências agendadas retidas](/pt/reference/flowker/list-parked-scheduled-occurrences) retorna da mais antiga para a mais recente.

    ```bash theme={null}
    curl -s http://localhost:4021/v1/workflows/019c96a0-0ac0-7de9-9f53-9cf842a2ee5a/schedule/missed | jq .
    ```

    ```json theme={null}
    {
      "occurrences": [
        {
          "id": "019c96a0-3f21-7b44-8d0e-5a1c7e2b9f30",
          "workflowId": "019c96a0-0ac0-7de9-9f53-9cf842a2ee5a",
          "status": "pending-review",
          "cronExpr": "0 9 * * *",
          "timezone": "America/Sao_Paulo",
          "scheduledFor": "2026-07-29T12:00:00Z",
          "attempts": 0,
          "createdAt": "2026-07-29T11:00:04Z",
          "updatedAt": "2026-07-30T08:12:41Z"
        }
      ]
    }
    ```

    `scheduledFor` é o horário que a ocorrência representa, e `status` é o que decide se você pode agir sobre ela.

    Esta rota não aceita `limit` nem cursor de paginação, e retorna no máximo 100 ocorrências. Planeje uma recuperação em massa com isso em mente: trabalhe as linhas que você recebe e leia a lista novamente. A contagem mais abaixo informa o total real. Descartar a lista inteira também cobre todas as ocorrências pendentes de revisão, não apenas as 100 que uma única leitura mostra.
  </Step>

  <Step title="Liste as ocorrências ignoradas">
    [Listar ocorrências agendadas ignoradas](/pt/reference/flowker/list-skipped-scheduled-occurrences) retorna da mais antiga para a mais recente, cada uma com o seu `skipReason`. `limit` aceita de `1` a `50`.

    ```bash theme={null}
    curl -s "http://localhost:4021/v1/workflows/019c96a0-0ac0-7de9-9f53-9cf842a2ee5a/schedule/skipped?limit=10" | jq '.occurrences[] | {scheduledFor, skipReason}'
    ```

    ```json theme={null}
    { "scheduledFor": "2026-07-28T12:00:00Z", "skipReason": "active-run" }
    ```

    Uma sequência de omissões `active-run` significa que o workflow demora mais do que o intervalo entre dois disparos. Alargue a cadência ou faça o workflow terminar mais rápido.
  </Step>

  <Step title="Conte o que está esperando em todos os workflows">
    [Contar ocorrências pendentes de revisão](/pt/reference/flowker/count-pending-review-occurrences) responde por todo o tenant em uma única chamada, que é o que você consulta para um badge de revisão. O mapa é esparso: um workflow sem nada esperando não aparece nele.

    ```bash theme={null}
    curl -s http://localhost:4021/v1/workflows/schedule/pending-review-counts | jq .
    ```

    ```json theme={null}
    {
      "counts": {
        "019c96a0-0ac0-7de9-9f53-9cf842a2ee5a": 2
      }
    }
    ```

    Acrescente `?workflowIds=<id>,<id>` para limitar as contagens aos workflows que interessam a você.
  </Step>
</Steps>

As duas listas respondem `200` com um array `occurrences` vazio para um id de workflow que o seu tenant não possui, então uma lista vazia significa "nada a revisar aqui".

<Tip>
  O Console mostra as mesmas três leituras. Abra o painel **Agendamento** a partir da lista de workflows para ver o status do agendamento, as próximas execuções e as execuções pendentes de revisão. Veja [Visão geral de workflows](/pt/flowker/console/workflows-overview).
</Tip>

## Passo 4: Execute ou descarte uma ocorrência retida

***

Executar e descartar agem sobre uma ocorrência cujo `status` é `pending-review`. Qualquer outro estado responde `FLK-0755`, o que também torna segura uma chamada repetida: a segunda é recusada em vez de agir duas vezes. A sua própria execução deixa a ocorrência em um desses outros estados: ela sai de `pending-review` na hora.

Uma execução que você pede sai da lista de retidas de imediato, e a idade do horário não a segura mais. Ela não promete que o workflow execute:

* **O workflow executa.** A execução aparece em [Listar execuções](/pt/reference/flowker/list-executions) para aquele workflow.
* **O engine encerra a ocorrência como ignorada.** Ela sai da lista de retidas para a de ignoradas com um dos três motivos acima. `active-run` significa que outra execução do workflow ainda estava em andamento. `workflow-gone` significa que o workflow não estava ativo quando a sua execução chegou ao engine. `execution-duplicate` significa que o trabalho daquele horário já havia sido executado.

Uma omissão vinda da sua própria execução é tão terminal quanto qualquer outra, então uma segunda execução ou um descarte sobre ela respondem `FLK-0755`. Leia as duas listas antes de concluir algo sobre um horário que você tentou recuperar. A linha ignorada pode registrar a recusa da sua recuperação, não a do disparo original.

Mantenha o workflow ativo enquanto você trabalha a lista. Uma execução recarrega o workflow, e um workflow que não está ativo encerra a ocorrência como uma omissão `workflow-gone` em vez de executá-la.

<Steps>
  <Step title="Execute uma ocorrência">
    [Executar uma ocorrência retida](/pt/reference/flowker/run-parked-occurrence) a move para `queued` e a entrega ao mesmo caminho de execução que um disparo agendado usa. Ela começa em um ou dois segundos.

    ```bash theme={null}
    curl -s -X POST http://localhost:4021/v1/workflows/019c96a0-0ac0-7de9-9f53-9cf842a2ee5a/schedule/missed/019c96a0-3f21-7b44-8d0e-5a1c7e2b9f30/run | jq '{id, status}'
    ```

    ```json theme={null}
    { "id": "019c96a0-3f21-7b44-8d0e-5a1c7e2b9f30", "status": "queued" }
    ```

    A execução cobre aquele único horário. Ela não desloca a cadência: o próximo disparo continua sendo o que o engine já planejou.
  </Step>

  <Step title="Descarte uma ocorrência">
    [Descartar uma ocorrência retida](/pt/reference/flowker/discard-parked-occurrence) a move para `discarded`, que é terminal. A ocorrência nunca é executada e sai da lista de retidas.

    ```bash theme={null}
    curl -s -X POST http://localhost:4021/v1/workflows/019c96a0-0ac0-7de9-9f53-9cf842a2ee5a/schedule/missed/019c96a0-3f21-7b44-8d0e-5a1c7e2b9f30/discard | jq '{id, status}'
    ```

    ```json theme={null}
    { "id": "019c96a0-3f21-7b44-8d0e-5a1c7e2b9f30", "status": "discarded" }
    ```
  </Step>

  <Step title="Limpe toda a lista de retidas de um workflow">
    [Descartar todas as ocorrências retidas](/pt/reference/flowker/discard-all-parked-occurrences) descarta, em uma única escrita, todas as ocorrências daquele workflow que estão pendentes de revisão, e informa quantas foram movidas.

    ```bash theme={null}
    curl -s -X POST http://localhost:4021/v1/workflows/019c96a0-0ac0-7de9-9f53-9cf842a2ee5a/schedule/missed/discard-all | jq .
    ```

    ```json theme={null}
    { "discarded": 7 }
    ```

    Sem nada pendente de revisão, ela responde `200` com `"discarded": 0`, então uma chamada repetida é segura.
  </Step>
</Steps>

<Warning>
  Um descarte não pode ser desfeito e nunca executa nada. Leia a lista de retidas antes de limpá-la.

  Descartar todas as ocorrências retidas cobre exatamente as ocorrências daquele único workflow, no seu tenant, que estão pendentes de revisão. Ele deixa o agendamento funcionando, deixa as próximas ocorrências intactas e não toca nas ocorrências de outro workflow nem nas que já foram executadas, falharam, foram ignoradas ou foram descartadas antes.
</Warning>

## Confirme que funcionou

***

* A cadência está saudável quando [Listar próximas ocorrências agendadas](/pt/reference/flowker/list-upcoming-scheduled-occurrences) retorna horários futuros e a lista de retidas se mantém curta.
* Uma execução funcionou quando a ocorrência saiu da lista de retidas e a execução aparece em [Listar execuções](/pt/reference/flowker/list-executions) para aquele workflow.
* Um descarte funcionou quando a ocorrência saiu da lista de retidas e a contagem de pendentes de revisão daquele workflow caiu.

## Mude ou pause uma cadência

***

Somente um workflow em draft aceita uma edição, então mudar a cadência são quatro chamadas:

1. [Desative o workflow](/pt/reference/flowker/deactivate-workflow). O Flowker para de registrar novas ocorrências para ele.
2. [Mova-o para draft](/pt/reference/flowker/move-workflow-to-draft).
3. [Atualize o workflow](/pt/reference/flowker/update-workflow) com o novo valor de `cron`, `timezone` ou `enabled`.
4. [Ative-o](/pt/reference/flowker/activate-workflow). Em menos de um minuto o engine registra a próxima ocorrência da nova cadência.

O Flowker não preenche os horários que passaram enquanto o workflow esteve inativo, e as ocorrências retidas sobrevivem aos quatro passos: elas continuam listadas e continuam acionáveis quando o workflow está ativo de novo.

<Note>
  Uma ocorrência que o Flowker registrou antes da mudança continua pendente. Leia a lista de retidas depois de mudar a cadência e limpe o que você não quiser mais.
</Note>

## Quando algo falha

***

| Código     | Quando acontece                                     | O que fazer                                                                                                                                                                                                         |
| ---------- | --------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `FLK-0117` | Você salva ou ativa o workflow.                     | O cron não é uma expressão padrão de 5 campos. Compare-o com [O que a expressão cron aceita](#o-que-a-expressão-cron-aceita).                                                                                       |
| `FLK-0118` | Você lista as próximas ocorrências.                 | O workflow não carrega um trigger de schedule, ou o cron dele não é uma expressão que o Flowker consiga calcular. Verifique o `triggerType` e o `cron` do node trigger.                                             |
| `FLK-0100` | Você lista as próximas ocorrências.                 | Nenhum workflow do seu tenant tem esse id.                                                                                                                                                                          |
| `FLK-0002` | Qualquer uma destas chamadas.                       | Um id do path não é um UUID válido.                                                                                                                                                                                 |
| `FLK-0304` | Você lista as próximas ocorrências ou as ignoradas. | `limit` está fora de `1`–`50`.                                                                                                                                                                                      |
| `FLK-0755` | Você executa ou descarta uma ocorrência.            | A ocorrência não está pendente de revisão. A sua própria execução pode já tê-la movido, ou ela pode ter sido executada, ignorada ou descartada. Leia a lista de retidas e a de ignoradas antes de chamar novamente. |
| `FLK-0760` | Você executa ou descarta uma ocorrência.            | Nenhuma ocorrência daquele workflow tem esse id. Pegue o id na lista de retidas do mesmo workflow.                                                                                                                  |

Duas falhas não respondem nenhum código de erro:

* **As próximas ocorrências são listadas, mas nada nunca é executado.** A API calcula a cadência por conta própria, enquanto o binário worker é quem a dispara. Confirme que o worker está em execução e que `SCHEDULER_REDIS_HOST` está definido. Veja [Variáveis do scheduler](/pt/flowker/flowker-environment-variables#scheduler).
* **Nada de novo é registrado para um workflow ativo.** Verifique `enabled` no node trigger: `false` mantém o workflow ativo e o agendamento dele em silêncio.

## Próximos passos

***

<CardGroup cols={2}>
  <Card title="Configurando um trigger de webhook" icon="webhook" href="/pt/flowker/configuring-a-webhook-trigger">
    Inicie o mesmo workflow a partir de uma chamada HTTP recebida em vez de uma cadência.
  </Card>

  <Card title="Guia de design de workflows" icon="diagram-project" href="/pt/flowker/workflow-design-guide">
    Construa o resto do grafo em que o trigger entra.
  </Card>
</CardGroup>
