Start with Triggers
Start a flow automatically by configuring a trigger source and mapping values into the flow’s inputs. An enabled source records events before publication, independently of execution. Ordinary dispatch runs the published live release. Development tests perform real actions and spend usage.
For Daily invoice digest, use workflow data with these development rows:
| Invoice ID | Amount | Review needed |
|---|---|---|
| INV-104 | 120 | false |
| INV-105 | 1500 | true |
| INV-106 | 600 | false |
Configure one digest at 09:00 America/Chicago. Create the docs-digest-test Slack channel and select its actual ID. Expect three invoices, one needing review, and exactly one message per run. An empty queue must produce one zero-item digest. Before live verification, separately import or copy live rows. Publishing copies no records.
Choose what starts the flow
Section titled “Choose what starts the flow”| Source | Configure | Deliver a sample |
|---|---|---|
| Schedule | Time and timezone | Wait for a scheduled firing. |
| Webhook | Generated endpoint | Send a request to the returned URL. |
| Generated inbound address | Send email to that address. | |
| App event | Discovered event, connection and settings | Produce the event; allow its polling interval when applicable. |
In the app: open Workflows → Daily invoice digest → flow → Triggers → Add new trigger. Choose the source/event, complete the settings, then choose Add Trigger. For schedules, choose Daily → Time → 09:00. There is no timezone picker. The timezone comes from the stored setting or your profile. To specify America/Chicago, use the assistant path.
With an assistant: list workflows to find the workflow’s ID.
cai workflow list --limit 100 --jsonNote its data.items[].id as <workflowId>. Only when data.hasMore is false can you trust a workflow’s absence. Otherwise, get the ID from the app or owner. Workflow-scoped MCP calls still need workflowId. Set CLI context with cai use, then find the flow and schedule identifiers.
cai use <workflowId> --jsoncai flow list --jsoncai trigger search "schedule" --jsonNote the flow’s data.items[].id as <flowId> and the schedule’s data.nodes[].slug and eventKeys[].key as <slug> and <eventKey>.
Inspect the schedule properties to find the values needed for creation.
cai trigger props --node <slug> --event <eventKey> --jsonMCP uses trigger_component_props with node and event.
Start with data.propsForCreate and leave hidden props unset. Create only when data.readyForCreate is true and required values are filled. Timezone priority is the explicit setting, your profile, then UTC. Create this schedule with the nested cron object to get its creation fields.
cai trigger create --flow <flowId> --node <slug> --event <eventKey> --source-basis explicit-in-request --props '{"cron":{"cron":"0 9 * * *","timezone":"America/Chicago"}}' --jsonKeep four creation fields under data as distinct placeholders. Use triggerId to control the canvas and backendTriggerId to list or replay events. Use triggerNodeId to select samples and runSubflowNodeId to map inputs.
MCP uses trigger_create with flow, node, event, sourceBasis and parsed props.
Creating a trigger provisions the source before saving the canvas. After STATE_CONFLICT or an uncertain result, inspect existing triggers and provider sources before retrying. Cleanup can fail. Another create can duplicate a source.
List triggers to see which already exist.
cai trigger list --jsonDoes another source need an account or options?
Section titled “Does another source need an account or options?”Use that source’s discovered <slug> and <eventKey>. Below, <nodeSlug> is the same slug. List connections and, if none fits, request a link to connect an account.
cai connection list --integration <slug> --jsoncai connection connect <nodeSlug> --no-open --jsonComplete the connection at data.url, list again, and note data.items[].id as <connectionId>.
MCP uses connection_list with integration and connection_connect_url with nodeSlug.
Inspect properties with that connection to get the creation values.
cai trigger props --node <slug> --event <eventKey> --connection <connectionId> --jsonSave data.propsForCreate as trigger-props.json and retain your chosen values. Keep the latest data.id as <dynamicPropsId>. Resolve each data.unresolvedOptionProps name as <name>. To find its options, replace <text> with the desired option label.
cai trigger options --node <slug> --event <eventKey> --connection <connectionId> --prop <name> --configured trigger-props.json --dynamic-props-id <dynamicPropsId> --query '<text>' --jsonMCP uses trigger_prop_options with parsed configured and dynamicPropsId.
To browse options, replace --query '<text>' with --page 0. On subsequent zero-based pages, pass the returned data.context as --prev-context. MCP uses page and parsed prevContext. Merge the exact data.options[].value into the file. Reload the properties to check whether the trigger is ready for creation.
cai trigger props --node <slug> --event <eventKey> --connection <connectionId> --configured trigger-props.json --dynamic-props-id <dynamicPropsId> --jsonWhen readyForCreate is true and required values are filled, create this alternative. According to the source choice, use <basis> as explicit-in-request, user-answer, or inferred-from-existing-workflow. Omit unnecessary connection/dynamic-ID flags. Create the alternative source to get its creation IDs.
cai trigger create --flow <flowId> --node <slug> --event <eventKey> --source-basis <basis> --connection <connectionId> --props trigger-props.json --dynamic-props-id <dynamicPropsId> --jsonKeep these creation IDs separate.
Capture a sample and map the inputs
Section titled “Capture a sample and map the inputs”List captured events to find a sample.
cai trigger events --trigger <backendTriggerId> --limit 50 --jsonNote the original sample’s data.events[].id as <eventId>. The default is the five newest events. The maximum is 50. Capture needs neither publication nor development permission. If nothing arrives, inspect source settings, destination and capture.sourceEnabled from trigger get. A disabled source captures nothing.
MCP uses trigger_event_list with backend triggerId. In MCP inputs, that ID and every captured-event ID are numeric strings.
Inspect the trigger and event, then select the sample to access its fields.
cai trigger get <triggerId> --jsoncai trigger event <eventId> --jsoncai trigger select-event --node <triggerNodeId> --event <eventId> --jsonIf dataTypeName or its schema is unavailable, wait and select the same event again. Write field expressions only after expression context exposes them.
MCP uses trigger_get with canvas triggerId, trigger_event_get with eventId, and trigger_event_select with triggerNodeId and eventId.
In the app: open the trigger canvas for Webhook URL, Email address, and Sample event → View. For schedules, use the assistant path because the sample picker is hidden. Open the flow’s Inputs → Add new input and add Schedule as text. In the trigger’s Run flow node, set it to 09:00 America/Chicago. This example supplies a label explicitly. It assumes no schedule payload field.
With an assistant: use data.runSubflowNodeId as <nodeId> below. If absent, add the input. Inspect its mapping property and expression context.
cai flow input add <flowId> --display "Schedule" --type text --jsoncai node props <nodeId> --jsoncai expr context <nodeId> --jsonKeep the Schedule property’s returned name as <name>. Each input creates a mapping property. Event values never enter the flow automatically.
MCP uses flow_input_add, node_prop_list and expr_context. The latter two take nodeId.
Set the Schedule label, then inspect its mapping.
cai expr set <nodeId> --prop <name> --js '"09:00 America/Chicago"' --jsoncai node props <nodeId> --jsonMCP uses node_prop_set with nodeId, prop and inline js.
For event-derived inputs, bind the exact compatible field expression from context instead. Keep existing source IDs when repairing mappings.
Prove the flow and trigger path
Section titled “Prove the flow and trigger path”First, test the flow directly to check its logic in isolation.
cai run flow <flowId> --inputs '{"Schedule":"09:00 America/Chicago"}' --target dev --jsonMCP uses run_flow with flowId, target: "dev" and parsed inputs.
In the app, select Dev, open the flow and choose Test (tooltip “Test current flow”). After success, replay the original sample once to test the trigger path.
cai trigger replay --trigger <backendTriggerId> --event <eventId> --target dev --jsonKeep the new data.eventId separate from the original sample ID. Use data.workflowExecutionId as <workflowExecutionId>. Development replay requires an enabled development trigger. It bypasses incoming-event permission. Every replay creates another captured event and real execution. Pending is not a reason to replay again.
MCP uses trigger_replay with backend triggerId, eventId and target: "dev".
Inspect the execution to get its status.
cai exec get <workflowExecutionId> --jsonRepeat until data.status is completed, completed_with_error, failed or cancelled. For paused, use execution inspection.
MCP uses execution_get with workflowExecutionId.
Then inspect the tree to find the node’s execution ID.
cai exec tree <workflowExecutionId> --jsonNote the relevant data.items[].id as <nodeExecutionId>.
MCP uses execution_tree with workflowExecutionId.
Read its values to check the mapping and message.
cai exec node <nodeExecutionId> --full --jsonMCP uses execution_node_get with nodeExecutionId and full: true.
Check mapping and send values, invoice and review counts, and exactly one Slack message per test. With the empty queue, repeat and expect one zero-item digest.
What can keep real events running?
Section titled “What can keep real events running?”Disabling development stops its canvas execution and leaves incoming-event permission intact. It stops neither source capture nor the published trigger. Publish the disabled definition to change live execution. When retained permission would double-run alongside a live path, CLI/MCP refuses re-enabling. Disallow incoming-event permission first.
Before turning Allow test events in dev mode On, rule out a live path or explicitly accept both executions and charges. While enabled, permission immediately admits real traffic. After one event, inspect Run history, then turn it Off. Replay’s target is separate.
To test incoming events intentionally, allow them into development for a real execution.
cai trigger test-events <triggerId> --allow --jsonMCP uses trigger_test_events_set with triggerId and allowed:true. Add --acknowledge-dual-run / acknowledgeDualRun:true only after the user accepts a reported double-run hazard.
Follow Publish a Workflow for the complete trigger audit and live verification. CLI/MCP publication rejects unacknowledged dual dispatch. The app/shared service can publish with a warning. Capture happens before asynchronous typing and dispatch, so if no run appears, reread events and executions before diagnosing publication, enablement, routing or ingestion failure. If a run starts with empty mapped inputs, inspect its mapping.