O ciclo de vida de formulários pela CLI: criar, configurar, enviar, transicionar
Crie um formulário de ponta a ponta — estados de workflow, audiências de permissão, roteamento de aprovação, lógica de perguntas — depois conduza todo o ciclo de vida das suas respostas pela CLI ou API, incluindo botões callback_form.
Formulários no Dailybot não são apenas um coletor de respostas — eles carregam estados de workflow, três audiências de permissão independentes, roteamento de aprovação e um atalho de ChatOps, e cada uma dessas superfícies é programável de ponta a ponta. Este passo a passo constrói um formulário do zero, conecta seu ciclo de vida e conduz respostas por ele — além do detalhe que conecta formulários de volta ao envio de mensagens: os botões callback_form.
Criando um formulário: tudo de uma vez vs. incremental
Um formulário precisa de um nome e pelo menos uma pergunta — create com um conjunto de perguntas vazio falha com 400 questions_required. Dois estilos de autoria, mesmo vocabulário de flags:
# One-shot: everything in a single call
FID=$(dailybot form create -n "Code Release Form" --active \
--state "Draft:#9CA3AF" --state "Review:#F59E0B" --state "Released:#10B981" \
--report-channel "$RELEASES_CHANNEL_UUID" \
--approval --approver-team "Release Managers" \
--command release \
--questions-file q.json --json | jq -r '.uuid')
# Incremental: create bare, then shape it
dailybot form create -n "Code Release Form" --questions-file q.json --json
dailybot form config "$FID" --state "Draft:#9CA3AF" --state "Review:#F59E0B"
form config é uma atualização parcial completa: envie apenas as flags que quer mudar, e o resto permanece como está. É um superset estrito de form edit (apenas nome + canais de relatório) — prefira config para qualquer coisa além disso.
Estados de workflow — forma de escrita vs. forma de leitura
dailybot form config "$FID" \
--state "Draft:#9CA3AF" --state "Review:#F59E0B" --state "Released:#10B981"
# Turn the workflow off entirely
dailybot form config "$FID" --no-workflow
Você escreve {label, color} por estado, ordenado pela posição da flag — o servidor deriva key (rótulo slugificado) e order (posição) para você. form get retorna cada estado como {key, label, color, order} dentro de workflow.states, mais workflow.enabled: true. Passar qualquer flag --state habilita o workflow; habilitá-lo com zero estados é inválido (workflow_requires_states); máximo de 20 estados.
Audiências de permissão — três controles independentes
--can-edit, --can-see e --can-change-states são independentes, cada uma sendo everyone / owner_and_admins / restricted:
dailybot form config "$FID" \
--can-see everyone \
--can-edit owner_and_admins \
--change-states-user [email protected] \
--change-states-team "Release Managers"
Passar uma flag --change-states-user/-team implica restricted para aquela audiência automaticamente. Cada audiência é substituição completa: os usuários/equipes que você envia se tornam o conjunto novo inteiro; uma audiência restricted com listas vazias significa “somente owner + admins.”
Roteamento de aprovação e o comando de ChatOps
dailybot form config "$FID" \
--approval --approver-team "Release Managers" --approver-user [email protected] \
--command release
Novos envios passam pela lista de aprovadores (substituição completa; --no-approvers a limpa, --no-approval desativa o roteamento) antes de contar como finais. --command release vincula @dailybot release como um atalho de ChatOps que abre este formulário — o charset do comando é [a-z0-9][a-z0-9_-]{0,30}, único por organização (command_already_exists se já estiver em uso); --no-command o desvincula.
Formulários públicos
dailybot form create -n "Q3 NPS Survey" \
--anonymous --public --brand --require-identity \
--report-channel "$SURVEYS_CHANNEL_UUID" --questions-file nps.json
--public expõe uma public_url (https://app.dailybot.com/forms/<uuid>/responses/create/) que qualquer pessoa pode abrir sem uma conta Dailybot; null quando desligado. Combine com --require-identity para tornar email + nome de quem envia obrigatórios, e --brand para exibir o logo da organização. Diferente do anonimato de check-ins, --anonymous em um formulário pode ser alternado livremente em ambas as direções.
Autoria de perguntas
O modelo de pergunta tem exatamente quatro tipos — text, multiple_choice (precisa de --options "A,B,C"), boolean (sem opções), numeric:
dailybot form questions add "$FID" --type text \
--question "Service name?" --short-question "Service" --required
dailybot form questions add "$FID" --type multiple_choice --options "Standard,Hotfix" \
--question "Release type?" --short-question "Type" --required
--short-question (o título do relatório, ≤ 512 caracteres) é obrigatório em add — passe-o explicitamente, ou --ai-short-question para deixar o servidor gerar um. Em edit, o título do relatório não é obrigatório (edições são parciais). --variation adiciona até 10 formas alternativas de fraseado mostradas a diferentes respondentes.
Lógica condicional
dailybot form questions add "$FID" \
--type multiple_choice --options "Yes,No" \
--question "Did all tests pass?" --short-question "Tests passed" \
--jump-if-equals "No" --jump-to 5 --else-jump-to 3
O objeto completo (o que --logic-file aceita, e o que as flags inline constroem):
{
"rules": {
"rules_if": [
{"conditions": [{"operator": "is_equal_to", "comparison_value": "No", "logic_connector": "and"}],
"then": {"action": "jump_to", "target": 5}}
],
"rules_else": {"action": "jump_to", "target": -1}
}
}
rules_else é obrigatório; target: -1 significa “pular para o final.” Os saltos são somente para frente — o alvo deve exceder o índice da pergunta atual, ou ser -1. As ações são jump_to (índice de pergunta), trigger_checkin (um UUID de check-in), ou trigger_form (encadear para outro formulário inteiro — útil para rotear uma resposta “Hotfix” para um formulário dedicado de intake de hotfix). Excluir ou reordenar perguntas ajusta automaticamente qualquer alvo de salto órfão.
# Reorder — pass the COMPLETE set of question UUIDs, in the new order
dailybot form questions reorder "$FID" "$Q3" "$Q1" "$Q2"
Lendo o vocabulário do ciclo de vida
Toda resposta em um formulário com workflow habilitado carrega cinco campos — nunca infira uma transição a partir de um rótulo, sempre leia allowed_transitions:
| Campo | Significado |
|---|---|
current_state |
O estado efetivo da resposta agora |
allowed_transitions |
[{to_state, label}] — movimentos que este chamador pode fazer, computados pelo servidor |
can_change_state |
Se o chamador está na audiência de mudança de estado |
allow_reopen_from_final_state |
Se um estado terminal é reversível |
state_history |
Log somente-append de {from_state, to_state, actor_name, at} |
Enviando, atualizando, transicionando
# Submit
dailybot form submit "$FID" --content '{"<q_summary>":"Auth service v2.1","<q_type>":"Standard"}' --yes
# Automation submission, no submitter shown, with provenance
dailybot form submit "$FID" --content '{"<q_summary>":"done"}' --yes --automation \
--guest-name "Release Bot" --guest-email "[email protected]" \
--source "workflow:production-deploy"
# Update an in-progress response (own responses only — never another user's)
dailybot form update "$FID" "$RID" --content '{"<q_summary>":"Auth service v2.1.1"}' --yes
# Transition once allowed_transitions is non-empty
dailybot form transition "$FID" "$RID" released --yes
--automation esconde o remetente por completo nas notificações de canal; --anonymous o substitui por um nome gerado aleatoriamente; combinados, automation prevalece para a notificação. Nenhum dos dois afeta quem é o dono da resposta. transition aceita tanto a chave técnica to_state quanto o label de exibição (sem diferenciar maiúsculas/minúsculas, resolvido automaticamente) da própria lista allowed_transitions daquela resposta — nunca um estado que você apenas espera que exista. As atualizações são estritamente próprias-apenas do lado do servidor, mesmo para admins (form_response_not_found caso contrário, e não um vazamento de permissão).
Conectando o envio de mensagens a formulários: callback_form
Um botão de send-message com callback_form abre exatamente este formulário para o usuário que clicou, através da UI normal de formulários — sem request externo, sem encaminhamento de payload, sem contornar o ciclo de vida acima:
curl -sS -X POST 'https://api.dailybot.com/v1/send-message/' \
-H 'X-API-KEY: $DAILYBOT_API_KEY' \
-H 'Content-Type: application/json' \
-d '{
"message": "Ready to log a release?",
"target_channels": ["C0123456789"],
"buttons": [
{"label": "Open release form", "button_type": "interactive", "value": "open_release_form",
"callback_form": "'"$FID"'"}
]
}'
callback_form aceita apenas o UUID do formulário (liste com dailybot form list --json) — nomes e slugs são rejeitados. Um formulário desconhecido ou arquivado retorna 400 button_callback_form_not_found. Uma vez aberto, tudo acima — tipos de pergunta, lógica condicional, estados de workflow, transições — se aplica exatamente como se o usuário tivesse aberto o formulário diretamente.
Referências cruzadas
- A API send-message, de ponta a ponta para o contrato completo de botões dentro do qual
callback_formvive. /pt/developers/api/messaging#send-messagepara a referência estruturada dos campos./pt/developers/clipara o grupo completo de comandosform.
Navegue pelo hub de Soluções para o passeio voltado ao produto do ciclo de vida de formulários.
FAQ
- Qual é o mínimo necessário para criar um formulário?
- Um nome e pelo menos uma pergunta. dailybot form create -n NAME sem perguntas falha rapidamente com 400 questions_required — semeie ao menos uma pergunta inline via --questions-file ou --interactive, ou adicione uma logo depois via form questions add.
- Como funcionam os estados de workflow de um formulário?
- Passe uma ou mais flags --state "Label:#color" em create ou config — passar qualquer flag --state habilita o workflow, e a ordem das flags define a sequência de estados. O servidor deriva uma chave slugificada e uma ordem numérica para você; você só escreve {label, color}. --no-workflow limpa os estados e desliga o workflow.
- Qual a diferença entre um botão callback_form e enviar um formulário pela CLI?
- callback_form é um campo em um botão de send-message que abre um formulário interno do Dailybot para o usuário que clicou preencher, através da UI normal de formulários — sem request externo, sem encaminhamento de payload. Ele conecta o envio de mensagens ao ciclo de vida de um formulário existente, em vez de pré-preenchê-lo ou contorná-lo.
- Como movo a resposta de um formulário entre estados de workflow?
- dailybot form transition <form_uuid> <response_uuid> <to_state> --yes, onde to_state pode ser tanto a chave técnica quanto o rótulo de exibição da própria lista allowed_transitions daquela resposta — nunca um nome de estado que você apenas supõe estar disponível.
- Qual a diferença entre form config e form edit?
- form config é um superset completo de atualização parcial cobrindo nome, estados de workflow, as três audiências de permissão, roteamento de aprovação e o comando de ChatOps — envie apenas as flags que quer alterar. form edit só altera o nome e os canais de relatório; prefira form config para qualquer coisa além disso.