Skip to content
Menú Academia

El ciclo de vida de formularios desde la CLI: crear, configurar, enviar, transicionar

Crea un formulario de punta a punta — estados de workflow, audiencias de permisos, enrutamiento de aprobación, lógica de preguntas — y luego lleva su ciclo de vida completo de respuestas desde la CLI o la API, incluyendo botones callback_form.

deep-diveDesarrolladorOps12 min read

Los formularios en Dailybot no son solo un recolector de respuestas — llevan estados de workflow, tres audiencias de permisos independientes, enrutamiento de aprobación, y un atajo de ChatOps, y cada una de esas superficies es scripteable de punta a punta. Este recorrido construye un formulario desde cero, arma su ciclo de vida, y lleva respuestas a través de él — más el detalle que conecta los formularios de vuelta con la mensajería: los botones callback_form.

Crear un formulario: de una sola vez vs. incremental

Un formulario necesita un nombre y al menos una preguntacreate con un conjunto de preguntas vacío falla con 400 questions_required. Dos estilos de autoría, el mismo vocabulario 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 es una actualización parcial completa: envía solo los flags que quieres cambiar, todo lo demás se mantiene igual. Es un superconjunto estricto de form edit (solo nombre + canales de reporte) — prefiere config para cualquier cosa más allá de eso.

Estados de workflow — forma de escritura vs. forma de lectura

dailybot form config "$FID" \
  --state "Draft:#9CA3AF" --state "Review:#F59E0B" --state "Released:#10B981"

# Turn the workflow off entirely
dailybot form config "$FID" --no-workflow

Escribes {label, color} por estado, ordenados por posición del flag — el servidor deriva key (etiqueta en slug) y order (posición) por ti. form get devuelve cada estado como {key, label, color, order} dentro de workflow.states, más workflow.enabled: true. Pasar cualquier flag --state habilita el workflow; habilitarlo con cero estados es inválido (workflow_requires_states); máximo 20 estados.

Audiencias de permisos — tres controles independientes

--can-edit, --can-see, y --can-change-states son independientes, cada uno con valor 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"

Pasar un flag --change-states-user/-team implica restricted para esa audiencia automáticamente. Cada audiencia es de reemplazo completo — los usuarios/equipos que envías se convierten en el conjunto nuevo completo; una audiencia restricted con listas vacías significa “solo el dueño + admins.”

Enrutamiento de aprobación y el comando de ChatOps

dailybot form config "$FID" \
  --approval --approver-team "Release Managers" --approver-user [email protected] \
  --command release

Los envíos nuevos se enrutan a través de la lista de aprobadores (reemplazo completo; --no-approvers la limpia, --no-approval deshabilita el enrutamiento) antes de contar como finales. --command release vincula @dailybot release como un atajo de ChatOps que abre este formulario — el charset del comando es [a-z0-9][a-z0-9_-]{0,30}, único por organización (command_already_exists si ya está tomado); --no-command lo desvincula.

Formularios públicos

dailybot form create -n "Q3 NPS Survey" \
  --anonymous --public --brand --require-identity \
  --report-channel "$SURVEYS_CHANNEL_UUID" --questions-file nps.json

--public expone una public_url (https://app.dailybot.com/forms/<uuid>/responses/create/) que cualquiera puede abrir sin una cuenta de Dailybot; null cuando está apagado. Combínalo con --require-identity para hacer obligatorios el email y nombre de quien envía, y --brand para mostrar el logo de la organización. A diferencia de la anonimidad de los check-ins, --anonymous en un formulario se puede alternar libremente en ambas direcciones.

Autoría de preguntas

El modelo de preguntas tiene exactamente cuatro tipos — text, multiple_choice (necesita --options "A,B,C"), boolean (sin opciones), 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 (el título del reporte, ≤ 512 caracteres) es obligatorio en add — pásalo explícitamente, o usa --ai-short-question para que el servidor genere uno. En edit, el título del reporte no es obligatorio (las ediciones son parciales). --variation agrega hasta 10 frases alternativas mostradas a distintos encuestados.

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

El objeto completo (lo que acepta --logic-file, y lo que construyen los flags en línea):

{
  "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 es obligatorio; target: -1 significa “saltar al final.” Los saltos son solo hacia adelante — el objetivo debe superar el índice de la pregunta actual, o ser -1. Las acciones son jump_to (índice de pregunta), trigger_checkin (un UUID de check-in), o trigger_form (encadenar a otro formulario por completo — útil para enrutar una respuesta “Hotfix” a un formulario de intake dedicado). Borrar o reordenar preguntas ajusta automáticamente cualquier objetivo de salto que quede colgando.

# Reorder — pass the COMPLETE set of question UUIDs, in the new order
dailybot form questions reorder "$FID" "$Q3" "$Q1" "$Q2"

Leer el vocabulario del ciclo de vida

Cada respuesta en un formulario con workflow habilitado lleva cinco campos — nunca infieras una transición a partir de una etiqueta, siempre lee allowed_transitions:

Campo Significado
current_state El estado efectivo de la respuesta ahora mismo
allowed_transitions [{to_state, label}] — movimientos que este llamante puede hacer, calculados por el servidor
can_change_state Si quien llama está en la audiencia de cambio de estado
allow_reopen_from_final_state Si un estado terminal es reversible
state_history Log de solo-agregar {from_state, to_state, actor_name, at}

Enviar, actualizar, transicionar

# 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 oculta al remitente por completo en las notificaciones del canal; --anonymous lo reemplaza con un nombre generado al azar; combinados, automation gana para la notificación. Ninguno afecta quién es dueño de la respuesta. transition acepta la key de máquina to_state o la etiqueta label de visualización (sin distinción de mayúsculas, resuelta automáticamente) de la propia allowed_transitions de esa respuesta — nunca un estado que simplemente esperas que exista. Las actualizaciones son estrictamente solo-propias del lado del servidor, incluso para admins (form_response_not_found en caso contrario, no una fuga de permisos).

Conectar la mensajería con los formularios: callback_form

Un botón de send-message con callback_form abre exactamente este formulario para el usuario que hizo clic, a través de la UI normal de formularios — sin request externo, sin reenvío de payload, sin saltarse el ciclo de vida de arriba:

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 recibe solo el UUID del formulario (listado vía dailybot form list --json) — nombres y slugs se rechazan. Un formulario desconocido o archivado devuelve 400 button_callback_form_not_found. Una vez abierto, todo lo de arriba — tipos de pregunta, lógica condicional, estados de workflow, transiciones — aplica exactamente igual que si el usuario hubiera abierto el formulario directamente.

Referencias cruzadas

Explora el hub de Soluciones para el recorrido orientado a producto del ciclo de vida de formularios.

FAQ

¿Qué es lo mínimo necesario para crear un formulario?
Un nombre y al menos una pregunta. dailybot form create -n NAME sin preguntas falla rápido con 400 questions_required — siembra al menos una pregunta en línea vía --questions-file o --interactive, o agrega una inmediatamente después vía form questions add.
¿Cómo funcionan los estados de workflow de un formulario?
Pasa uno o más flags --state "Label:#color" en create o config — pasar cualquier flag --state habilita el workflow, y el orden de los flags define la secuencia de estados. El servidor deriva una key en slug y un order numérico por ti; tú solo escribes {label, color}. --no-workflow limpia los estados y apaga el workflow.
¿En qué se diferencia un botón callback_form de enviar un formulario desde la CLI?
callback_form es un campo de un botón de send-message que abre un formulario interno de Dailybot para que el usuario que hizo clic lo llene a través de la UI normal de formularios — sin request externo, sin reenvío de payload. Conecta la mensajería con el propio ciclo de vida de un formulario existente en lugar de prellenarlo o saltárselo.
¿Cómo muevo una respuesta de formulario entre estados de workflow?
dailybot form transition <form_uuid> <response_uuid> <to_state> --yes, donde to_state puede ser la key de máquina o la etiqueta de visualización de la propia lista allowed_transitions de esa respuesta — nunca un nombre de estado que asumas que debería estar disponible.
¿Cuál es la diferencia entre form config y form edit?
form config es un superconjunto de actualización parcial completo que cubre nombre, estados de workflow, las tres audiencias de permisos, enrutamiento de aprobación, y el comando de ChatOps — envía solo los flags que quieres cambiar. form edit solo toca el nombre y los canales de reporte; prefiere form config para cualquier cosa más allá de eso.