@controllerai/cli 0.2.17 → 0.2.20

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (39) hide show
  1. package/dist/api/client.js +32 -0
  2. package/dist/api/client.js.map +1 -1
  3. package/dist/commands/agent.js +101 -8
  4. package/dist/commands/agent.js.map +1 -1
  5. package/dist/commands/expr.js +3 -10
  6. package/dist/commands/expr.js.map +1 -1
  7. package/dist/commands/file.js +11 -1
  8. package/dist/commands/file.js.map +1 -1
  9. package/dist/commands/integration.js +8 -2
  10. package/dist/commands/integration.js.map +1 -1
  11. package/dist/commands/workflow.js +29 -6
  12. package/dist/commands/workflow.js.map +1 -1
  13. package/dist/errors.js +5 -2
  14. package/dist/errors.js.map +1 -1
  15. package/package.json +1 -1
  16. package/skills/controllerai-agents/SKILL.md +25 -192
  17. package/skills/controllerai-agents/references/command-reference.md +205 -0
  18. package/skills/controllerai-ai-nodes/SKILL.md +11 -92
  19. package/skills/controllerai-ai-nodes/references/command-reference.md +98 -0
  20. package/skills/controllerai-data/SKILL.md +34 -159
  21. package/skills/controllerai-data/references/command-reference.md +177 -0
  22. package/skills/controllerai-expressions/SKILL.md +29 -151
  23. package/skills/controllerai-expressions/references/command-reference.md +166 -0
  24. package/skills/controllerai-expressions/references/dsl-and-recipes.md +1 -1
  25. package/skills/controllerai-flow-control/SKILL.md +21 -160
  26. package/skills/controllerai-flow-control/references/command-reference.md +171 -0
  27. package/skills/controllerai-integration-actions/SKILL.md +11 -112
  28. package/skills/controllerai-integration-actions/references/command-reference.md +118 -0
  29. package/skills/controllerai-node-config/SKILL.md +18 -178
  30. package/skills/controllerai-node-config/references/command-reference.md +186 -0
  31. package/skills/controllerai-runs/SKILL.md +25 -117
  32. package/skills/controllerai-runs/references/command-reference.md +113 -0
  33. package/skills/controllerai-start/SKILL.md +36 -67
  34. package/skills/controllerai-start/references/mcp-tool-map.md +6 -0
  35. package/skills/controllerai-triggers/SKILL.md +16 -210
  36. package/skills/controllerai-triggers/references/command-reference.md +215 -0
  37. package/skills/controllerai-workflows/SKILL.md +24 -104
  38. package/skills/controllerai-workflows/references/command-reference.md +118 -0
  39. package/skills/manifest.json +120 -60
@@ -1,222 +1,28 @@
1
1
  ---
2
2
  name: controllerai-triggers
3
- description: Discover, configure, create, sample, enable, test, and debug Controller AI triggers. Use when working with schedules, webhooks, email or app events, captured sample payloads, trigger-to-flow mappings, replay, or any question about why an automation did or did not start.
3
+ description: Build and verify Controller AI event-driven workflows using schedules, webhooks, email and integration events. Use for trigger discovery, configuration, samples, event mapping, replay and enabling live execution.
4
4
  ---
5
5
 
6
- # Controller AI triggers
6
+ # Run workflows from events
7
7
 
8
- The `cai ...` examples are canonical grammar. Use the transport selected in `controllerai-start` and its MCP tool map; never mix transports in one task.
8
+ A trigger captures a schedule, webhook, email or integration event and maps it into a flow's typed inputs. It lets the same reusable processing run without a chat message. The trigger configuration, captured samples and execution state are separate concerns.
9
9
 
10
- A trigger targets exactly one flow. Its source may capture events before publish, but ordinary event execution uses the live workflow. Creating the source is therefore separate from mapping, development testing, publishing, and live replay.
10
+ ## Build the event path
11
11
 
12
- ## Rules that break tasks when skipped
12
+ 1. Discover the trigger component and inspect its properties, authorization and output schema.
13
+ 2. Create/select the destination flow and define the inputs it needs.
14
+ 3. Configure the trigger using the exact component identity. Choose selectors before dependent properties and bind any required connection.
15
+ 4. Capture a representative event. Use the returned webhook URL, trigger email address or provider action; do not invent an endpoint.
16
+ 5. Inspect/select the captured sample and map its fields into flow inputs using the actual expression context.
17
+ 6. Replay the sample on development and verify received inputs, flow outputs and expected record or external effects.
18
+ 7. When live operation is authorized, publish the workflow, enable the trigger as needed and verify an actual live event.
13
19
 
14
- - Preserve trigger ID and source during repair; see Create and map.
15
- - Delete a retired start; disable a reversible pause. See Remove or disable an automatic start.
16
- - Lifecycle uses `--enable|--disable`; test events use `--allow|--disallow`. See Remove or disable an automatic start and Finish trigger setup.
17
- - Disarm capture when setup ends; see Finish trigger setup.
18
- - Lifecycle edits are development-only; publish only for Live. See Verify development, then publish.
19
- - Replay with `--target dev`; Live also requires `--confirm-live`. See Verify development, then publish.
20
+ Use `trigger_set_enabled` for a reversible pause/resume and `trigger_delete` to remove a retired trigger. Capture can exist before publication; publication controls the live executable definition. Replaying an event can perform real external actions, so use the existing authorization and intended test scope. A recorded event is not proof the flow executed.
20
21
 
21
- ## Require a real source decision
22
+ ## Diagnose by stage
22
23
 
23
- Determine how the trigger choice was established:
24
+ If there is no event, inspect trigger identity, connection, registration and the source action. If the event exists but inputs are wrong, inspect selected sample and mappings. If the flow starts but fails, follow the execution ID with `controllerai-runs`. Inspect enabled state and published configuration when development works but live does not.
24
25
 
25
- - `explicit-in-request`: user named it in the request
26
- - `user-answer`: user chose after clarification
27
- - `inferred-from-existing-workflow`: preserving an existing source
26
+ Schedules need an explicit timezone and intended cadence. Follow the user's cadence; do not infer a production schedule from a test sample. Avoid duplicate triggers while debugging: keep the original trigger and event IDs.
28
27
 
29
- Do not use `assumption`; the backend rejects it. If the request does not determine when the automation runs, ask one focused question before creating a source.
30
-
31
- ## Discover the exact event
32
-
33
- ```bash
34
- cai trigger search "<event intent>" --json
35
- cai trigger search --node <nodeSlug> --events-per-node 50 --json
36
- ```
37
-
38
- Copy the exact `nodeSlug` and `eventKey`. Never infer an event key from its display name.
39
-
40
- If authentication is required:
41
-
42
- ```bash
43
- cai connection list --node <nodeSlug> --json
44
- cai connection connect <nodeSlug>
45
- ```
46
-
47
- MCP: call `connection_connect_url`; it returns the URL immediately and has no `open` or `wait` parameter.
48
-
49
- ## Resolve trigger props
50
-
51
- ```bash
52
- cai trigger props \
53
- --node <nodeSlug> \
54
- --event <eventKey> \
55
- --connection <connectionId> \
56
- --json
57
- ```
58
-
59
- Use the returned shape-correct `propsExample` as a starting point. Hidden props remain unset. `readyForCreate` must be true before using it in `trigger create`; the response intentionally omits unresolved required option props rather than emitting a plausible placeholder.
60
-
61
- For each name in `unresolvedOptionProps`, run the complete canonical option command returned by the transport, or equivalently:
62
-
63
- ```bash
64
- cai trigger options \
65
- --node <nodeSlug> \
66
- --event <eventKey> \
67
- --prop <propName> \
68
- --connection <connectionId> \
69
- --configured '<configuredPropsJson>' \
70
- --dynamic-props-id <dynamicPropsId> \
71
- --query "<human option label>" \
72
- --json
73
- ```
74
-
75
- Copy the exact returned `value`, not its display `label`, into `--configured`, then rerun `trigger props`. Use `--page` and returned `context` via `--prev-context` only when search is unavailable.
76
-
77
- When a selector has `reloadProps`, rerun with its configured values and returned `dynamicPropsId` before creating the trigger.
78
-
79
- ```bash
80
- cai trigger props \
81
- --node <nodeSlug> \
82
- --event <eventKey> \
83
- --connection <connectionId> \
84
- --configured '<configuredPropsJson>' \
85
- --dynamic-props-id <dynamicPropsId> \
86
- --json
87
- ```
88
-
89
- Keep the same node, event, connection, and configured values on every reload, but always pass the LATEST `dynamicPropsId` the backend returned — a reload can mint a new ID, and reusing a stale one resolves against a stale schema. The response provides the complete canonical command; do not shorten it to only `--configured`.
90
-
91
- Timer values are objects:
92
-
93
- ```json
94
- {"cron":{"cron":"0 9 * * *","timezone":"America/Chicago"}}
95
- ```
96
-
97
- or
98
-
99
- ```json
100
- {"cron":{"intervalSeconds":900}}
101
- ```
102
-
103
- Do not pass a bare cron string or assume a timezone. Ask when the user says "at 9am" without one.
104
-
105
- ## Create and map
106
-
107
- ```bash
108
- cai trigger create \
109
- --flow <targetFlowId> \
110
- --node <nodeSlug> \
111
- --event <eventKey> \
112
- --source-basis <basis> \
113
- --connection <connectionId> \
114
- --props '<json>' \
115
- --dynamic-props-id <id> \
116
- --json
117
- ```
118
-
119
- Capture all returned IDs. `triggerId` is the canvas ID used for get/rename/set-enabled/delete/test-events. `backendTriggerId` is numeric and used for captured events and replay. They are not interchangeable.
120
-
121
- When repairing an existing trigger, preserve its canvas ID and source. Repair its mapping in place; do not delete and recreate it merely to clear readiness. Replacement changes captured IDs and may change a webhook URL. Replace only when the requested source itself must change, then recapture every returned ID.
122
-
123
- Read a single trigger back with `cai trigger get <triggerId> --json` — the full record: node, event, connection, props, lifecycle. Read-back is always `get`; the CLI has no `describe` read command anywhere (`cai workflow set-description` is a setter).
124
-
125
- Follow returned `nextSteps` in order. Trigger payload does not automatically populate the target flow; define flow inputs, relink the run-subflow node if needed, and configure its mapping props.
126
-
127
- ## Remove or disable an automatic start
128
-
129
- `cai trigger delete <triggerId>` removes the automatic start from the development canvas; use it when the start should no longer exist. Never delete its owning flow merely to remove the trigger. `cai trigger set-enabled <triggerId> --enable|--disable` changes the enabled state reversibly and idempotently; pass exactly one state flag.
130
-
131
- MCP: call `trigger_set_enabled` with `enabled: true` or `enabled: false`.
132
-
133
- Both are development edits. Publish only for an authorized Live change; otherwise the prior Live trigger remains active.
134
-
135
- ## Establish a typed sample
136
-
137
- After sending a representative event to the source:
138
-
139
- ```bash
140
- cai trigger events --trigger <backendTriggerId> --json
141
- cai trigger event <eventId> --json
142
- cai trigger select-event --node <triggerNodeId> --event <eventId> --json
143
- ```
144
-
145
- Then re-read expression context on downstream nodes. A sample without a platform data type may remain untyped.
146
-
147
- ## Finish trigger setup: disarm test events
148
-
149
- Armed test events let real events reach the DEV version while you set the trigger up. They exist for one purpose: capturing the real data shape so it becomes the trigger node's output type. Arming is the START of trigger setup; **disarming is how trigger setup ENDS.** Once the shape is captured, selected, and typed, turn it off — also when a build fails or is abandoned midway:
150
-
151
- ```bash
152
- cai trigger test-events --id <triggerId> --disallow
153
- ```
154
-
155
- MCP: call `trigger_test_events_set` with `allowed: false`, or `allowed: true` to arm it.
156
-
157
- Do not mix the flag families. `set-enabled` takes `--enable` or `--disable`; `test-events` takes `--allow` or `--disallow`; replay takes `--target dev` or `--target live`, with `--confirm-live` for Live.
158
-
159
- The acknowledgements are distinct: `--acknowledge-dual-run` applies only while arming, `--acknowledge-dual-dispatch` only while publishing an armed trigger, and `--confirm-live` only to one Live replay.
160
-
161
- Arming is sticky and independent from enablement. Armed plus live dispatch runs each real event twice; a schedule does so every interval. Disabling does not clear the allow flag, so always disallow after capture.
162
-
163
- Keeping both rails armed is an uncommon user decision, never a default.
164
-
165
- ## Verify development, then publish
166
-
167
- Use `cai run flow` for direct development verification, then replay one captured event through the development trigger path. MCP `run_flow` calls take `waitSeconds`.
168
-
169
- ```bash
170
- cai trigger replay --trigger <backendTriggerId> --event <eventId> --target dev --json
171
- cai exec tree <workflowExecutionId> --json
172
- ```
173
-
174
- A development replay never dispatches live, but nodes still call real providers and can create side effects or spend usage. Publish only after mappings and development behavior pass.
175
-
176
- A draft-only request stops after development proof. Do not publish merely because the trigger is ready.
177
-
178
- Before publishing, audit EVERY trigger in the workflow — not just the one you worked on. Users forget triggers left enabled or armed in other flows. Read each row's lifecycle fields from `cai trigger list --json` (`devCanvasEnabled`, `deployment.liveCanvasEnabled`, `deployment.inLiveVersion`, `deployment.devDispatchArmed`, `deployment.dualDispatchLive`) and confirm with the user which triggers should be starting this workflow live:
179
-
180
- ```bash
181
- cai trigger list --json
182
- cai workflow publish --name "<release>" --json
183
- ```
184
-
185
- If publish fails because a trigger still has test events armed, that error is the designed backstop, not a malfunction: trigger setup was never finished. The normal resolution is to disarm and republish. Publishing WITH an armed trigger requires the user's explicit, informed choice — explain the double-run and double-billing consequence first, then pass the intent flag:
186
-
187
- ```bash
188
- cai workflow publish --name "<release>" --acknowledge-dual-dispatch --json
189
- ```
190
-
191
- Never pass `--acknowledge-dual-dispatch` on your own initiative.
192
-
193
- Live replay is optional and requires an explicit acknowledgement:
194
-
195
- ```bash
196
- cai trigger replay \
197
- --trigger <backendTriggerId> \
198
- --event <eventId> \
199
- --target live \
200
- --confirm-live \
201
- --json
202
- cai exec tree <workflowExecutionId> --json
203
- ```
204
-
205
- It executes the published workflow, calls live third-party actions, and spends usage. Obtain appropriate user intent before replaying a side-effectful event.
206
-
207
- Read [references/lifecycle.md](references/lifecycle.md) for trigger state and debugging.
208
-
209
- ## Before you finish
210
-
211
- ```bash
212
- cai trigger get <triggerId> --json
213
- cai trigger list --json
214
- cai workflow status --json
215
- # Only after an authorized create or mapping test:
216
- cai exec tree <workflowExecutionId> --json
217
- ```
218
-
219
- - Read-back must retain the intended trigger, source, target flow, connection, props, and mapping.
220
- - `devCanvasEnabled`, `liveCanvasEnabled`, and `inLiveVersion` must match the requested rail state.
221
- - `devDispatchArmed` must be false unless the user explicitly chose dual dispatch; report `dualDispatchLive`.
222
- - For authorized create/mapping work, the development test must produce the expected tree. Never replay for delete/disable-only work. Live replay needs separate authorization.
28
+ Commands: [reference](references/command-reference.md). Capture, replay and lifecycle details: [lifecycle](references/lifecycle.md).
@@ -0,0 +1,215 @@
1
+ # Controller AI triggers
2
+
3
+
4
+ A trigger targets exactly one flow. Its source may capture events before publish, but ordinary event execution uses the live workflow. Creating the source is therefore separate from mapping, development testing, publishing, and live replay.
5
+
6
+
7
+ - Preserve trigger ID and source during repair; see Create and map.
8
+ - Delete a retired start; disable a reversible pause. See Remove or disable an automatic start.
9
+ - Lifecycle uses `--enable|--disable`; test events use `--allow|--disallow`. See Remove or disable an automatic start and Finish trigger setup.
10
+ - Disarm capture when setup ends; see Finish trigger setup.
11
+ - Lifecycle edits are development-only; publish only for Live. See Verify development, then publish.
12
+ - Replay with `--target dev`; Live also requires `--confirm-live`. See Verify development, then publish.
13
+
14
+ ## Require a real source decision
15
+
16
+ Determine how the trigger choice was established:
17
+
18
+ - `explicit-in-request`: user named it in the request
19
+ - `user-answer`: user chose after clarification
20
+ - `inferred-from-existing-workflow`: preserving an existing source
21
+
22
+ Do not use `assumption`; the backend rejects it. If the request does not determine when the automation runs, ask one focused question before creating a source.
23
+
24
+ ## Discover the exact event
25
+
26
+ ```bash
27
+ cai trigger search "<event intent>" --json
28
+ cai trigger search --node <nodeSlug> --events-per-node 50 --json
29
+ ```
30
+
31
+ Copy the exact `nodeSlug` and `eventKey`. Never infer an event key from its display name.
32
+
33
+ If authentication is required:
34
+
35
+ ```bash
36
+ cai connection list --node <nodeSlug> --json
37
+ cai connection connect <nodeSlug>
38
+ ```
39
+
40
+ MCP: call `connection_connect_url`; it returns the URL immediately and has no `open` or `wait` parameter.
41
+
42
+ ## Resolve trigger props
43
+
44
+ ```bash
45
+ cai trigger props \
46
+ --node <nodeSlug> \
47
+ --event <eventKey> \
48
+ --connection <connectionId> \
49
+ --json
50
+ ```
51
+
52
+ Use the returned shape-correct `propsExample` as a starting point. Hidden props remain unset. `readyForCreate` must be true before using it in `trigger create`; the response intentionally omits unresolved required option props rather than emitting a plausible placeholder.
53
+
54
+ For each name in `unresolvedOptionProps`, run the complete canonical option command returned by the transport, or equivalently:
55
+
56
+ ```bash
57
+ cai trigger options \
58
+ --node <nodeSlug> \
59
+ --event <eventKey> \
60
+ --prop <propName> \
61
+ --connection <connectionId> \
62
+ --configured '<configuredPropsJson>' \
63
+ --dynamic-props-id <dynamicPropsId> \
64
+ --query "<human option label>" \
65
+ --json
66
+ ```
67
+
68
+ Copy the exact returned `value`, not its display `label`, into `--configured`, then rerun `trigger props`. Use `--page` and returned `context` via `--prev-context` only when search is unavailable.
69
+
70
+ When a selector has `reloadProps`, rerun with its configured values and returned `dynamicPropsId` before creating the trigger.
71
+
72
+ ```bash
73
+ cai trigger props \
74
+ --node <nodeSlug> \
75
+ --event <eventKey> \
76
+ --connection <connectionId> \
77
+ --configured '<configuredPropsJson>' \
78
+ --dynamic-props-id <dynamicPropsId> \
79
+ --json
80
+ ```
81
+
82
+ Keep the same node, event, connection, and configured values on every reload, but always pass the LATEST `dynamicPropsId` the backend returned — a reload can mint a new ID, and reusing a stale one resolves against a stale schema. The response provides the complete canonical command; do not shorten it to only `--configured`.
83
+
84
+ Timer values are objects:
85
+
86
+ ```json
87
+ {"cron":{"cron":"0 9 * * *","timezone":"America/Chicago"}}
88
+ ```
89
+
90
+ or
91
+
92
+ ```json
93
+ {"cron":{"intervalSeconds":900}}
94
+ ```
95
+
96
+ Do not pass a bare cron string or assume a timezone. Ask when the user says "at 9am" without one.
97
+
98
+ ## Create and map
99
+
100
+ ```bash
101
+ cai trigger create \
102
+ --flow <targetFlowId> \
103
+ --node <nodeSlug> \
104
+ --event <eventKey> \
105
+ --source-basis <basis> \
106
+ --connection <connectionId> \
107
+ --props '<json>' \
108
+ --dynamic-props-id <id> \
109
+ --json
110
+ ```
111
+
112
+ Capture all returned IDs. `triggerId` is the canvas ID used for get/rename/set-enabled/delete/test-events. `backendTriggerId` is numeric and used for captured events and replay. They are not interchangeable.
113
+
114
+ When repairing an existing trigger, preserve its canvas ID and source. Repair its mapping in place; do not delete and recreate it merely to clear readiness. Replacement changes captured IDs and may change a webhook URL. Replace only when the requested source itself must change, then recapture every returned ID.
115
+
116
+ Read a single trigger back with `cai trigger get <triggerId> --json` — the full record: node, event, connection, props, lifecycle. Read-back is always `get`; the CLI has no `describe` read command anywhere (`cai workflow set-description` is a setter).
117
+
118
+ Follow returned `nextSteps` in order. Trigger payload does not automatically populate the target flow; define flow inputs, relink the run-subflow node if needed, and configure its mapping props.
119
+
120
+ ## Remove or disable an automatic start
121
+
122
+ `cai trigger delete <triggerId>` removes the automatic start from the development canvas; use it when the start should no longer exist. Never delete its owning flow merely to remove the trigger. `cai trigger set-enabled <triggerId> --enable|--disable` changes the enabled state reversibly and idempotently; pass exactly one state flag.
123
+
124
+ MCP: call `trigger_set_enabled` with `enabled: true` or `enabled: false`.
125
+
126
+ Both are development edits. Publish only for an authorized Live change; otherwise the prior Live trigger remains active.
127
+
128
+ ## Establish a typed sample
129
+
130
+ After sending a representative event to the source:
131
+
132
+ ```bash
133
+ cai trigger events --trigger <backendTriggerId> --json
134
+ cai trigger event <eventId> --json
135
+ cai trigger select-event --node <triggerNodeId> --event <eventId> --json
136
+ ```
137
+
138
+ Then re-read expression context on downstream nodes. A sample without a platform data type may remain untyped.
139
+
140
+ ## Finish trigger setup: disarm test events
141
+
142
+ Armed test events let real events reach the DEV version while you set the trigger up. They exist for one purpose: capturing the real data shape so it becomes the trigger node's output type. Arming is the START of trigger setup; **disarming is how trigger setup ENDS.** Once the shape is captured, selected, and typed, turn it off — also when a build fails or is abandoned midway:
143
+
144
+ ```bash
145
+ cai trigger test-events --id <triggerId> --disallow
146
+ ```
147
+
148
+ MCP: call `trigger_test_events_set` with `allowed: false`, or `allowed: true` to arm it.
149
+
150
+ Do not mix the flag families. `set-enabled` takes `--enable` or `--disable`; `test-events` takes `--allow` or `--disallow`; replay takes `--target dev` or `--target live`, with `--confirm-live` for Live.
151
+
152
+ The acknowledgements are distinct: `--acknowledge-dual-run` applies only while arming, `--acknowledge-dual-dispatch` only while publishing an armed trigger, and `--confirm-live` only to one Live replay.
153
+
154
+ Arming is sticky and independent from enablement. Armed plus live dispatch runs each real event twice; a schedule does so every interval. Disabling does not clear the allow flag, so always disallow after capture.
155
+
156
+ Keeping both rails armed is an uncommon user decision, never a default.
157
+
158
+ ## Verify development, then publish
159
+
160
+ Use `cai run flow` for direct development verification, then replay one captured event through the development trigger path. MCP `run_flow` calls take `waitSeconds`.
161
+
162
+ ```bash
163
+ cai trigger replay --trigger <backendTriggerId> --event <eventId> --target dev --json
164
+ cai exec tree <workflowExecutionId> --json
165
+ ```
166
+
167
+ A development replay never dispatches live, but nodes still call real providers and can create side effects or spend usage. Publish only after mappings and development behavior pass.
168
+
169
+ A draft-only request stops after development proof. Do not publish merely because the trigger is ready.
170
+
171
+ Before publishing, audit EVERY trigger in the workflow — not just the one you worked on. Users forget triggers left enabled or armed in other flows. Read each row's lifecycle fields from `cai trigger list --json` (`devCanvasEnabled`, `deployment.liveCanvasEnabled`, `deployment.inLiveVersion`, `deployment.devDispatchArmed`, `deployment.dualDispatchLive`) and confirm with the user which triggers should be starting this workflow live:
172
+
173
+ ```bash
174
+ cai trigger list --json
175
+ cai workflow publish --name "<release>" --json
176
+ ```
177
+
178
+ If publish fails because a trigger still has test events armed, that error is the designed backstop, not a malfunction: trigger setup was never finished. The normal resolution is to disarm and republish. Publishing WITH an armed trigger requires the user's explicit, informed choice — explain the double-run and double-billing consequence first, then pass the intent flag:
179
+
180
+ ```bash
181
+ cai workflow publish --name "<release>" --acknowledge-dual-dispatch --json
182
+ ```
183
+
184
+ Never pass `--acknowledge-dual-dispatch` on your own initiative.
185
+
186
+ Live replay is optional and requires an explicit acknowledgement:
187
+
188
+ ```bash
189
+ cai trigger replay \
190
+ --trigger <backendTriggerId> \
191
+ --event <eventId> \
192
+ --target live \
193
+ --confirm-live \
194
+ --json
195
+ cai exec tree <workflowExecutionId> --json
196
+ ```
197
+
198
+ It executes the published workflow, calls live third-party actions, and spends usage. Obtain appropriate user intent before replaying a side-effectful event.
199
+
200
+ Read [lifecycle.md](lifecycle.md) for trigger state and debugging.
201
+
202
+ ## Before you finish
203
+
204
+ ```bash
205
+ cai trigger get <triggerId> --json
206
+ cai trigger list --json
207
+ cai workflow status --json
208
+ # Only after an authorized create or mapping test:
209
+ cai exec tree <workflowExecutionId> --json
210
+ ```
211
+
212
+ - Read-back must retain the intended trigger, source, target flow, connection, props, and mapping.
213
+ - `devCanvasEnabled`, `liveCanvasEnabled`, and `inLiveVersion` must match the requested rail state.
214
+ - `devDispatchArmed` must be false unless the user explicitly chose dual dispatch; report `dualDispatchLive`.
215
+ - For authorized create/mapping work, the development test must produce the expected tree. Never replay for delete/disable-only work. Live replay needs separate authorization.
@@ -1,126 +1,46 @@
1
1
  ---
2
2
  name: controllerai-workflows
3
- description: Build, inspect, edit, test, recover, and publish Controller AI workflows through the cai CLI or typed MCP tools. Use when a user asks to create or change an automation, workflow, flow, or workflow release, or when another Controller AI skill needs the shared lifecycle and safety rules.
3
+ description: Build, inspect, repair, test and publish Controller AI workflows: typed callable flows, deterministic actions, branching, durable workflow data and triggers. Use for automations or an agent-callable application backend.
4
4
  ---
5
5
 
6
6
  # Controller AI workflows
7
7
 
8
- The `cai ...` examples are canonical grammar. Follow the transport rules and MCP map in `controllerai-start`; never mix transports within one task. Do not call private REST endpoints or invoke MCP routes outside the typed tools. When the selected transport lacks a capability, say so and name the UI path instead of bypassing it.
8
+ A workflow groups **flows**, **custom schemas**, **data collections** and **triggers**. A flow is one callable function with typed inputs and outputs; its connected nodes implement the function. Several flows can share the workflow's data store and call one another.
9
9
 
10
- ## Rules that break tasks when skipped
10
+ Flows are useful as API-like tools for agents. For example one “Investor CRM” workflow can expose create/get/update/delete/search flows for contacts, companies, deals and activities, plus a contact history view. An agent chooses a tool; the flow enforces its contract and performs the work.
11
11
 
12
- - Lock the effective workflow ID and exact flow ID; see Establish context.
13
- - Repair the selected workflow and flow instead of creating replacements; see Build protocol.
14
- - Keep workflow, flow, node, input, and output IDs distinct; see Lifecycle rules.
15
- - Preserve contract fields in place and refresh their dependents; see Lifecycle rules.
16
- - Use save, history, and restore for recovery instead of rebuilding; see Lifecycle rules.
17
- - Treat validation counts as status; prove the requested rail and stop. See Lifecycle rules and Before you finish.
12
+ ## Start with the contract
18
13
 
19
- ## Establish context
14
+ Define each flow's inputs, outputs and failure behavior. Keep one operation per agent tool when that makes selection clearer than a giant operation dispatcher. Choose useful names and descriptions: “Search contacts by name, owner, tags and status” tells an agent when to call it.
20
15
 
21
- ```bash
22
- cai auth status --json
23
- cai workflow list --json
24
- cai use <workflowId>
25
- cai workflow status --json
26
- ```
16
+ Create the workflow, then explicitly create the first flow. `workflow_outline` provides a compact inventory; `flow_get` provides a flow's contracts, graph and configured values. Workflow IDs, flow IDs and node IDs are different identities.
27
17
 
28
- MCP: use `account_status`, then call `workflow_list` and `workflow_status` with explicit `workflowId`; there is no `cai use` or stored pin.
18
+ Before changing an existing workflow, read its outline and the affected flow. Repair the existing IDs instead of creating replacements. For a substantial rewrite, save a named checkpoint. Restore rolls back the definition, not record changes or external effects.
29
19
 
30
- If no workflow exists, create it with its final name:
20
+ ## Assemble and test
31
21
 
32
- ```bash
33
- cai workflow create --name "<clear outcome-oriented name>" --json
34
- ```
22
+ 1. Create any custom schemas and flow inputs/outputs first.
23
+ 2. Discover actions and add nodes in execution order. Configure the type or action selector before dependent props; reload props if the selector changes.
24
+ 3. Bind expressions using current `expr_context` names. Wire the source output to the destination so it appears in `inputs`.
25
+ 4. Use a Return node to map promised flow outputs. Merely declaring an output does not populate it.
26
+ 5. Test a complete development path with explicit representative input. Check the returned contract and same-environment data changes.
27
+ 6. Apply the proven pattern to additional paths. Batch independent configuration when the available tool supports it; do not combine operations whose IDs depend on earlier responses.
28
+ 7. Layout each changed flow, validate the saved workflow, and re-read its outline.
35
29
 
36
- Read `selected`, `effectiveWorkflowId`, and `pinSource`; creation may not win the pin. If unselected, remove a command flag, use `cai use <id>` for a stored pin, or clear inherited `CAI_WORKFLOW`, as `pinSource` directs, then re-check. `cai config reset` clears only stored pins. `cai doctor` verifies the effective pin and development head. On MCP, capture and pass the new `workflowId`. Create with the final name.
30
+ Use `controllerai-node-config` for action configuration, `controllerai-expressions` for computed values, `controllerai-flow-control` for routing/loops, `controllerai-data` for storage and `controllerai-runs` for execution evidence.
37
31
 
38
- A new workflow already ships with one empty flow. Rename that flow and build in it — do not add a second flow for the first piece of work; only add flows for genuinely separate canvases. A stray empty "Flow 1" left behind is clutter the user has to clean up.
32
+ ## Files and agents
39
33
 
40
- Use IDs returned by the selected transport. For account-wide lists, filter by exact ID or name and owning workflow; never choose the first or latest similar result. Read the selected object's ID, name, and owner once, reuse those IDs, and never rediscover the target by name. A missing projected create field is not failure: inspect the complete result and exact inventory before retrying. Never invent identifiers.
34
+ A chat attachment is handled by a user-facing agent. For CSV enrichment, make a per-row flow accepting `investorName` and optional `company`, returning normalized contact information and evidence. The agent reads and writes the CSV. The native Create File action can generate files; it does not imply a native CSV reader/upload trigger.
41
35
 
42
- To orient inside a workflow, prefer one call over many:
36
+ For an agent tool, attach the tested flow with `agent_tool_workflow_add`. Its flow inputs and outputs are the tool contract. For unattended operation, add a trigger and map its event into these same inputs.
43
37
 
44
- ```bash
45
- cai workflow outline --json
46
- ```
38
+ ## Release and recovery
47
39
 
48
- `cai workflow state --json` is bounded; add `--flow <flowId>` for node and edge identities. Use `workflow document` only for complete opaque JSON. `workflow outline` shows flows, contracts, graph `deps`, triggers, and data inventory. Use `flow get` for props and expressions.
40
+ Graph edits affect development. Publishing creates the workflow's live release; attached live agents follow its latest release without another agent publish. The development/live record stores remain separate.
49
41
 
50
- ## Build protocol
42
+ Use the user's existing authorization when deciding whether to publish. If publication is authorized, fix validation errors, publish, then verify Live. For a draft-only request, deliver the tested draft and its link.
51
43
 
52
- 1. Translate the request into inputs, steps, outputs, trigger, integrations, failure behavior, and publish intent. When the request says to store, save, log, or record something and names no external destination, that means a data type plus a create-record node (`controllerai-data`) — a flow output alone does not persist anything. When the user names the destination (a spreadsheet, a CRM, another app, a file), write there with that integration's node instead; add a platform record only when the user also wants a copy kept here.
53
- 2. Inspect the current workflow before editing: `cai workflow outline`, then `cai flow get <flowId>`. Repair those IDs; do not create replacements for a repair.
54
- 3. Create or select a flow. Define flow inputs and outputs before nodes that derive props from them.
55
- 4. Build in execution order. After each material change, read it back with the corresponding `get`, `props`, `status`, or `list` command.
56
- 5. Run `cai flow layout <flowId>` once per changed flow as the LAST step after a headless build or any batch of structural edits (adds, deletes, rewires) — add-time placement avoids overlap, but only layout produces clean left-to-right columns. An open builder adopts your layout automatically.
57
- 6. Test on the development rail. Debug every failed or suspicious node; a green top-level status alone is insufficient.
58
- 7. Re-read `cai workflow status`. Publish only when the user asked for a live change or clearly authorized deployment.
44
+ On a state conflict, re-read the current saved version and reapply the intended change. Do not overwrite a newer graph with an old document. Report validation issues by their practical effect and inspect empty results where data was expected.
59
45
 
60
- For multi-domain work, read [references/command-map.md](references/command-map.md) before editing.
61
-
62
- ## Route specialized work
63
-
64
- Load the narrow skill when the task reaches that surface:
65
-
66
- - Node discovery, initialization, connections, props, or wiring: `controllerai-node-config`
67
- - Dynamic values or conditions: `controllerai-expressions`
68
- - Router, If/Else, loops, joins, or subflows: `controllerai-flow-control`
69
- - Test execution or debugging: `controllerai-runs`
70
- - Scheduled, webhook, or integration events: `controllerai-triggers`
71
- - Schemas or records: `controllerai-data`
72
- - Ask AI or Agent nodes: `controllerai-ai-nodes`
73
- - User-facing agents and their workflow tools: `controllerai-agents`
74
-
75
- ## Lifecycle rules
76
-
77
- - All graph edits target development. Live remains unchanged until `cai workflow publish`.
78
- - Email verification is not a publishing prerequisite. An unclaimed agent-created account may publish; email claiming only raises its monthly usage cap and enables account recovery.
79
- - On the CLI, prefer `--json` for decisions and IDs; human tables are for presentation. MCP tools return typed JSON. If human output looks odd, re-run the same read with `--json` before acting.
80
- - A workflow contains flows; a flow is one canvas. Do not confuse their IDs.
81
- - For flow inputs, pass a human `--display` label and use the current binding from `flow get` (`jsBinding`) or `workflow outline` (`binding`). Rename an existing contract input or output in place; do not delete and recreate it. After any rename or deletion, re-read the flow and repair every expression and subflow mapping before validation or execution. `legacyBinding` is diagnostic-only.
82
- - Name nodes after the data they produce. Downstream input bindings are seeded from that name when wired.
83
- - Use `cai workflow save --name "<checkpoint>"` before a risky rewrite. Named saves and state renames work on every plan.
84
-
85
- ```bash
86
- cai workflow history --json
87
- cai workflow history --group <groupId> --json
88
- cai workflow restore --state <stateId> --json
89
- ```
90
-
91
- - **Use version history for recovery.** Each save is a state. History retention is unlimited on Free, Max, and custom plans and 90 days on Pro/Starter; restore eligibility is 7 days on Free, 90 on Pro/Starter, and unlimited on Max/custom. Expand groups to capture state IDs. Restore rolls back the definition only; records and external effects remain.
92
- - **Validate after structural edits and before publish.** Fix every listed prop, wire, expression, type, subflow, branch, and trigger error. Publish refuses errors; use `--acknowledge-validation-errors` only after explicit approval of the listed issues. Flow deletion also removes its contract, graph, and triggers and breaks callers; validation shows each break.
93
- - Treat validation warning and error counts as status only. Never write them or their messages into unrelated workflow properties.
94
- - On a conflict, re-read current state and reapply intent. Do not replay stale IDs or whole documents.
95
- - Never delete a workflow without the user's explicit intent; the CLI requires `--yes` but that is not a substitute for authorization. MCP: `workflow_delete` has no `yes` parameter, but still requires the same explicit intent. `cai workflow delete` tears down deployed triggers and soft-deletes the workflow row. Historical workflow/version data remains stored, but there is currently no restore command for the deleted row.
96
- - **Check dependencies before shared-resource changes.** `cai deps` shows attached agents, workflow callers, and connections; `cai deps --account` maps the account. Deleting a workflow with agent dependents is refused server-side, and `--force` is a deprecated, inert compatibility flag. Detach draft tools with `cai agent remove-tool <agentId> --tool <toolId>`. If still LIVE, use `cai agent publish <agentId>` after explicit approval. A dependent agent publish or delete is its own live/destructive decision. Then retry deletion.
97
- - **Use the account feed only for recorded history.** Filter `cai events` by type, time, workflow, and cursor. It omits deletions, settings, member removals, and labels. For an unrecorded past change, say it is not recorded and change nothing; names and current state are not proof.
98
- - **Share real product links.** Relevant publish, development run, agent, connection, workflow get/status, and agent get outputs include `appUrl` when known. Share returned links; never guess one. MCP `connection_connect_url` returns its link immediately.
99
- - Never silently weaken the request to make a test pass. Report an unsupported capability or ask about a real product decision.
100
-
101
- ## Before you finish
102
-
103
- Before claiming success, verify all of the following:
104
-
105
- ```bash
106
- cai workflow outline --json
107
- cai workflow validate --json
108
- cai workflow status --json
109
- cai flow get <flowId> --json
110
- cai run flow <flowId> --inputs <values.json> --json
111
- ```
112
-
113
- MCP: pass the parsed values in `inputs` and set `waitSeconds` on `run_flow`.
114
-
115
- Then confirm:
116
-
117
- - **`cai workflow validate` reports `errors: 0`.** Every error is fixed, or explicitly reported to the user with what it breaks — never summarized away, never called cosmetic. A red canvas and a "done" claim cannot coexist.
118
- - Required node connections and props are complete.
119
- - Expressions compiled and their resolved configs are non-null.
120
- - Expected branch or error paths were exercised where practical.
121
- - Flow outputs contain the promised values.
122
- - The reported live/dev state matches what the user asked for.
123
- - Final outline inventory matches the request. Remove only scratch schemas, flows, nodes, and triggers created during abandoned attempts.
124
- - After fixing requested blockers and testing each changed path once, stop. Do not redesign for non-blocking warnings.
125
-
126
- State what was built, what was tested, whether it was published, and any user-owned connection or product choice still pending.
46
+ Detailed CLI/MCP sequences and lifecycle operations: [command reference](references/command-reference.md). Multi-domain command lookup: [command map](references/command-map.md).