Skip to content

Formulários

Formulários são as telas de entrada de dados que a plataforma exibe dentro de uma tarefa, ou antes de iniciar uma instância. Cada tarefa de um processo pode ter um formulário diferente, com campos e regras específicos para aquela etapa.

Esta página cobre três coisas, nesta ordem: preencher um formulário, montar um no construtor visual e substituir o formulário da plataforma por um plugin próprio.

Como preencher um formulário (visão do usuário)

  1. Abra uma tarefa (em Tarefas, na barra lateral)
  2. O formulário da tarefa é exibido automaticamente dentro do painel da tarefa
  3. Preencha os campos conforme as instruções — campos obrigatórios estão marcados com *
  4. Clique em Enviar para concluir a tarefa; as respostas viram variáveis de processo automaticamente

TIP

A versão do formulário exibida é a que estava publicada no momento em que a tarefa foi criada. Atualizações posteriores no formulário não afetam tarefas já abertas.

Construtor visual de formulários (admin)

Administradores criam e editam formulários dentro da definição do processo, em Modelagem → Catálogo de Processos → o processo → aba Formulários, usando o construtor visual drag & drop. A barra lateral não traz um item Formulários: o formulário pertence ao processo que o usa.

Interface do construtor

O construtor tem três painéis:

PainelFunção
Esquerda — PaletaTipos de campo agrupados por categoria; clique para adicionar ao formulário
Centro — Canvas / Pré-visualizaçãoLista de campos em ordem; arraste para reordenar; aba "Pré-visualização" mostra a renderização real
Direita — PropriedadesConfigurações do campo selecionado

Tipos de campo disponíveis

GrupoTipoDescrição
TextotextTexto curto livre
TextotextareaTexto longo multilinha
TextoemailEndereço de e-mail (validação automática)
TextophoneTelefone
TextourlEndereço web (URL)
TextopasswordCredencial digitada na tarefa — ver Campo de senha, abaixo
NumériconumberValor numérico
NuméricocurrencyValor monetário (R$)
NuméricopercentagePercentual (%)
NuméricosliderValor numérico escolhido numa régua
Data/HoradateSeletor de data
Data/HoradatetimeSeletor de data e hora
Data/HoratimeSeletor de horário
Data/Horadate-rangeIntervalo de datas (data inicial e final)
Documentos BRcpfCPF (máscara automática)
Documentos BRcnpjCNPJ (máscara automática)
Documentos BRcepCEP (máscara automática)
EscolhaselectDropdown com opções fixas
EscolhamultiselectSeleção múltipla
EscolharadioOpções únicas (radio buttons)
EscolhacheckboxMúltiplos checkboxes
EscolhabooleanSim / Não
EscolhaswitchLiga/desliga em forma de interruptor
BuscalookupBusca paginada em API externa (digitação live)
ArquivofileUpload de arquivo (configurável: tipos aceitos, múltiplos)
AvaliaçãoratingAvaliação por estrelas — 5 por padrão, configurável até 10
LayoutheadingTítulo de seção (H2/H3/H4)
LayoutseparatorSeparador horizontal
Layoutmd-viewerExibe conteúdo em Markdown — não coleta dado

Campo de senha

O tipo Senha existe para credencial que a pessoa digita durante o processo. Ele muda quatro coisas em relação a um campo de texto comum:

  • é exibido mascarado, e o navegador não guarda o valor em preenchimento automático;
  • o valor não aparece nas telas que mostram variáveis do processo — nem na instância, nem nas variáveis da tarefa, nem na busca;
  • o valor não chega à IA: um agente que leia aquele processo recebe o identificador do campo, não o conteúdo;
  • o valor é gravado cifrado, deixa de existir entre as variáveis da instância quando ela termina, e é apagado do histórico sete dias depois.

O tipo é a marca

Um campo de texto chamado senha não ganha nada disso. A plataforma não adivinha pelo nome — adivinhar erra nos dois sentidos, deixando passar credencialErp e escondendo senhaDoWifiDaSala. Escolha o tipo Senha.

Como o valor é guardado

Em uma frase: a senha é gravada cifrada, deixa de existir entre as variáveis da instância quando ela termina, e é apagada do histórico sete dias depois — prazo que quem administra a instalação pode alterar. O passo seguinte do processo continua lendo o valor normalmente: um ${senhaErp} numa configuração de tarefa de serviço funciona como sempre funcionou; quem vê a senha em claro é só o motor, no momento em que ela é usada.

O que a cifra não resolve

A chave que cifra é a mesma chave da instalação (APP_ENCRYPTION_KEY). Ela protege contra um dump do banco, uma réplica ou um backup que vaze — não contra alguém que já tenha a chave da aplicação. Guarde essa chave com o mesmo cuidado que guardaria as senhas.

Uma senha só é gravada cifrada quando o campo é do tipo Senha. Se um passo do processo gravar aquela variável de novo por conta própria, o valor volta a ser texto comum — quem modela precisa saber disso.

O corpo do formulário não vai para o log

O registro de requisições da plataforma nunca escreve o corpo enviado por um formulário, em nenhuma rota, nem quando o envio falha. Um erro de validação continua aparecendo no log com método, caminho, status e a resposta que explica o problema — mas sem o que foi digitado.

Propriedades gerais de cada campo

PropriedadeDescrição
RótuloTexto exibido acima do campo
Chave (key)Identificador único — vira o nome da variável de processo ao submeter
TipoTipo de campo (veja tabela acima)
Largura100% / ½ / ⅓ / ¼ — controla a coluna no grid responsivo
ObrigatórioMarca o campo como obrigatório na validação
PlaceholderTexto de exemplo dentro do input
Instrução / AjudaTexto descritivo exibido abaixo do rótulo

Grid responsivo

O formulário usa CSS Grid com até 4 colunas. A propriedade Largura de cada campo define quantas colunas ele ocupa:

LarguraColunasVisual
fulllinha inteiraOcupa toda a largura
half2/4Metade da linha
third1/3Um terço da linha
quarter1/4Um quarto da linha

Em telas pequenas (mobile), todos os campos ocupam a largura total independentemente da configuração.

Regras condicionais

Cada campo pode ter uma ou mais regras condicionais configuradas no painel de propriedades. Uma regra define:

PropriedadeDescrição
AçãoO que acontece quando a condição é verdadeira
Campo observadoQual outro campo é monitorado
OperadorComo comparar o valor (=, , contém, vazio, não vazio, >, <)
ValorValor a comparar (não necessário para vazio/não vazio)

Ações disponíveis

AçãoEfeito
Mostrar este campoCampo fica visível quando a condição for verdadeira (padrão: oculto)
Ocultar este campoCampo fica oculto quando a condição for verdadeira
Habilitar este campoCampo fica editável quando a condição for verdadeira
Desabilitar este campoCampo fica bloqueado quando a condição for verdadeira
Tornar obrigatórioCampo vira obrigatório quando a condição for verdadeira
Carregar opções de APIDisponível apenas para campos de escolha (select, multiselect, radio, checkbox). Carrega as opções a partir de uma URL, substituindo {value} pelo valor do campo observado

WARNING

Se um campo tiver regra Tornar obrigatório, o checkbox estático "Obrigatório" fica desabilitado — quem controla a obrigatoriedade são as regras.

Validações

Além da obrigatoriedade, cada campo suporta validações específicas por tipo:

Tipo do campoValidações disponíveis
Texto curto (text), Texto longo (textarea)Regex personalizado com mensagem; Mínimo/máximo de caracteres
E-mail (email), Telefone (phone), URL (url)Mínimo/máximo de caracteres
Número (number), Moeda (currency), Percentual (percentage)Valor mínimo e máximo
Data (date), Data e Hora (datetime), Horário (time), Intervalo de Datas (date-range)Data mínima e máxima
CPF, CNPJ, CEP— formato fixo, sem validações adicionais configuráveis
Seleção, Avaliação, Arquivo, Busca, etc.— não possuem validações configuráveis

TIP

Campos com formato fixo como CPF (000.000.000-00), CNPJ (00.000.000/0000-00) e CEP (00000-000) já aplicam a máscara automaticamente. Não é necessário configurar regex ou comprimento para eles.

Onde a obrigatoriedade é conferida

Ao concluir uma tarefa, os campos obrigatórios são conferidos também no servidor — não só na tela. Quem chama a API direto (integração, script, chave de API) recebe 400 e a tarefa continua aberta se faltar um obrigatório; antes, uma chamada direta com o corpo vazio concluía a tarefa e a etapa seguinte recebia as variáveis em branco.

A conferência usa a versão do formulário travada na criação da tarefa — a mesma que a pessoa viu — e segue as regras condicionais: um campo escondido por uma regra não é cobrado. Um campo que só existe para exibir (título, separador, visualizador markdown) também não.

O que a conferência cobra é presença: o campo obrigatório precisa ter valor. Um obrigatório enviado só com espaços conta como vazio.

O que ainda é só do navegador

As variáveis do formulário de início — tanto de um processo quanto de um caso — e as validações de formato, tamanho e faixa (regex, mínimo/máximo de caracteres, valor mínimo e máximo, datas) continuam sendo verificadas apenas na tela.

Salvar rascunho também não passa pela conferência, e isso é de propósito: um rascunho existe justamente para guardar o formulário pela metade.

Intervalo de Datas (date-range)

O campo date-range exibe dois seletores de data — inicial e final — em linha. O valor salvo é um objeto { start: "YYYY-MM-DD", end: "YYYY-MM-DD" }. Validação automática garante que a data inicial seja anterior ou igual à data final.

Datas preenchidas não mudam com o fuso horário

Uma data que você digita num formulário — vencimento, competência, emissão — é gravada exatamente como escrita e aparece igual para todo mundo, independentemente de onde a pessoa esteja. Um vencimento em 06/08 é 06/08 para quem acessa de Manaus, de Recife ou de Lisboa.

Isso vale também para os campos de data do CMS e para variáveis de processo do tipo Data.

É diferente dos horários de registro — quando algo foi criado, executado ou concluído. Esses marcam um instante real e são exibidos no fuso de quem está lendo, porque a pergunta ali é "que horas eram para mim quando isso aconteceu".

Gatilhos de campo (preenchimento automático)

Um campo pode ter gatilhos: ao sair (blur) ou ao entrar (focus) no campo, a plataforma chama uma URL e roda um pequeno script que distribui a resposta pelos outros campos. O caso clássico é o CEP: sai do campo, consulta o serviço de endereços, preenche rua, bairro e cidade.

O script recebe três coisas e nada mais:

NomeO que é
responseO corpo JSON que a URL respondeu
valueO valor atual do campo que disparou o gatilho
set(chave, valor)Preenche outro campo do formulário

O script roda isolado — e isso limita o que ele pode fazer

O script é executado fora da página, num contexto próprio sem window, sem document, sem localStorage e sem rede. Ele não consegue fazer chamadas HTTP por conta própria: a única chamada é a da URL configurada no gatilho, feita pela plataforma antes do script rodar. Um script escrito para usar fetch, cookies ou qualquer API do navegador vai falhar.

Além disso:

  • o script tem 2 segundos para terminar; passou disso, é interrompido — laço infinito não trava a aba;
  • a URL do gatilho precisa ser http:// ou https://;
  • quando alguma coisa falha — a URL responde erro, a resposta não é JSON, o script quebra ou estoura o tempo — aparece "Não foi possível executar o preenchimento automático deste campo." logo abaixo do campo, e o detalhe vai para o console do navegador. Antes, a falha era silenciosa: o campo simplesmente não era preenchido e ninguém ficava sabendo.

Visualizador Markdown (md-viewer)

O campo ✨ Visualizador Markdown (grupo Layout & Display da paleta) exibe texto formatado em Markdown dentro do formulário. É o campo indicado para mostrar o parecer de um agente de IA na tarefa, já com títulos, listas, negrito e tabelas renderizados.

Ele não coleta dado nenhum — só exibe.

Como ligar ao parecer da IA

O campo lê a variável de processo de mesmo nome da sua chave. Se o agente grava o parecer na variável parecerIa:

  1. Adicione o campo Visualizador Markdown ao formulário
  2. Em Propriedades, defina a Chave (key) como parecerIa
  3. O Rótulo é o título exibido acima do quadro (ex.: "Parecer da IA")

Quando a tarefa abrir, o conteúdo da variável aparece renderizado. Se a variável ainda não existir, o campo mostra (vazio) em vez de ficar em branco — útil para perceber que o agente ainda não respondeu.

Campos de exibição não são enviados

Visualizador Markdown, Título de seção e Separador existem só para exibir, então não vão no envio da tarefa nem no salvamento de rascunho. Isso evita que o formulário regrave por cima da variável: se o agente atualizar o parecer enquanto a tarefa está aberta, a versão nova é preservada.

Busca paginada (Lookup)

O campo lookup faz requisições à medida que o usuário digita (mínimo de 2 caracteres). Configure:

PropriedadeDescrição
URLEndpoint com {search} que será substituído pelo texto digitado
Campo labelPropriedade do JSON de resposta a exibir como texto
Campo valorPropriedade do JSON de resposta a usar como valor salvo

Exemplo de URL: https://api.empresa.com/clientes?q={search}

Versionamento de formulários

Todo formulário é versionado automaticamente. A cada salvamento, uma nova versão imutável é criada.

Publicar uma versão

  1. Abra o formulário pela aba Formulários da definição do processo
  2. Clique na aba 🕑 Histórico
  3. Localize a versão desejada e clique em Publicar
  4. A versão publicada aparece com a etiqueta ✓ Publicada

O editor do formulário tem três abas — 🎨 Construtor visual, </> JSON e 🕑 Histórico — e o botão Salvar nova versão no alto. Cada salvamento cria uma versão nova; publicar é um passo à parte.

Comportamento de versão em tarefas

  • Quando uma tarefa é criada em um processo, o sistema trava automaticamente a versão publicada do formulário naquela tarefa
  • Se nenhuma versão foi publicada explicitamente, a versão mais recente é usada
  • Publicações futuras não afetam tarefas já criadas — cada tarefa sempre exibe o formulário com o schema que tinha no momento de sua criação
  • As respostas submetidas viram variáveis de processo

Restaurar uma versão no editor

Na aba 🕑 Histórico, clique em Restaurar para carregar uma versão antiga no construtor visual. Isso não altera o formulário — é preciso clicar em Salvar nova versão para que ela passe a existir.

Formulários standalone

Além de formulários vinculados a tarefas, o sistema pode ter formulários avulsos para coleta de dados ou início de processos. Eles ficam na mesma aba Formulários da definição.

O formulário de início é o que a tela de iniciar processo abre antes de criar a instância. Ele vem do Form Key do evento de início, em um processo BPMN, e do Form Key do plano do caso — o retângulo externo do desenho — em um caso CMMN. Nos dois, o formulário precisa existir na definição antes do deploy, senão o deploy é recusado com "Formulário referenciado não existe no ambiente do processo".

Micro-Frontend Plugins (Formulários Externos)

Para casos de uso muito complexos que a ferramenta Low-Code do construtor visual não atenda (ex: renderizações pesadas em 3D, drag and drop de arquivos avançado customizado, integrações de socket ao vivo), o Flow.IA suporta Remote Form Plugins.

Como Funciona: Você pode desenvolver um projeto React/Vite isolado, seguindo a nossa estrutura recomendada (custom-form-boilerplate), fazer o build do componente form e expor essa URL num servidor estático (S3, Vercel, Nginx).

Há um par de exemplos no repositório: samples/custom-form-boilerplate é o plugin, e samples/external-form é um processo BPMN mínimo que o usa — com o passo a passo de servir o bundle, publicar a definição e iniciar a instância. Rodar os dois juntos é o teste mais rápido de que o caminho inteiro está de pé.

Como Configurar:

  1. Abra o Modelador BPMN/CMMN.
  2. Acesse as propriedades do elemento: a tarefa de usuário (User Task) ou o evento de início (Start Event), no BPMN; a tarefa humana ou o plano do caso, no CMMN.
  3. No campo Form Key (ou Start Form Key), insira diretamente a URL do Plugin (ex: http://localhost:3001/assets/plugin.js).
  4. Quando o usuário abrir a Tarefa ou Processo que possua uma formKey iniciada com http:// ou https://, o Flow.IA automaticamente reconhecerá como um plugin externo. Ele vai baixar assincronamente o bundle e injetar a interface diretamente na tela, passando variáveis de contexto via props. Não é necessário salvar um schema local no construtor de formulários.

O build do plugin precisa sair como UMD com React externo

O bundle é carregado por uma tag <script> e tem de publicar o componente em window.CustomFlowiForm. A plataforma expõe React, ReactDOM, MUI, EmotionReact e EmotionStyled como globais, e o projeto do plugin marca esses pacotes como external para usá-los — dois Reacts na mesma página quebram os hooks.

Uma armadilha específica, e o boilerplate já vem configurado para evitá-la: o runtime automático de JSX importa de react/jsx-runtime, que é um especificador diferente de react e por isso escapa da lista de external. Ele entra no bundle na forma CommonJS, começando por require("react"), e o script inteiro morre no navegador com require is not defined — sem mensagem na tela além de "Componente customizado não encontrado no script". Por isso o vite.config.ts do boilerplate usa jsxRuntime: 'classic' e externaliza react por expressão regular.

As variáveis chegam antes de o formulário montar

A plataforma só monta o plugin depois de ter as variáveis do processo em mãos, e mostra um indicador de carregamento nesse intervalo. Isso importa porque defaultValues do React Hook Form é lido uma única vez, na montagem: se as props mudassem depois, o formulário nasceria vazio e ignoraria os valores que chegaram atrasados.

Boilerplate e Validação (React Hook Form + Zod)

O projeto base recomendado (custom-form-boilerplate) já vem pré-configurado com as melhores práticas de mercado utilizando React Hook Form e Zod. Ele implementa a mesma arquitetura lógica do construtor visual nativo do Flow.IA, garantindo estabilidade na injeção e extração de dados:

  • Injeção de variáveis (defaultValues): O Flow.IA entrega as variáveis do processo atual através da prop initialVariables. O formulário injeta esses dados nativamente usando o defaultValues do React Hook Form.
  • Validação tipada (Schema Zod): Regras complexas de formulário são definidas via código (z.object({...})), garantindo total Type Safety e bloqueando o envio se os dados estiverem inconsistentes.
  • Salvamento Parcial e Conclusão (onSave e onComplete): Ao salvar o rascunho (chamando a prop onSave injetada), a validação rígida do Zod pode ser ignorada, capturando os dados atuais com getValues(). Mas ao avançar a tarefa (onComplete), os dados são validados pelo schema e empacotados no exato formato esperado pelo motor de processos.

Flowi Agentic — Plataforma de Gestão de Processos com IA