FlowsReferência

O formato de arquivo do flow (YAML / JSON)

Tudo o que está no canvas de um flow também é um arquivo de texto. Ver arquivo mostra o flow em YAML ou JSON, você pode editar ali e ver o canvas acompanhar, e o mesmo formato é o que um repositório Git conectado guarda como .flow.yaml. O arquivo guarda só o significado — passos, ligações e configurações — nunca posições: o canvas se organiza sozinho a partir da estrutura.

O que você vai aprender
  • Abrir, ler e editar um flow em YAML ou JSON
  • Conhecer as chaves: trigger, a, b, c… e onError
  • Escrever cada forma de vínculo e cada nó estrutural
  • Copiar um flow entre flows, e guardá-lo no Git

Um flow é um arquivo

Abra o menu ⋯ do flow e escolha Ver arquivo (“Ler este flow como YAML”). Abre uma gaveta com a definição inteira e uma chave YAML / JSON. Mudanças no canvas aparecem no arquivo na hora; edições no arquivo chegam ao canvas cerca de meio segundo depois que você para de digitar, desde que o texto seja válido — senão a gaveta diz YAML parse error e o canvas mantém a última versão boa. As edições ficam não salvas até você clicar em Salvar, igual às edições no canvas.

O canvas é desenhado a partir da estrutura do arquivo: nenhuma coordenada é guardada, então o mesmo arquivo sempre se organiza do mesmo jeito.

Pílulas de ramo, finais de grupo, a junção abaixo de ramos em paralelo e o corpo sombreado do loop também não estão no arquivo. Eles são derivados da estrutura toda vez que o canvas é desenhado, e por isso um arquivo escrito à mão — ou por um assistente de IA, ou trazido do Git — aparece tão organizado quanto um montado arrastando.

Um exemplo completo

Um flow que carrega pedidos acima de um total mínimo, dá uma nota a cada um num loop em paralelo, gera um relatório quando houve pedidos, e tem um passo Em caso de erro — exatamente como o Ver arquivo escreve:

YAMLorders.flow.yaml
trigger:
  parameters:
    - name: minTotal
      type: number
      default: 100
  next: a
a:
  kind: script
  label: Load orders
  alias: loadOrders
  lang: postgresql
  code: |
    -- @param min_total number = 100
    SELECT id, email, total FROM orders WHERE total >= :min_total
  integration: 9b1c6e2a-5d1f-4c1e-9a7e-2f0c3b8d4e61
  inputs:
    min_total:
      from: trigger
      path: minTotal
  next: b
b:
  kind: loop
  label: Each order
  alias: eachOrder
  iterate:
    from: a
    path: rows
  mode: parallel
  concurrency: 5
  body:
    - c
  next: d
c:
  kind: script
  label: Score
  alias: score
  lang: python
  code: |
    def main(total: float):
        return {"vip": total > 500}
  inputs:
    total:
      from: b
      path: item.total
  retry:
    attempts: 2
    delay: exponential
    delaySec: 2
d:
  kind: condition
  label: Any orders?
  alias: anyOrders
  if: nodes.loadOrders.output.rowCount > 0
  then:
    label: "Yes"
    nodes:
      - e
  else:
    label: "No"
    nodes: []
e:
  kind: script
  label: Report
  alias: report
  lang: typescript
  code: |
    export async function main() {
      return { ok: true }
    }
onError:
  kind: script
  label: Notify
  alias: notify
  lang: python
  code: |
    def main(message: str = "", step: str = ""):
        print(f"{step} failed: {message}")
  • trigger é sempre o nó Início; os parameters dele são as entradas do flow e next indica o primeiro passo.
  • Todo outro passo ganha uma chave curta — a, b, … z, aa, ab — em ordem de largura a partir do Início. As chaves valem só dentro do arquivo e são refeitas toda vez que ele é escrito; o passo mantém o id real por trás, então execuções e vínculos continuam presos a ele.
  • alias é o nome usado nas expressões (nodes.loadOrders.output); ele é derivado do rótulo e aparece como referência.
  • onError (e preprocessor) são entradas de primeiro nível sem next — elas não ficam na cadeia.

Tipos de nó e os campos deles

kindCampos
scriptlang (python, typescript, javascript, c, cpp, postgresql, mysql), code num passo próprio ou script (o caminho) num vinculado, integration e rowLimit em SQL, dependencies em Python próprio.
conditionif, then: {label, nodes}, elseIfs: [{id, label, if, nodes}] opcional, else: {label, nodes}. nodes lista todo passo dentro daquele ramo.
loopiterate (um vínculo, uma lista ou uma expressão), mode: parallel + concurrency ou mode: while + maxIterations, breakIf, body (todo passo dentro).
parallelbranches: [{id, name, mayFail?, nodes}], sequential: true opcional.
flowflowRef (o id do filho — a referência de verdade) e flowName (uma dica legível, nunca lida de volta).
aiScraperscraper (id), scraperName (dica), timeoutMs opcional.
emailprovider (ausente = o padrão do projeto), template; destinatários e valores são inputs (to + um por valor do template).
approvalfields, approvers, timeoutSec, onTimeout, notify, allowLinks; a mensagem é inputs.message. Valores padrão são omitidos.
YAMLfragment.flow.yaml
c:
  kind: parallel
  label: Fan out
  branches:
    - id: b1x9k2
      name: Send e-mail
      nodes: [d]
    - id: b7qq01
      name: Notify team
      mayFail: true
      nodes: [e]
  next: f
m:
  kind: flow
  label: Enrich customer
  flowRef: 5f0e8a3c-2b7d-4e19-8c55-1a2b3c4d5e6f
  flowName: Enrich customer
  inputs:
    customerId: { from: a, path: id }
    retries: { manual: "3" }
    apiKey: { var: CRM_API_KEY }
  next: n

Qualquer passo executável também pode trazer as configurações de execução com os mesmos nomes do passo — retry, continueOnError, skipIf, stopIf, sleepAfterSec, cacheTtlSec, timeoutMs — e uma note curta. O que está desligado simplesmente não aparece, então um flow sem configurações não tem nenhuma dessas chaves.

Formas de vínculo

FormaSignifica
{ from: a, path: rows.0.total }Um valor da saída do passo a, naquele caminho (sem path = a saída inteira). Dentro de um loop, from o loop com path: item.total lê o item atual.
{ manual: "42" }Uma constante, convertida para o tipo declarado do parâmetro.
{ var: NAME }Uma variável do projeto ou global, lida quando o passo roda.
{ expr: "vars.RETRIES * 2" }Uma expressão. O Ver arquivo hoje mostra isso como { manual: "__expr__:vars.RETRIES * 2" }; arquivos do Git e o servidor MCP escrevem expr.

Copiar, exportar e guardar no Git

  1. Exportar

    Abra o Ver arquivo, escolha YAML ou JSON e copie o texto. Esse texto é o flow inteiro; guarde, compartilhe, revise num pull request.

  2. Importar em outro flow

    Crie um flow vazio, abra o Ver arquivo dele, troque o texto pela cópia e clique em Salvar. Os passos ganham ids novos; scripts vinculados, conexões e flows filhos são referenciados por id, então precisam existir no projeto de destino.

  3. Guarde no Git

    Com o projeto conectado a um repositório (Git), cada flow é um arquivo <pasta>/<nome>.flow.yaml no mesmo formato. Um commit grava o flow; um pull traz o arquivo como rascunho do flow — nunca publicado — para você revisar e publicar.

Arquivos do Git diferem do Ver arquivo em pequenos pontos: expressões são escritas { expr: … }, constantes mantêm o tipo JSON, rótulos padrão de ramo e alias ficam de fora, e o arquivo é validado ao ser lido — uma chave ou tipo desconhecido, um if ou iterate faltando, ou um passo que nenhum caminho alcança é apontado em vez de adivinhado.

O que o arquivo não guarda

  • Nada de posições, cores ou zoom: o layout é sempre derivado.
  • Nenhuma versão fixada num passo flow ou aiScraper: quem chama sempre roda a versão publicada mais recente.
  • Não as configurações do próprio flow — tempo limite, limite de concorrência, gatilhos e estado ficam fora da definição.