@controllerai/cli 0.2.18 → 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.
- package/dist/api/client.js +32 -0
- package/dist/api/client.js.map +1 -1
- package/dist/commands/agent.js +101 -8
- package/dist/commands/agent.js.map +1 -1
- package/dist/commands/expr.js +3 -10
- package/dist/commands/expr.js.map +1 -1
- package/dist/commands/integration.js +8 -2
- package/dist/commands/integration.js.map +1 -1
- package/dist/commands/workflow.js +7 -6
- package/dist/commands/workflow.js.map +1 -1
- package/dist/errors.js +5 -2
- package/dist/errors.js.map +1 -1
- package/package.json +1 -1
- package/skills/controllerai-agents/SKILL.md +25 -192
- package/skills/controllerai-agents/references/command-reference.md +205 -0
- package/skills/controllerai-ai-nodes/SKILL.md +11 -92
- package/skills/controllerai-ai-nodes/references/command-reference.md +98 -0
- package/skills/controllerai-data/SKILL.md +34 -159
- package/skills/controllerai-data/references/command-reference.md +177 -0
- package/skills/controllerai-expressions/SKILL.md +29 -151
- package/skills/controllerai-expressions/references/command-reference.md +166 -0
- package/skills/controllerai-expressions/references/dsl-and-recipes.md +1 -1
- package/skills/controllerai-flow-control/SKILL.md +21 -160
- package/skills/controllerai-flow-control/references/command-reference.md +171 -0
- package/skills/controllerai-integration-actions/SKILL.md +11 -112
- package/skills/controllerai-integration-actions/references/command-reference.md +118 -0
- package/skills/controllerai-node-config/SKILL.md +18 -178
- package/skills/controllerai-node-config/references/command-reference.md +186 -0
- package/skills/controllerai-runs/SKILL.md +25 -117
- package/skills/controllerai-runs/references/command-reference.md +113 -0
- package/skills/controllerai-start/SKILL.md +36 -67
- package/skills/controllerai-start/references/mcp-tool-map.md +6 -0
- package/skills/controllerai-triggers/SKILL.md +16 -210
- package/skills/controllerai-triggers/references/command-reference.md +215 -0
- package/skills/controllerai-workflows/SKILL.md +24 -104
- package/skills/controllerai-workflows/references/command-reference.md +118 -0
- package/skills/manifest.json +120 -60
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
# Controller AI flow control
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
Choose by intended runtime semantics.
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
- Guard the exact action with node `only-when`; see Conditions.
|
|
8
|
+
- Use If/Else for one path and Router for all matches; see Pick the correct primitive.
|
|
9
|
+
- Keep downstream wiring after node-only skip; see Conditions.
|
|
10
|
+
- Never invent a missing condition or Router order; see If/Else and Router.
|
|
11
|
+
- Build standard loops only with `flow for-each`; see Loops.
|
|
12
|
+
- Converge paths through Join Paths; see Subflows and convergence.
|
|
13
|
+
- Fail missing comparisons closed; keep money paths blocking. See Conditions, Loops, and the error pattern.
|
|
14
|
+
- Never acknowledge validation errors without explicit approval; see `controllerai-workflows` Lifecycle rules.
|
|
15
|
+
|
|
16
|
+
## Pick the correct primitive
|
|
17
|
+
|
|
18
|
+
| Intent | Primitive | Semantics |
|
|
19
|
+
| --- | --- | --- |
|
|
20
|
+
| Skip one action when a condition is false | Node `only-when` | No alternate path |
|
|
21
|
+
| Choose exactly one path | If/Else | First matching branch runs; Else is last |
|
|
22
|
+
| Run every matching path | Router | Conditions are independent; multiple routes may run |
|
|
23
|
+
| Apply work to every list item | `flow for-each` | Atomic loop scaffold with typed item flow |
|
|
24
|
+
| Reuse a typed unit of work once | Run flow/subflow node | Explicit input and output contract |
|
|
25
|
+
| Continue after an action error | Error output or continue-on-error | Error behavior is explicit and testable |
|
|
26
|
+
|
|
27
|
+
Do not substitute one primitive merely because its component is easier to find.
|
|
28
|
+
|
|
29
|
+
## Conditions
|
|
30
|
+
|
|
31
|
+
Before writing any condition:
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
cai expr context <controlNodeId> --json
|
|
35
|
+
cai expr validate <controlNodeId> --mode onlyWhen --js '<boolean expression>' --json
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
For one guarded action:
|
|
39
|
+
|
|
40
|
+
```bash
|
|
41
|
+
cai node only-when <nodeId> --js '<boolean expression>' --json
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
Use `--clear` only when the user's intent is to remove the guard.
|
|
45
|
+
|
|
46
|
+
Guard the action that must skip. Do not substitute If/Else for a node-only skip. Its `only_when_false` does not block ordinary output; downstream remains eligible. Keep wiring. Guard downstream separately or branch if it must also skip.
|
|
47
|
+
|
|
48
|
+
Node `only-when` takes one restricted boolean through `--js` or `--js-file`, or grouped conditions through `--groups-json '[["a","b"],["c"]]'` (inner arrays are AND, outer rows are OR). Root scalar `&&` or `||` inside one expression is unsupported; use `--groups-json` for compound guards. Grouped `string[][]` conditions exist only on branch add/update, with outer rows OR and inner entries AND. Use them only when branch semantics fit. If an exact compound node-only guard is required, report it as unsupported; do not weaken the rule or probe private APIs. For a missing number that must fail `< 5`, use a same-type boundary such as `(flow.unitsLeft ?? 5) < 5`.
|
|
49
|
+
|
|
50
|
+
Choose the primitive by the runtime signal that callers and tests need. A false node `only-when` records `skipReason: "only_when_false"`; a node on an untaken If/Else branch or unmatched Router route records `skipReason: "upstream_skipped"`.
|
|
51
|
+
|
|
52
|
+
## If/Else and Router
|
|
53
|
+
|
|
54
|
+
Discover and initialize the appropriate control component using `controllerai-node-config`, then inspect its exact branch IDs:
|
|
55
|
+
|
|
56
|
+
```bash
|
|
57
|
+
cai branch list <controlNodeId> --json
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
A fresh If/Else already contains one blank `If` branch and an Else branch. The blank condition is a publish/runtime blocker: copy that default branch ID from `branch list` and update it before adding another condition branch. Do not leave the default blank and create a replacement beside it.
|
|
61
|
+
|
|
62
|
+
Never invent a missing condition from node names, current values, or one observed run. If no authoritative platform surface supplies the business rule, leave the branch blank, report the blocker, and ask the user.
|
|
63
|
+
|
|
64
|
+
```bash
|
|
65
|
+
cai branch update <ifElseNodeId> \
|
|
66
|
+
--route <defaultIfBranchId> \
|
|
67
|
+
--name "<meaning>" \
|
|
68
|
+
--js '<boolean expression>' \
|
|
69
|
+
--json
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
Add another condition only when the decision needs another non-Else case. Router routes are independent, so update an existing blank route or add each intended route explicitly:
|
|
73
|
+
|
|
74
|
+
```bash
|
|
75
|
+
cai branch add <controlNodeId> --name "<meaning>" --js '<boolean expression>' --json
|
|
76
|
+
cai branch update <controlNodeId> --route <routeOrBranchId> --js '<boolean expression>' --json
|
|
77
|
+
cai branch connect <controlNodeId> --route <routeOrBranchId> --to <targetNodeId> --flow <flowId> --json
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
For If/Else, order is behavior:
|
|
81
|
+
|
|
82
|
+
```bash
|
|
83
|
+
cai branch reorder <ifElseNodeId> --order <conditionId1,conditionId2> --json
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
List every condition branch exactly once and omit Else; the operation keeps Else last. Router routes cannot be reordered because every match runs. Do not simulate order by deleting a route or serializing its downstream nodes. Leave the fan-out unchanged unless the user explicitly authorizes a redesign.
|
|
87
|
+
|
|
88
|
+
After edits, run `cai branch list` again. Treat its warnings about missing conditions or unwired paths as blockers: an unwired selected path can end with an apparently green execution.
|
|
89
|
+
|
|
90
|
+
## Loops
|
|
91
|
+
|
|
92
|
+
Never assemble the standard per-item subflow pattern by hand:
|
|
93
|
+
|
|
94
|
+
```bash
|
|
95
|
+
cai node get <listProducingNodeId> --json
|
|
96
|
+
cai flow for-each \
|
|
97
|
+
--flow <parentFlowId> \
|
|
98
|
+
--from <listProducingNodeId> \
|
|
99
|
+
--source-output <exactOutputId> \
|
|
100
|
+
--name "<item flow name>" \
|
|
101
|
+
--item-type <text|number|date|boolean|custom.type> \
|
|
102
|
+
--json
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
Use repeatable `--item-field <id:type[:display]>` only when creating a new `custom.*` item type.
|
|
106
|
+
|
|
107
|
+
Copy `--source-output` from the selected node's exact `outputs[].id`. It is an opaque ID, not `displayName`, and there is no first-output default. This matters for Router, If/Else, and error outputs as well as ordinary action nodes.
|
|
108
|
+
|
|
109
|
+
- If the source's whole output is the list, omit both `--list-field` and `--list-js`.
|
|
110
|
+
- If the list is nested in the source payload, use `--list-field` with the dot-delimited path below `.data`; the operation derives the not-yet-created loop input binding deterministically.
|
|
111
|
+
- Use `--list-js` only for an advanced exact expression. For multiline or shell-sensitive source, use `--js-file <path|->` instead. Both are mutually exclusive with `--list-field` and with each other; copy the wrapper/binding shape from expression context rather than guessing it.
|
|
112
|
+
|
|
113
|
+
MCP: pass expression source inline as `listJs` to `flow_for_each_scaffold`; the server cannot read a local `--js-file` path.
|
|
114
|
+
|
|
115
|
+
- The runtime cap defaults to 500 items and accepts 1 through 10000. Set `--max-items` explicitly when the product requirement differs. The scaffold operation creates the core graph first, then materializes and verifies this optional prop. The cap is all-or-nothing at runtime: a list larger than the cap throws and NOTHING iterates — there is no partial truncation.
|
|
116
|
+
|
|
117
|
+
Changing an existing loop: update its loop-node props directly:
|
|
118
|
+
|
|
119
|
+
```bash
|
|
120
|
+
cai node set <loopNodeId> --prop maxItems --value <n> --json
|
|
121
|
+
cai node set <loopNodeId> --prop continueOnIterationError --value true --json
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
MCP: use `node_prop_set` for both writes.
|
|
125
|
+
|
|
126
|
+
This is not `cai node continue-on-error`, which configures the node-level Error output — a different feature.
|
|
127
|
+
|
|
128
|
+
Read every returned warning. A list/item type mismatch means the scaffold is not verified even though it was created. Follow the returned `nextSteps` in order.
|
|
129
|
+
|
|
130
|
+
Inside loop mappings, `item` exists only where context exposes it. Inside the body flow, use its `flow.<itemInput>` binding. Downstream loop results are iteration records whose declared child outputs are under `.outputs`.
|
|
131
|
+
|
|
132
|
+
Loops run sequentially. `--continue-on-error` applies to a failed child iteration; a list expression or mapping/config expression that fails before the child starts still aborts the loop. Test empty, one-item, several-item, over-limit, and intended iteration-error behavior.
|
|
133
|
+
|
|
134
|
+
Never enable continue-on-error on a money path; charges, purchases, transfers, refunds, and other spend must fail fast.
|
|
135
|
+
|
|
136
|
+
## Subflows and convergence
|
|
137
|
+
|
|
138
|
+
Define the called flow's inputs and outputs first. Then initialize a Run flow component and bind it:
|
|
139
|
+
|
|
140
|
+
```bash
|
|
141
|
+
cai node set-flow <runFlowNodeId> --flow <calledFlowId> --json
|
|
142
|
+
cai node props <runFlowNodeId> --json
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
MCP: `cai node set-flow` maps to `node_subflow_set`.
|
|
146
|
+
|
|
147
|
+
Setting the target flow creates mapping props from the target's current inputs. If those inputs later change, run `set-flow` again and reconfigure mappings.
|
|
148
|
+
|
|
149
|
+
For one action after whichever exclusive branch runs, use `registry_flow-merge` (Join Paths) in `chooseActivePath` mode, then place the shared action after it. Never wire several branches directly to an ordinary node or duplicate the shared action. Follow the exact recipe in [patterns.md](patterns.md) and test each branch once.
|
|
150
|
+
|
|
151
|
+
Return semantics: a flow that should return data needs `registry_flow-return-response`; without it callers see empty success. Declare outputs first, initialize that exact component after the producer, then bind its generated prop with `cai expr set`. Do not guess component keys. See [patterns.md](patterns.md). Multiple completed Return nodes merge, with later values overwriting earlier ones; design for one Return per path unless merging is intended.
|
|
152
|
+
|
|
153
|
+
Deleting a flow removes its graph, contract, triggers, and caller links. Validate and restore if mistaken. Turning `continueOnError` off also deletes its Error output and edges; validate and restore likewise.
|
|
154
|
+
|
|
155
|
+
Read [patterns.md](patterns.md) for concise canonical patterns.
|
|
156
|
+
|
|
157
|
+
## Before you finish
|
|
158
|
+
|
|
159
|
+
```bash
|
|
160
|
+
cai branch list <controlNodeId> --json
|
|
161
|
+
cai workflow validate --json
|
|
162
|
+
cai run flow <flowId> --inputs <values.json> --json
|
|
163
|
+
cai exec tree <workflowExecutionId> --json
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
- Every branch has the intended condition and a wired target.
|
|
167
|
+
- If/Else ordering matches priority and Else remains last.
|
|
168
|
+
- Router fan-out is intentional when more than one condition can be true.
|
|
169
|
+
- Loop item type and list expression compile against actual source data.
|
|
170
|
+
- Expected true, false/Else, empty-list, one-item, several-item, over-limit, and error paths are tested.
|
|
171
|
+
- The execution tree shows intended `only_when_false` or `upstream_skipped` reasons and no unexplained missing nodes.
|
|
@@ -1,125 +1,24 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: controllerai-integration-actions
|
|
3
|
-
description: Discover
|
|
3
|
+
description: Discover and attach ready integration actions directly to Controller AI agents, configure connections and dynamic properties, and verify external app operations. Use when one existing action satisfies an agent capability.
|
|
4
4
|
---
|
|
5
5
|
|
|
6
|
-
#
|
|
6
|
+
# Ready actions as agent tools
|
|
7
7
|
|
|
8
|
-
|
|
8
|
+
A ready integration action is one existing operation: search a service, read an object, create a record or send a message. Attach it directly to an agent when that operation is the capability. Use a workflow tool when you also need deterministic validation, multiple ordered steps, transformation, persistence or a reusable typed contract.
|
|
9
9
|
|
|
10
|
-
|
|
10
|
+
## Discover and configure
|
|
11
11
|
|
|
12
|
-
|
|
12
|
+
Search by the intended operation, inspect the matching integration, then read its exact action key and properties. Prefer capability evidence over a similar integration name. Native actions and external provider actions can have different authorization requirements.
|
|
13
13
|
|
|
14
|
-
|
|
15
|
-
- Capture the exact integration, action, connection, and tool IDs. See Discover exact identities.
|
|
16
|
-
- Decide confirmation before attachment, especially for writes or spend. See Decide approval before attaching.
|
|
17
|
-
- Verify persisted direct-action events, not a workflow execution ID. See Verify through the hosted agent.
|
|
14
|
+
Select an existing matching connection and verify its identity. If a new connection is needed, return the connection URL and let the user complete provider authorization. Never request provider credentials in chat. An “active” stored connection still needs a representative action test to prove current authorization.
|
|
18
15
|
|
|
19
|
-
|
|
16
|
+
Attach the action with its exact integration/action/connection and a description that tells the agent when to use it. Inspect configurable inputs and reload dependent options after selector changes. Choose the tool's runtime confirmation setting for the requested experience.
|
|
20
17
|
|
|
21
|
-
|
|
18
|
+
## Verify the attached capability
|
|
22
19
|
|
|
23
|
-
|
|
20
|
+
Read the saved tool list and test in a draft conversation. Inspect the chosen action, arguments, terminal result and intended external effect. A direct action does not create a workflow execution. For a failed or uncertain mutation, inspect external state before repeating it.
|
|
24
21
|
|
|
25
|
-
|
|
22
|
+
Connection rebinding, detachment or revocation can affect Live independently of publishing the agent. If the user requested release, publish the updated agent configuration after testing and verify a Live conversation. Do not publish merely because the draft is ready.
|
|
26
23
|
|
|
27
|
-
|
|
28
|
-
cai integration search "<app or capability>" --json
|
|
29
|
-
cai integration actions "<operation>" --integration <integrationSlug> --json
|
|
30
|
-
cai integration action --integration <integrationSlug> --key <actionKey> --json
|
|
31
|
-
```
|
|
32
|
-
|
|
33
|
-
Preserve each returned `nodeSlug` and `key` pair exactly, then inspect that action's static props before using it. Never derive either identifier from a display label. Narrow the query or raise `--limit` when more matches exist.
|
|
34
|
-
|
|
35
|
-
## Select a connection
|
|
36
|
-
|
|
37
|
-
```bash
|
|
38
|
-
cai connection list --integration <integrationSlug> --json
|
|
39
|
-
```
|
|
40
|
-
|
|
41
|
-
Use an active connection whose `integration` exactly matches the integration slug. If none exists:
|
|
42
|
-
|
|
43
|
-
```bash
|
|
44
|
-
cai connection connect <integrationSlug>
|
|
45
|
-
```
|
|
46
|
-
|
|
47
|
-
MCP: call `connection_connect_url`, show its `url` as a markdown link, ask the user to finish, then confirm with `connection_list` using its `integration`; it has no `open` or `wait` parameter.
|
|
48
|
-
|
|
49
|
-
The connection handoff keeps provider credentials out of the agent context. The CLI may open the URL; MCP returns it. Re-list connections after the user finishes, then attach the action.
|
|
50
|
-
|
|
51
|
-
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`).
|
|
52
|
-
Deleting a connection immediately removes authorization from bound nodes and agent tools.
|
|
53
|
-
|
|
54
|
-
A missing connection is never a reason to substitute `registry_http-http-request` for a catalog component. For a workflow node, add the real component and leave it unconnected; `missingConnection: true` is a valid handoff state. For a direct action, preserve the selected integration and action and stop at the connection handoff. Give the user the returned connection URL; on CLI, `cai connection connect <slug>` obtains it. A raw endpoint mentioned by the user is background context, not an instruction to hand-roll the call.
|
|
55
|
-
|
|
56
|
-
## Decide approval before attaching
|
|
57
|
-
|
|
58
|
-
Attached actions run without a human approval step unless `requireConfirmation` is `true`. When attaching an action that sends, posts, spends, or deletes, choose `true` or explicitly tell the user that it will run unattended. Mention the confirmation choice in the report to the user.
|
|
59
|
-
|
|
60
|
-
- Prefer confirmation for permission changes, irreversible writes, or an ambiguous destination.
|
|
61
|
-
- Usually omit confirmation for read-only retrieval and low-risk, reversible operations the user clearly asked the agent to perform autonomously.
|
|
62
|
-
|
|
63
|
-
```bash
|
|
64
|
-
cai agent add-action <agentId> \
|
|
65
|
-
--integration <integrationSlug> \
|
|
66
|
-
--action <actionKey> \
|
|
67
|
-
--connection <connectionId> \
|
|
68
|
-
--description "Use when ..." \
|
|
69
|
-
--require-confirmation \
|
|
70
|
-
--json
|
|
71
|
-
```
|
|
72
|
-
|
|
73
|
-
MCP: call `agent_tool_action_add`; `requireConfirmation` is optional and defaults to `false`. On CLI, `--require-confirmation` selects `true` and omission preserves the `false` default. Do not attach the same action twice.
|
|
74
|
-
|
|
75
|
-
Read the saved grant back:
|
|
76
|
-
|
|
77
|
-
```bash
|
|
78
|
-
cai agent tools <agentId> --json
|
|
79
|
-
```
|
|
80
|
-
|
|
81
|
-
Verify `toolType`, integration, action key, connection, schema tier, description, and confirmation policy. The hosted runtime configures dynamic action properties when it invokes the action; the builder does not preconfigure runtime-only action arguments here.
|
|
82
|
-
|
|
83
|
-
To rebind the live authorization grant or change a versioned policy:
|
|
84
|
-
|
|
85
|
-
```bash
|
|
86
|
-
cai agent update-tool <agentId> --tool <toolId> --connection <connectionId> --json
|
|
87
|
-
cai agent update-tool <agentId> --tool <toolId> --require-confirmation --json
|
|
88
|
-
cai agent update-tool <agentId> --tool <toolId> --no-confirmation --json
|
|
89
|
-
```
|
|
90
|
-
|
|
91
|
-
MCP: call `agent_tool_update`; use `connectionId` and `requireConfirmation: true` or `requireConfirmation: false`.
|
|
92
|
-
|
|
93
|
-
`--connection` can redirect the published action immediately because authorization is live-bound. Description and confirmation-policy edits remain draft changes until the agent is published.
|
|
94
|
-
|
|
95
|
-
## Verify through the hosted agent
|
|
96
|
-
|
|
97
|
-
Use a representative draft conversation:
|
|
98
|
-
|
|
99
|
-
```bash
|
|
100
|
-
cai agent test <agentId> --draft --message "<request>" --json
|
|
101
|
-
cai agent conversation history <conversationId> --json
|
|
102
|
-
```
|
|
103
|
-
|
|
104
|
-
MCP: call `agent_test` with `rail: draft` and `waitSeconds`.
|
|
105
|
-
|
|
106
|
-
A direct action runs inline and does not create a workflow execution ID. Evidence is the persisted conversation, its direct-action tool/run events, the returned result, and any observed external side effect. Never invent a workflow execution ID for it.
|
|
107
|
-
|
|
108
|
-
If confirmation is required, inspect the pending action and exact arguments before approving or denying its request. A successful assistant reply alone does not prove the intended action ran.
|
|
109
|
-
|
|
110
|
-
## Publishing and sharing semantics
|
|
111
|
-
|
|
112
|
-
Publishing snapshots the action identity, description, and approval policy into the agent version. The connection and authorization grant remain live security bindings: rebinding can redirect the published action, while breakage, revocation, or detachment can stop it immediately without another agent publish. Detachment also removes the draft tool; publish afterward to remove the unavailable tool from the published list.
|
|
113
|
-
|
|
114
|
-
Organization members use the published agent, never its mutable draft. Direct actions run through the agent owner's connected external account. Controller AI usage draws from the organization's shared usage pool, regardless of which member calls the agent. State that credential boundary before organization sharing.
|
|
115
|
-
|
|
116
|
-
## Before you finish
|
|
117
|
-
|
|
118
|
-
```bash
|
|
119
|
-
cai agent tools <agentId> --json
|
|
120
|
-
cai agent conversation history <conversationId> --json
|
|
121
|
-
```
|
|
122
|
-
|
|
123
|
-
- Tools must show one intended direct attachment with the exact returned identities, connection, description, and confirmation policy.
|
|
124
|
-
- History must contain the persisted action event, exact arguments, and result; confirm any requested external effect separately.
|
|
125
|
-
- No wrapper workflow should exist unless the capability actually required orchestration or reuse.
|
|
24
|
+
Discovery, attachment, update and removal commands: [reference](references/command-reference.md).
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
# Controller AI integration actions
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
Ready integration actions give a hosted agent one app operation without first building a workflow. Use the canonical operations below through the selected transport; do not call Controller AI REST routes directly.
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
- Attach one existing app operation directly; never wrap it in a one-node workflow. See Choose direct action or workflow.
|
|
8
|
+
- Capture the exact integration, action, connection, and tool IDs. See Discover exact identities.
|
|
9
|
+
- Decide confirmation before attachment, especially for writes or spend. See Decide approval before attaching.
|
|
10
|
+
- Verify persisted direct-action events, not a workflow execution ID. See Verify through the hosted agent.
|
|
11
|
+
|
|
12
|
+
## Choose direct action or workflow
|
|
13
|
+
|
|
14
|
+
Use a direct action for one existing operation such as sending one message, creating one record, or adding one row.
|
|
15
|
+
|
|
16
|
+
Use a workflow tool instead when the capability needs multiple operations, transformations, branches, loops, durable state, triggers, a custom typed contract, or reuse outside the agent. Do not build a one-node workflow when the same ready action already fits.
|
|
17
|
+
|
|
18
|
+
## Discover exact identities
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
cai integration search "<app or capability>" --json
|
|
22
|
+
cai integration actions "<operation>" --integration <integrationSlug> --json
|
|
23
|
+
cai integration action --integration <integrationSlug> --key <actionKey> --json
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
Preserve each returned `nodeSlug` and `key` pair exactly, then inspect that action's static props before using it. Never derive either identifier from a display label. Narrow the query or raise `--limit` when more matches exist.
|
|
27
|
+
|
|
28
|
+
## Select a connection
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
cai connection list --integration <integrationSlug> --json
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
Use an active connection whose `integration` exactly matches the integration slug. If none exists:
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
cai connection connect <integrationSlug>
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
MCP: call `connection_connect_url`, show its `url` as a markdown link, ask the user to finish, then confirm with `connection_list` using its `integration`; it has no `open` or `wait` parameter.
|
|
41
|
+
|
|
42
|
+
The connection handoff keeps provider credentials out of the agent context. The CLI may open the URL; MCP returns it. Re-list connections after the user finishes, then attach the action.
|
|
43
|
+
|
|
44
|
+
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`).
|
|
45
|
+
Deleting a connection immediately removes authorization from bound nodes and agent tools.
|
|
46
|
+
|
|
47
|
+
A missing connection is never a reason to substitute `registry_http-http-request` for a catalog component. For a workflow node, add the real component and leave it unconnected; `missingConnection: true` is a valid handoff state. For a direct action, preserve the selected integration and action and stop at the connection handoff. Give the user the returned connection URL; on CLI, `cai connection connect <slug>` obtains it. A raw endpoint mentioned by the user is background context, not an instruction to hand-roll the call.
|
|
48
|
+
|
|
49
|
+
## Decide approval before attaching
|
|
50
|
+
|
|
51
|
+
Attached actions run without a human approval step unless `requireConfirmation` is `true`. When attaching an action that sends, posts, spends, or deletes, choose `true` or explicitly tell the user that it will run unattended. Mention the confirmation choice in the report to the user.
|
|
52
|
+
|
|
53
|
+
- Prefer confirmation for permission changes, irreversible writes, or an ambiguous destination.
|
|
54
|
+
- Usually omit confirmation for read-only retrieval and low-risk, reversible operations the user clearly asked the agent to perform autonomously.
|
|
55
|
+
|
|
56
|
+
```bash
|
|
57
|
+
cai agent add-action <agentId> \
|
|
58
|
+
--integration <integrationSlug> \
|
|
59
|
+
--action <actionKey> \
|
|
60
|
+
--connection <connectionId> \
|
|
61
|
+
--description "Use when ..." \
|
|
62
|
+
--require-confirmation \
|
|
63
|
+
--json
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
MCP: call `agent_tool_action_add`; `requireConfirmation` is optional and defaults to `false`. On CLI, `--require-confirmation` selects `true` and omission preserves the `false` default. Do not attach the same action twice.
|
|
67
|
+
|
|
68
|
+
Read the saved grant back:
|
|
69
|
+
|
|
70
|
+
```bash
|
|
71
|
+
cai agent tools <agentId> --json
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
Verify `toolType`, integration, action key, connection, schema tier, description, and confirmation policy. The hosted runtime configures dynamic action properties when it invokes the action; the builder does not preconfigure runtime-only action arguments here.
|
|
75
|
+
|
|
76
|
+
To rebind the live authorization grant or change a versioned policy:
|
|
77
|
+
|
|
78
|
+
```bash
|
|
79
|
+
cai agent update-tool <agentId> --tool <toolId> --connection <connectionId> --json
|
|
80
|
+
cai agent update-tool <agentId> --tool <toolId> --require-confirmation --json
|
|
81
|
+
cai agent update-tool <agentId> --tool <toolId> --no-confirmation --json
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
MCP: call `agent_tool_update`; use `connectionId` and `requireConfirmation: true` or `requireConfirmation: false`.
|
|
85
|
+
|
|
86
|
+
`--connection` can redirect the published action immediately because authorization is live-bound. Description and confirmation-policy edits remain draft changes until the agent is published.
|
|
87
|
+
|
|
88
|
+
## Verify through the hosted agent
|
|
89
|
+
|
|
90
|
+
Use a representative draft conversation:
|
|
91
|
+
|
|
92
|
+
```bash
|
|
93
|
+
cai agent test <agentId> --draft --message "<request>" --json
|
|
94
|
+
cai agent conversation history <conversationId> --json
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
MCP: call `agent_test` with `rail: draft` and `waitSeconds`.
|
|
98
|
+
|
|
99
|
+
A direct action runs inline and does not create a workflow execution ID. Evidence is the persisted conversation, its direct-action tool/run events, the returned result, and any observed external side effect. Never invent a workflow execution ID for it.
|
|
100
|
+
|
|
101
|
+
If confirmation is required, inspect the pending action and exact arguments before approving or denying its request. A successful assistant reply alone does not prove the intended action ran.
|
|
102
|
+
|
|
103
|
+
## Publishing and sharing semantics
|
|
104
|
+
|
|
105
|
+
Publishing snapshots the action identity, description, and approval policy into the agent version. The connection and authorization grant remain live security bindings: rebinding can redirect the published action, while breakage, revocation, or detachment can stop it immediately without another agent publish. Detachment also removes the draft tool; publish afterward to remove the unavailable tool from the published list.
|
|
106
|
+
|
|
107
|
+
Organization members use the published agent, never its mutable draft. Direct actions run through the agent owner's connected external account. Controller AI usage draws from the organization's shared usage pool, regardless of which member calls the agent. State that credential boundary before organization sharing.
|
|
108
|
+
|
|
109
|
+
## Before you finish
|
|
110
|
+
|
|
111
|
+
```bash
|
|
112
|
+
cai agent tools <agentId> --json
|
|
113
|
+
cai agent conversation history <conversationId> --json
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
- Tools must show one intended direct attachment with the exact returned identities, connection, description, and confirmation policy.
|
|
117
|
+
- History must contain the persisted action event, exact arguments, and result; confirm any requested external effect separately.
|
|
118
|
+
- No wrapper workflow should exist unless the capability actually required orchestration or reuse.
|
|
@@ -1,192 +1,32 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: controllerai-node-config
|
|
3
|
-
description: Discover
|
|
3
|
+
description: Discover and configure Controller AI workflow action nodes, dynamic properties, connections, optional fields, output types and graph wiring. Use when assembling or repairing a concrete step in a flow.
|
|
4
4
|
---
|
|
5
5
|
|
|
6
|
-
#
|
|
6
|
+
# Workflow nodes
|
|
7
7
|
|
|
8
|
-
|
|
8
|
+
A node is a step in a flow: a ready integration action, native data/file/AI action, or a control-flow construct. Its component defines properties, required authorization and output shape. The saved node is an instance configured for this workflow.
|
|
9
9
|
|
|
10
|
-
|
|
10
|
+
## Discover by capability
|
|
11
11
|
|
|
12
|
-
|
|
12
|
+
Use `integration_search` and `integration_action_list` to search for the intended action, then inspect the exact integration slug and action key. Integration display names are not component identities. For native storage use `registry_data`; for generated files inspect native file actions; for web research inspect available search actions and connections.
|
|
13
13
|
|
|
14
|
-
|
|
14
|
+
`integration_action_get` describes static properties. Some actions add dependent properties after a type, object, sheet or other selector is chosen. Saved connection status indicates an available binding; a successful representative provider request is the evidence it still works.
|
|
15
15
|
|
|
16
|
-
|
|
17
|
-
cai integration actions "<capability>" --json
|
|
18
|
-
cai integration action --integration <nodeSlug> --key <nodeKey> --json
|
|
19
|
-
```
|
|
16
|
+
## Configure in dependency order
|
|
20
17
|
|
|
21
|
-
|
|
18
|
+
1. Add the action to the intended flow using its returned exact key. Name the node after its purpose or produced value.
|
|
19
|
+
2. Bind a required connection. Use `connection_connect_url` only when the user needs to connect an account; never request provider credentials in chat.
|
|
20
|
+
3. Set selectors first, reload properties with `node_prop_list`, then read the resulting schema.
|
|
21
|
+
4. Enable optional fields before setting them. Omission and an enabled empty value can have different effects, especially for updates.
|
|
22
|
+
5. Set literal properties with `value`; use `js` for computed values. Read `expr_context` for expected types and available inputs.
|
|
23
|
+
6. Wire the source output channel to the destination. Use returned output/port IDs; “main” and “error” are distinct channels.
|
|
24
|
+
7. Inspect `node_status` and `node_get`, test the step or complete flow, then verify the saved output type and downstream mapping.
|
|
22
25
|
|
|
23
|
-
|
|
24
|
-
cai integration search "<integration>" --actions --json
|
|
25
|
-
cai integration actions "<action>" --integration <nodeSlug> --json
|
|
26
|
-
```
|
|
26
|
+
Use the supported initial configuration batch when creating a node: `node_add` accepts its name, connection, upstream wiring, optional fields and a `props` map together. Direct values are literals; an advanced entry such as `"name": {"valueJs": "flow.name"}` compiles a typed expression. Put selectors such as `dataType` first so dependent fields exist. Inspect the returned `propsReadback` and readiness, then fix only rejected or missing fields. This avoids one call per property when repeating a proven CRUD pattern. Use flow scaffolds for loops and return mappings where they fit.
|
|
27
27
|
|
|
28
|
-
|
|
28
|
+
A static output contract should remain stable after a run. A dynamic action may learn its output shape from a representative test; re-read its output/context before authoring downstream fields. Do not overwrite a known contract with an unrelated inferred schema just to remove a warning.
|
|
29
29
|
|
|
30
|
-
|
|
30
|
+
Use `controllerai-flow-control` for branches/loops and `controllerai-ai-nodes` for AI output configuration. Layout once after a group of structural changes.
|
|
31
31
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
```bash
|
|
35
|
-
cai connection list --node <nodeSlug> --json
|
|
36
|
-
```
|
|
37
|
-
|
|
38
|
-
- One active connection: use its exact `id` as the `connectionId`.
|
|
39
|
-
- Several: use an explicit user preference; otherwise ask which account.
|
|
40
|
-
- 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.
|
|
41
|
-
|
|
42
|
-
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`.
|
|
43
|
-
|
|
44
|
-
After they confirm, run `cai connection list --integration <nodeSlug> --json` and bind the new ID with `cai node set-connection <nodeId> --connection <connectionId>`.
|
|
45
|
-
|
|
46
|
-
Never substitute a connection from a similar slug.
|
|
47
|
-
|
|
48
|
-
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`).
|
|
49
|
-
Deleting a connection immediately removes authorization from bound nodes and agent tools.
|
|
50
|
-
|
|
51
|
-
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.
|
|
52
|
-
|
|
53
|
-
### 3. Initialize once
|
|
54
|
-
|
|
55
|
-
```bash
|
|
56
|
-
cai node init \
|
|
57
|
-
--flow <flowId> \
|
|
58
|
-
--node <nodeSlug> \
|
|
59
|
-
--key <nodeKey> \
|
|
60
|
-
--name "<data this node produces>" \
|
|
61
|
-
--connection <connectionId> \
|
|
62
|
-
--after <upstreamNodeId> \
|
|
63
|
-
--json
|
|
64
|
-
```
|
|
65
|
-
|
|
66
|
-
MCP: use `node_add`; `cai node init` is the CLI alias of `cai node add`.
|
|
67
|
-
|
|
68
|
-
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.
|
|
69
|
-
|
|
70
|
-
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.
|
|
71
|
-
|
|
72
|
-
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.
|
|
73
|
-
|
|
74
|
-
### 4. Follow readiness, not guesses
|
|
75
|
-
|
|
76
|
-
```bash
|
|
77
|
-
cai node status <nodeId> --json
|
|
78
|
-
cai node props <nodeId> --json
|
|
79
|
-
```
|
|
80
|
-
|
|
81
|
-
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.
|
|
82
|
-
|
|
83
|
-
Work through blockers in this order:
|
|
84
|
-
|
|
85
|
-
1. Missing connection
|
|
86
|
-
2. Required selector props with `reloadProps`
|
|
87
|
-
3. Newly revealed required props
|
|
88
|
-
4. Static and remote-option props
|
|
89
|
-
5. Wiring required for expressions
|
|
90
|
-
6. Expressions
|
|
91
|
-
7. Unresolved output type
|
|
92
|
-
|
|
93
|
-
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.
|
|
94
|
-
|
|
95
|
-
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.
|
|
96
|
-
|
|
97
|
-
### 5. Set props safely
|
|
98
|
-
|
|
99
|
-
Static value:
|
|
100
|
-
|
|
101
|
-
```bash
|
|
102
|
-
cai node set <nodeId> --prop <exactName> --value '<literal-or-json>' --json
|
|
103
|
-
```
|
|
104
|
-
|
|
105
|
-
MCP: use `node_prop_set` with `value`; it also handles expression writes through `js`.
|
|
106
|
-
|
|
107
|
-
Optional prop:
|
|
108
|
-
|
|
109
|
-
```bash
|
|
110
|
-
cai node optional-props <nodeId> --json
|
|
111
|
-
cai node set <nodeId> --prop <exactName> --value '<literal-or-json>' --json
|
|
112
|
-
# or: cai expr set <nodeId> --prop <exactName> --js '<expression>' --json
|
|
113
|
-
```
|
|
114
|
-
|
|
115
|
-
MCP: `cai expr set` is the `js` form of `node_prop_set`.
|
|
116
|
-
|
|
117
|
-
`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.
|
|
118
|
-
|
|
119
|
-
MCP: use `node_optional_prop_set` with `enabled: false` to disable or `enabled: true` to enable.
|
|
120
|
-
|
|
121
|
-
Remote or dynamic option:
|
|
122
|
-
|
|
123
|
-
```bash
|
|
124
|
-
cai node options <nodeId> --prop <exactName> --query "<specific label>" --json
|
|
125
|
-
cai node set <nodeId> \
|
|
126
|
-
--prop <exactName> \
|
|
127
|
-
--value '<returned value>' \
|
|
128
|
-
--label '<returned label>' \
|
|
129
|
-
--json
|
|
130
|
-
```
|
|
131
|
-
|
|
132
|
-
`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.
|
|
133
|
-
|
|
134
|
-
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.
|
|
135
|
-
|
|
136
|
-
When an earlier selector makes the prop `dynamic_upstream`, no option list exists. Use a known exact ID or an expression:
|
|
137
|
-
|
|
138
|
-
```bash
|
|
139
|
-
cai node set <nodeId> --prop <exactName> --value '<exact-id>' --label '<display label>' --json
|
|
140
|
-
cai node set <nodeId> --prop <exactName> --js '<expression>' --json
|
|
141
|
-
```
|
|
142
|
-
|
|
143
|
-
`--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.
|
|
144
|
-
|
|
145
|
-
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.
|
|
146
|
-
|
|
147
|
-
For dynamic values, load `controllerai-expressions` and prefer `cai expr set`.
|
|
148
|
-
|
|
149
|
-
### 6. Wire and verify
|
|
150
|
-
|
|
151
|
-
Ordinary outputs:
|
|
152
|
-
|
|
153
|
-
```bash
|
|
154
|
-
cai node connect --flow <flowId> --from <sourceNodeId> --to <targetNodeId> --output main --json
|
|
155
|
-
```
|
|
156
|
-
|
|
157
|
-
Use `--output error` only for the automatic error path. Router and If/Else outputs require `cai branch connect` from the flow-control skill.
|
|
158
|
-
|
|
159
|
-
Finish with:
|
|
160
|
-
|
|
161
|
-
```bash
|
|
162
|
-
cai node status <nodeId> --json
|
|
163
|
-
cai run node <nodeId> --inputs <values.json> --json
|
|
164
|
-
```
|
|
165
|
-
|
|
166
|
-
MCP: `run_node` takes the parsed `inputs` object and `waitSeconds` (default 60, max 120).
|
|
167
|
-
|
|
168
|
-
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.
|
|
169
|
-
|
|
170
|
-
MCP: `run_flow` takes the parsed `inputs` object and `waitSeconds` (default 60, max 120).
|
|
171
|
-
|
|
172
|
-
If a dynamic provider action cannot be run but its response is documented, declare an unverified output contract:
|
|
173
|
-
|
|
174
|
-
```bash
|
|
175
|
-
cai node declare-output <nodeId> --sample-file provider-response.json --json
|
|
176
|
-
```
|
|
177
|
-
|
|
178
|
-
MCP: call `node_output_type_declare` with the parsed provider response in `sample`; the server cannot read `provider-response.json`.
|
|
179
|
-
|
|
180
|
-
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.
|
|
181
|
-
|
|
182
|
-
Read [references/prop-and-readiness.md](references/prop-and-readiness.md) when a prop is dynamic, option-backed, expression-capable, or unexpectedly absent.
|
|
183
|
-
|
|
184
|
-
## Hard rules
|
|
185
|
-
|
|
186
|
-
- Configure props in returned order; later props may depend on earlier values.
|
|
187
|
-
- Never write a prop absent from `node props`.
|
|
188
|
-
- Let `node set` or `expr set` auto-enable catalog-only optional props; disable the prop explicitly after a failed write.
|
|
189
|
-
- Wire before authoring an expression that consumes upstream data.
|
|
190
|
-
- Changing a connection invalidates connection-scoped options; re-read props and options.
|
|
191
|
-
- A successful write is not completion. Require read-back plus `node status`.
|
|
192
|
-
- 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.
|
|
32
|
+
Detailed property-setting examples: [command reference](references/command-reference.md). Readiness and dynamic-property behavior: [prop reference](references/prop-and-readiness.md).
|