@controllerai/cli 0.2.20 → 0.2.22

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 (79) hide show
  1. package/README.md +6 -3
  2. package/dist/api/client.js +5 -38
  3. package/dist/api/client.js.map +1 -1
  4. package/dist/commands/agent.js +169 -146
  5. package/dist/commands/agent.js.map +1 -1
  6. package/dist/commands/expr.js +10 -3
  7. package/dist/commands/expr.js.map +1 -1
  8. package/dist/commands/integration.js +30 -10
  9. package/dist/commands/integration.js.map +1 -1
  10. package/dist/commands/skills.js +1 -0
  11. package/dist/commands/skills.js.map +1 -1
  12. package/dist/commands/templateSetup.js +42 -0
  13. package/dist/commands/templateSetup.js.map +1 -0
  14. package/dist/commands/workflow.js +6 -7
  15. package/dist/commands/workflow.js.map +1 -1
  16. package/dist/errors.js +2 -5
  17. package/dist/errors.js.map +1 -1
  18. package/dist/index.js +2 -0
  19. package/dist/index.js.map +1 -1
  20. package/dist/permissionTool.js +1 -1
  21. package/dist/permissionTool.js.map +1 -1
  22. package/package.json +6 -4
  23. package/skills/controllerai-agents/SKILL.md +109 -26
  24. package/skills/controllerai-agents/references/instructions-and-versioning.md +32 -34
  25. package/skills/controllerai-ai-nodes/SKILL.md +83 -10
  26. package/skills/controllerai-ai-nodes/references/selection-and-testing.md +44 -26
  27. package/skills/controllerai-data/SKILL.md +106 -34
  28. package/skills/controllerai-data/references/data-rails.md +24 -26
  29. package/skills/controllerai-expressions/SKILL.md +82 -29
  30. package/skills/controllerai-expressions/references/dsl-and-recipes.md +42 -40
  31. package/skills/controllerai-flow-control/SKILL.md +104 -21
  32. package/skills/controllerai-flow-control/references/patterns.md +23 -60
  33. package/skills/controllerai-integration-actions/SKILL.md +89 -11
  34. package/skills/controllerai-node-config/SKILL.md +108 -18
  35. package/skills/controllerai-node-config/references/prop-and-readiness.md +28 -78
  36. package/skills/controllerai-runs/SKILL.md +82 -25
  37. package/skills/controllerai-runs/references/debugging.md +24 -22
  38. package/skills/controllerai-start/SKILL.md +63 -35
  39. package/skills/controllerai-start/references/mcp-tool-map.md +22 -21
  40. package/skills/controllerai-template-setup/SKILL.md +132 -0
  41. package/skills/controllerai-template-setup/agents/openai.yaml +4 -0
  42. package/skills/controllerai-triggers/SKILL.md +113 -16
  43. package/skills/controllerai-triggers/references/lifecycle.md +36 -48
  44. package/skills/controllerai-workflows/SKILL.md +105 -25
  45. package/skills/controllerai-workflows/references/command-map.md +20 -44
  46. package/skills/manifest.json +96 -136
  47. package/skills-mcp/controllerai-agents/SKILL.md +121 -0
  48. package/skills-mcp/controllerai-agents/references/instructions-and-versioning.md +76 -0
  49. package/skills-mcp/controllerai-ai-nodes/SKILL.md +91 -0
  50. package/skills-mcp/controllerai-ai-nodes/references/selection-and-testing.md +66 -0
  51. package/skills-mcp/controllerai-data/SKILL.md +116 -0
  52. package/skills-mcp/controllerai-data/references/data-rails.md +43 -0
  53. package/skills-mcp/controllerai-expressions/SKILL.md +97 -0
  54. package/skills-mcp/controllerai-expressions/references/dsl-and-recipes.md +136 -0
  55. package/skills-mcp/controllerai-flow-control/SKILL.md +112 -0
  56. package/skills-mcp/controllerai-flow-control/references/patterns.md +82 -0
  57. package/skills-mcp/controllerai-integration-actions/SKILL.md +90 -0
  58. package/skills-mcp/controllerai-node-config/SKILL.md +106 -0
  59. package/skills-mcp/controllerai-node-config/references/prop-and-readiness.md +49 -0
  60. package/skills-mcp/controllerai-runs/SKILL.md +87 -0
  61. package/skills-mcp/controllerai-runs/references/debugging.md +53 -0
  62. package/skills-mcp/controllerai-start/SKILL.md +82 -0
  63. package/skills-mcp/controllerai-start/references/mcp-tool-map.md +177 -0
  64. package/skills-mcp/controllerai-template-setup/SKILL.md +10 -0
  65. package/skills-mcp/controllerai-triggers/SKILL.md +109 -0
  66. package/skills-mcp/controllerai-triggers/references/lifecycle.md +59 -0
  67. package/skills-mcp/controllerai-workflows/SKILL.md +108 -0
  68. package/skills-mcp/controllerai-workflows/references/command-map.md +1 -0
  69. package/skills-mcp/manifest.json +200 -0
  70. package/skills/controllerai-agents/references/command-reference.md +0 -205
  71. package/skills/controllerai-ai-nodes/references/command-reference.md +0 -98
  72. package/skills/controllerai-data/references/command-reference.md +0 -177
  73. package/skills/controllerai-expressions/references/command-reference.md +0 -166
  74. package/skills/controllerai-flow-control/references/command-reference.md +0 -171
  75. package/skills/controllerai-integration-actions/references/command-reference.md +0 -118
  76. package/skills/controllerai-node-config/references/command-reference.md +0 -186
  77. package/skills/controllerai-runs/references/command-reference.md +0 -113
  78. package/skills/controllerai-triggers/references/command-reference.md +0 -215
  79. package/skills/controllerai-workflows/references/command-reference.md +0 -118
@@ -1,186 +0,0 @@
1
- # Controller AI node configuration
2
-
3
-
4
- A node is ready only after its component, connection, dependency-ordered props, wiring, and output type are valid. Treat configuration as a state machine, not a bag of property writes.
5
-
6
- ## Deterministic sequence
7
-
8
- ### 1. Find an exact component
9
-
10
- ```bash
11
- cai integration actions "<capability>" --json
12
- cai integration action --integration <nodeSlug> --key <nodeKey> --json
13
- ```
14
-
15
- Use the returned `nodeSlug` and full `key`. Do not infer a component key from its display name. If discovery is broad, narrow it with:
16
-
17
- ```bash
18
- cai integration search "<integration>" --actions --json
19
- cai integration actions "<action>" --integration <nodeSlug> --json
20
- ```
21
-
22
- Inspect static prop metadata before creating the node. `required`, `remoteOptions`, and `reloadProps` determine configuration order.
23
-
24
- ### 2. Resolve the account
25
-
26
- If the component requires auth:
27
-
28
- ```bash
29
- cai connection list --node <nodeSlug> --json
30
- ```
31
-
32
- - One active connection: use its exact `id` as the `connectionId`.
33
- - Several: use an explicit user preference; otherwise ask which account.
34
- - None: add the real component without `--connection`; `missingConnection: true` is a valid handoff state. On CLI, get the link with `cai connection connect <nodeSlug> --no-open` and share it right away; do not block on `--wait` before sharing.
35
-
36
- MCP: call `connection_connect_url` with `nodeSlug`, show its `url` as a markdown link, ask the user to finish, then confirm with `connection_list` using its `integration`.
37
-
38
- After they confirm, run `cai connection list --integration <nodeSlug> --json` and bind the new ID with `cai node set-connection <nodeId> --connection <connectionId>`.
39
-
40
- Never substitute a connection from a similar slug.
41
-
42
- Rename or change the default with `cai connection update <id> [--name "<displayName>"] [--default|--no-default]` (MCP: `connection_update`); delete only intentionally with `cai connection delete <id> --yes` (MCP: `connection_delete`).
43
- Deleting a connection immediately removes authorization from bound nodes and agent tools.
44
-
45
- A missing connection is never a reason to substitute `registry_http-http-request` for a catalog component. A raw endpoint mentioned by the user is background context, not an instruction to hand-roll the call.
46
-
47
- ### 3. Initialize once
48
-
49
- ```bash
50
- cai node init \
51
- --flow <flowId> \
52
- --node <nodeSlug> \
53
- --key <nodeKey> \
54
- --name "<data this node produces>" \
55
- --connection <connectionId> \
56
- --after <upstreamNodeId> \
57
- --json
58
- ```
59
-
60
- MCP: use `node_add`; `cai node init` is the CLI alias of `cai node add`.
61
-
62
- Omit flags that do not apply. `--after` creates the ordinary main/error wire at creation. Use it when later props need upstream data. Initialization also accepts `--props`, but use it only for static, non-option values already present in the inspected component metadata. Never inline a `remoteOptions` value, a reload selector and its dependents, or a prop that has not materialized yet; initialize first and set those sequentially. Use `--enable-prop <name...>` only for optional props confirmed by component metadata.
63
-
64
- Capture the returned `nodeId`; do not rediscover it by name. Inspect the complete create result before projecting fields. A missing projection is not proof that creation failed, so read the captured ID or exact flow inventory before any retry.
65
-
66
- When repairing an existing node, keep its node ID and configure it in place. Do not delete and recreate it merely to clear bad props, select a component, or refresh generated props; deletion discards wiring, conditions, and identity-based references. Replace it only when the requested component itself must change. Then capture the replacement ID, reconnect every dependent, and revalidate them.
67
-
68
- ### 4. Follow readiness, not guesses
69
-
70
- ```bash
71
- cai node status <nodeId> --json
72
- cai node props <nodeId> --json
73
- ```
74
-
75
- For option-backed props, `node props` and write readback may report `optionsAvailability`: `available`, `blocked_upstream` with `blockedBy`, or `dynamic_upstream`. It is positional: earlier single `DROPDOWN` selectors gate later options. Older backends, and responses without a dependency catalog, may omit it; treat absence as unknown, not available.
76
-
77
- Work through blockers in this order:
78
-
79
- 1. Missing connection
80
- 2. Required selector props with `reloadProps`
81
- 3. Newly revealed required props
82
- 4. Static and remote-option props
83
- 5. Wiring required for expressions
84
- 6. Expressions
85
- 7. Unresolved output type
86
-
87
- Follow `next`. When a disabled required prop has an activating selector, its blocker names that selector; when it is the next blocker, `next` gives the exact `cai node set` command. `dynamicSelectorNotes` is non-blocking: a node may read ready while its dynamic selector's dependents still reflect the last concrete resolution.
88
-
89
- After every concrete reload-selector or connection change, re-run `node props`; dynamic props can appear, disappear, or reset. Use `cai node reload <nodeId> --json` to re-resolve without re-setting a selector. If an explicit reload finds an unset materialized reload selector, it returns `reconcileSkipped: "unset_selector"` plus a note and preserves materialized dependent props instead of reconciling them.
90
-
91
- ### 5. Set props safely
92
-
93
- Static value:
94
-
95
- ```bash
96
- cai node set <nodeId> --prop <exactName> --value '<literal-or-json>' --json
97
- ```
98
-
99
- MCP: use `node_prop_set` with `value`; it also handles expression writes through `js`.
100
-
101
- Optional prop:
102
-
103
- ```bash
104
- cai node optional-props <nodeId> --json
105
- cai node set <nodeId> --prop <exactName> --value '<literal-or-json>' --json
106
- # or: cai expr set <nodeId> --prop <exactName> --js '<expression>' --json
107
- ```
108
-
109
- MCP: `cai expr set` is the `js` form of `node_prop_set`.
110
-
111
- `node set` and `expr set` auto-enable a catalog-only optional prop, refresh its metadata, then write. Do not run a separate enable step first. If validation or the later write fails, the prop stays enabled; repair with `cai node disable-prop <nodeId> --prop <exactName>` and re-read props. This is also the repair for the Update-data wipe footgun: that action writes every enabled field, so disable any accidentally enabled field before running it.
112
-
113
- MCP: use `node_optional_prop_set` with `enabled: false` to disable or `enabled: true` to enable.
114
-
115
- Remote or dynamic option:
116
-
117
- ```bash
118
- cai node options <nodeId> --prop <exactName> --query "<specific label>" --json
119
- cai node set <nodeId> \
120
- --prop <exactName> \
121
- --value '<returned value>' \
122
- --label '<returned label>' \
123
- --json
124
- ```
125
-
126
- `node options` also supports `--prev-context '<context JSON>'` from the preceding page and repeatable `--for '<earlierProp>=<value>'` overrides for read-only hypothetical resolution; JSON literals are accepted and bare text stays a string. If options are `blocked_upstream`, both `node options` and `node set` name the blocking prop and print the exact `cai node set` command to run first.
127
-
128
- For an ordinary remote option, preserve both fields from the same returned option. The label is not cosmetic: it is used to search providers that do not index opaque IDs, then the returned value is verified before writing. For a multi-select, pass a JSON array of returned values and one `--label` argument per value, in the same order. The write supplies the persisted label shape, chooses the correct expression storage channel, and verifies read-back.
129
-
130
- When an earlier selector makes the prop `dynamic_upstream`, no option list exists. Use a known exact ID or an expression:
131
-
132
- ```bash
133
- cai node set <nodeId> --prop <exactName> --value '<exact-id>' --label '<display label>' --json
134
- cai node set <nodeId> --prop <exactName> --js '<expression>' --json
135
- ```
136
-
137
- `--value` stores the literal without provider-option validation and prints a note; on a label-bearing selector, `--label` controls its display label. This is the sole raw `--value` exception when the CLI has an advertised option set: outside `dynamic_upstream`, a missing prop row, a failed or empty advertised remote-options lookup, or a value absent from advertised options fails closed. The exception still requires prop metadata and verified read-back. Do not bypass failures with a raw API call.
138
-
139
- For components whose dependent props exist only after a concrete selector value, use a template first: set one concrete value, re-read `node props`, configure or record the revealed dependents, then switch the selector to `--js`. Those materialized props persist as the last concrete schema. Starting dynamic leaves them absent; neither that write nor `node reload` materializes them until one concrete selection is made.
140
-
141
- For dynamic values, load `controllerai-expressions` and prefer `cai expr set`.
142
-
143
- ### 6. Wire and verify
144
-
145
- Ordinary outputs:
146
-
147
- ```bash
148
- cai node connect --flow <flowId> --from <sourceNodeId> --to <targetNodeId> --output main --json
149
- ```
150
-
151
- Use `--output error` only for the automatic error path. Router and If/Else outputs require `cai branch connect` from the flow-control skill.
152
-
153
- Finish with:
154
-
155
- ```bash
156
- cai node status <nodeId> --json
157
- cai run node <nodeId> --inputs <values.json> --json
158
- ```
159
-
160
- MCP: `run_node` takes the parsed `inputs` object and `waitSeconds` (default 60, max 120).
161
-
162
- If the node has a wired input or consumes `inputs.<name>`, the node test is only an isolated configuration check. Run `cai run flow <flowId> --inputs <values.json> --json` before declaring its upstream expressions verified.
163
-
164
- MCP: `run_flow` takes the parsed `inputs` object and `waitSeconds` (default 60, max 120).
165
-
166
- If a dynamic provider action cannot be run but its response is documented, declare an unverified output contract:
167
-
168
- ```bash
169
- cai node declare-output <nodeId> --sample-file provider-response.json --json
170
- ```
171
-
172
- MCP: call `node_output_type_declare` with the parsed provider response in `sample`; the server cannot read `provider-response.json`.
173
-
174
- The sample must be a JSON object or a non-empty JSON array of provider items. Re-read status and expression context afterward; the first real completed run verifies the declaration.
175
-
176
- Read [prop-and-readiness.md](prop-and-readiness.md) when a prop is dynamic, option-backed, expression-capable, or unexpectedly absent.
177
-
178
- ## Hard rules
179
-
180
- - Configure props in returned order; later props may depend on earlier values.
181
- - Never write a prop absent from `node props`.
182
- - Let `node set` or `expr set` auto-enable catalog-only optional props; disable the prop explicitly after a failed write.
183
- - Wire before authoring an expression that consumes upstream data.
184
- - Changing a connection invalidates connection-scoped options; re-read props and options.
185
- - A successful write is not completion. Require read-back plus `node status`.
186
- - If output type remains unresolved, perform a realistic development test and inspect the resulting execution. Declare only a documented provider sample; never fabricate an output schema.
@@ -1,113 +0,0 @@
1
- # Controller AI runs
2
-
3
-
4
- Think "real run", not "simulation". `run node` always uses development; `run flow` defaults to development and can target the published live version. Both rails execute real integration actions (messages send, records change, provider usage is spent); development isolation covers the data store only. Running is a required part of building — one successful run is how a dynamic node's output type gets resolved for the next step — so mitigate risk before running.
5
-
6
- ## Consequential actions: mitigate with the user, don't refuse
7
-
8
- Use the task's existing authorization and a safe test target for actions with external consequences. For authorized CRUD testing, create synthetic records and exercise updates/deletion on those. Ask only when a needed external side effect or target is not covered by the user's request. Test runs execute real actions.
9
-
10
- ## First live run is part of development
11
-
12
- After publishing, run the published version directly under supervision:
13
-
14
- ```bash
15
- cai run flow <flowId> --inputs values.json --target live --confirm-live --json
16
- ```
17
-
18
- MCP: pass parsed values in `inputs` and set `waitSeconds` on `run_flow`.
19
-
20
- This command fires external actions and spends usage. For risky sends, build the safe-audience harness: branch on the `isLiveVersion` data source with If/Else — the false branch targets the developer (own email/channel), the true branch targets the real audience. Use this direct live run for explicit verification; do not wait for a real trigger event.
21
-
22
- ## Prepare exact run inputs
23
-
24
- ```bash
25
- cai run inputs <nodeId> --json
26
- cai run inputs <flowId> --flow --json
27
- ```
28
-
29
- Use returned opaque input IDs. Flow mode lists EVERY declared input with a `used` flag: supply the used ones (an unsupplied used input falls back to its saved test value), while values keyed to unused inputs are accepted and ignored. The input object can be a flat map; the CLI may load it from a file:
30
-
31
- ```json
32
- {
33
- "<inputId>": "representative value"
34
- }
35
- ```
36
-
37
- Do not key test values by a guessed display name.
38
-
39
- Before an isolated node run, `cai run inputs <nodeId> --json` calls `get_node_test_inputs`; supply every referenced `flowInputs[].id` explicitly. Missing one fails before execution with `ISOLATED_FLOW_CONTEXT_REQUIRED`. Explicit `null`, `""`, `false`, and `0` are valid supplied values.
40
-
41
- Date-typed inputs take plain ISO-8601 strings, e.g. `"2026-06-05"` or `"2026-06-05T12:30:00Z"` (no double-encoding, no epoch strings).
42
-
43
- ## Run the smallest useful scope
44
-
45
- Start with a changed node, then run its containing flow:
46
-
47
- ```bash
48
- cai run node <nodeId> --inputs values.json --json
49
- cai run flow <flowId> --inputs values.json --json
50
- ```
51
-
52
- MCP: pass parsed values in `inputs` and set `waitSeconds` on `run_node` or `run_flow`.
53
-
54
- `run node` is deliberately isolated: it does not execute wired upstream nodes. Read its `runScope`. If `endToEndValidationRequired` is true, values derived from upstream can be empty even when the selected node is green; do not accept that run as expression proof. `run flow` is the end-to-end check that executes upstream wiring.
55
-
56
- The CLI waits for a terminal execution state by default. MCP polling is bounded by `waitSeconds` and may return an unfinished execution ID. Capture `workflowExecutionId` and `nodeExecutionId` from the result.
57
-
58
- For every node test, inspect:
59
-
60
- - `status` and `errorMessage`
61
- - `skipReason`
62
- - `runScope`, especially `upstreamNodesExecuted` and `endToEndValidationRequired`
63
- - `resolvedConfigs`
64
- - `resolvedConfigs[].resolutionWarnings`: trust every structured entry; `[]` is authoritatively clean. Also read any transport warnings; CLI runs may mirror them on stderr.
65
- - `outputTypeAdoption`: the server verifies the exact completed `nodeExecutionId`, derives its persisted output shape, and updates only that non-static node. `adopted` or `already_typed` lets the next `node status` converge; `no_observed_output` means the representative run returned no reusable shape. `adoptedNodeIds` must be empty or contain only the tested node; stop if it names a sibling.
66
- - output shape and values
67
-
68
- A dynamic prop with a null/empty resolved config is a failure even when status is green. `0` and `false` are valid resolved values.
69
-
70
- ## Debug from the execution tree
71
-
72
- ```bash
73
- cai exec tree <workflowExecutionId> --limit 50 --json
74
- cai exec get <workflowExecutionId> --json
75
- cai exec flow <flowExecutionId> --json
76
- cai exec node <nodeExecutionId> --full --json
77
- ```
78
-
79
- Page with the returned `nextCursor` via `--cursor`; narrow large runs with repeatable `--status`
80
- or `--flow <flowId>`. Use the tree to locate the first unexpected status. Use the full node
81
- execution to inspect its status, resolved configuration, and untruncated output. Read
82
- [debugging.md](debugging.md) for the fault-isolation order.
83
-
84
- ## Output discovery
85
-
86
- Prefer a configured node test. If a component is not yet in the graph, `run discover` creates a scratch node and deletes it after execution:
87
-
88
- ```bash
89
- cai run discover \
90
- --node <nodeSlug> \
91
- --key <nodeKey> \
92
- --connection <connectionId|none> \
93
- --props '<json>' \
94
- --json
95
- ```
96
-
97
- MCP: `run_discover` always removes the scratch graph and exposes neither `keep` nor `waitSeconds`.
98
-
99
- This calls the real third-party action and spends usage. For a destructive action, do not probe merely to learn its output — first ask the user for a safe target (see "Consequential actions" above); if they decline, declare the expected shape instead. On CLI, use `--keep` only when the user wants the scratch node retained.
100
-
101
- After successful output discovery, re-read `cai node status` and downstream `cai expr context`; verify the adopted output type is concrete.
102
-
103
- ## Completion gate
104
-
105
- - CLI scripts may gate on `cai workflow validate` exiting 1; MCP callers inspect `valid` and `errors`.
106
- - The test exercised the changed path with credible values.
107
- - The first unexpected node, if any, was identified rather than inferred from the final error.
108
- - All dynamic configs resolved to intended values.
109
- - Output fields and types match downstream expectations.
110
- - Branch skips are intentional and error paths are accounted for.
111
- - A full flow test passes after isolated node fixes.
112
- - `completed` with an empty or null output is treated as a failure until the output values are read and explained — an empty result usually means a mis-mapped input or an expression that null-propagated silently.
113
- - The final report cites execution IDs and distinguishes development testing from live verification.
@@ -1,215 +0,0 @@
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,118 +0,0 @@
1
- # Controller AI workflows
2
-
3
-
4
-
5
- - Lock the effective workflow ID and exact flow ID; see Establish context.
6
- - Repair the selected workflow and flow instead of creating replacements; see Build protocol.
7
- - Keep workflow, flow, node, input, and output IDs distinct; see Lifecycle rules.
8
- - Preserve contract fields in place and refresh their dependents; see Lifecycle rules.
9
- - Use save, history, and restore for recovery instead of rebuilding; see Lifecycle rules.
10
- - Treat validation counts as status; prove the requested rail and stop. See Lifecycle rules and Before you finish.
11
-
12
- ## Establish context
13
-
14
- ```bash
15
- cai auth status --json
16
- cai workflow list --json
17
- cai use <workflowId>
18
- cai workflow status --json
19
- ```
20
-
21
- MCP: use `account_status`, then call `workflow_list` and `workflow_status` with explicit `workflowId`; there is no `cai use` or stored pin.
22
-
23
- If no workflow exists, create it with its final name:
24
-
25
- ```bash
26
- cai workflow create --name "<clear outcome-oriented name>" --json
27
- ```
28
-
29
- 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
-
31
- After `cai workflow create`, check `flowCount` in the output. If it is 0 (or the field is missing, run `cai flow list --json`), create the first flow with `cai flow create --name "<name>" --json`. If one empty flow already exists, rename it and build in it. Never add a second flow for the first piece of work; add flows only for genuinely separate canvases.
32
-
33
- 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
-
35
- To orient inside a workflow, prefer one call over many:
36
-
37
- ```bash
38
- cai workflow outline --json
39
- ```
40
-
41
- `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.
42
-
43
- ## Build protocol
44
-
45
- 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.
46
- 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.
47
- 3. Create or select a flow. Define flow inputs and outputs before nodes that derive props from them.
48
- 4. Build in execution order. After each material change, read it back with the corresponding `get`, `props`, `status`, or `list` command.
49
- 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.
50
- 6. Test on the development rail. Debug every failed or suspicious node; a green top-level status alone is insufficient.
51
- 7. Re-read `cai workflow status`. Publish only when the user asked for a live change or clearly authorized deployment.
52
-
53
- For multi-domain work, read [command-map.md](command-map.md) before editing.
54
-
55
- ## Route specialized work
56
-
57
- Load the narrow skill when the task reaches that surface:
58
-
59
- - Node discovery, initialization, connections, props, or wiring: `controllerai-node-config`
60
- - Dynamic values or conditions: `controllerai-expressions`
61
- - Router, If/Else, loops, joins, or subflows: `controllerai-flow-control`
62
- - Test execution or debugging: `controllerai-runs`
63
- - Scheduled, webhook, or integration events: `controllerai-triggers`
64
- - Schemas or records: `controllerai-data`
65
- - Ask AI or Agent nodes: `controllerai-ai-nodes`
66
- - User-facing agents and their workflow tools: `controllerai-agents`
67
-
68
- ## Lifecycle rules
69
-
70
- - All graph edits target development. Live remains unchanged until `cai workflow publish`.
71
- - 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.
72
- - 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.
73
- - A workflow contains flows; a flow is one canvas. Do not confuse their IDs.
74
- - 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.
75
- - Name nodes after the data they produce. Downstream input bindings are seeded from that name when wired.
76
- - Use `cai workflow save --name "<checkpoint>"` before a risky rewrite. Named saves and state renames work on every plan.
77
-
78
- ```bash
79
- cai workflow history --json
80
- cai workflow history --group <groupId> --json
81
- cai workflow restore --state <stateId> --json
82
- ```
83
-
84
- - **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.
85
- - **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.
86
- - Treat validation warning and error counts as status only. Never write them or their messages into unrelated workflow properties.
87
- - On a conflict, re-read current state and reapply intent. Do not replay stale IDs or whole documents.
88
- - 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.
89
- - **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.
90
- - **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.
91
- - **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.
92
- - Never silently weaken the request to make a test pass. Report an unsupported capability or ask about a real product decision.
93
-
94
- ## Before you finish
95
-
96
- Before claiming success, verify all of the following:
97
-
98
- ```bash
99
- cai workflow outline --json
100
- cai workflow validate --json
101
- cai workflow status --json
102
- cai flow get <flowId> --json
103
- cai run flow <flowId> --inputs <values.json> --json
104
- ```
105
-
106
- MCP: pass the parsed values in `inputs` and set `waitSeconds` on `run_flow`.
107
-
108
- Then confirm:
109
-
110
- - **`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.
111
- - Required node connections and props are complete.
112
- - Expressions compiled and their resolved configs are non-null.
113
- - Expected branch or error paths were exercised where practical.
114
- - Flow outputs contain the promised values.
115
- - The reported live/dev state matches what the user asked for.
116
- - Final outline inventory matches the request. Remove only scratch schemas, flows, nodes, and triggers created during abandoned attempts.
117
-
118
- State what was built, what was tested, whether it was published, and any user-owned connection or product choice still pending.