Platform

Triggers

A trigger is what starts a flow. Each flow declares a single trigger type — the door through which something in the real world asks the flow to run. Daguito has ten types, each with its own data contract.

What is a trigger?

A trigger is the source of an inbound event. It does no work: it just receives the signal (a message, a webhook, a clock tick) and hands the engine a normalized input so the flow can start running.

The types live as a typed const array (CANONICAL_TRIGGER_TYPES), never as loose string literals — so a flow can only declare a valid trigger.

// Canonical trigger types — apps/api/src/flows/architecture.ts
const CANONICAL_TRIGGER_TYPES = [
  'message',         // inbound message from a channel
  'media',           // image / audio / document / video file
  'stream',          // real-time voice turn
  'webhook',         // external HTTP POST
  'schedule',        // cron / scheduled
  'manual',          // manual run from the dashboard or API
  'flow_completed',  // another flow finished
  'record',          // data record change (reserved)
  'timeout',         // a wait expired
  'event_delayed',   // delayed business event (abandoned cart, reminder)
] as const

The ten types

Grouped by how they fire:

From a conversation

From an external system

From time and the engine itself

Reserved

record is defined in the model (a change to a data record: an insert or update) but does not yet have an adapter. It is reserved for a future release; today it cannot be declared in production.

Data contract

Every trigger hands a typed object to the engine. Here is what your flow receives depending on the trigger it declares:

message        → { text, sender, channel, session_key, metadata }
media          → { file_url, mime_type, size, sender, channel, session_key }
stream         → { stream_id, codec, sample_rate, session_key }
webhook        → { method, headers, body, source }
schedule       → { cron, last_run, scheduled_at }
manual         → { triggered_by, params }
flow_completed → { source_flow_id, execution_id, status, output }
record         → { table, action, record, old_record }   // reserved
timeout        → { node_id, wait_key, resume_at, reason }
event_delayed  → { watch_event, delay_minutes, cancel_events, payload_filter? }

Channels and triggers

A channel is not the same as a trigger. The channel is the source (WhatsApp, Instagram, the widget, a webhook); the trigger is the event type that starts the flow. Several channels can produce the same trigger: a widget message and a WhatsApp message both arrive as message.

Each channel connects to its trigger through an adapter, which normalizes the platform-specific payload into an InboundMessage before handing it to the unified ingest pipeline. That way the engine never has to know where the event came from.

What's next?