@oomol-lab/open-flow 0.1.0-beta.56 → 0.1.0-beta.58

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 (36) hide show
  1. package/dist/browser/{createResourceDialog-Btjes3wD.js → createResourceDialog-C23SBjYd.js} +2 -2
  2. package/dist/browser/flow-authoring-node.d.ts +6 -2
  3. package/dist/browser/flow-authoring.js +44 -12
  4. package/dist/browser/flow-change-schema.d.ts +266 -0
  5. package/dist/browser/flow-change.d.ts +5 -0
  6. package/dist/browser/flow-change.js +33 -2
  7. package/dist/browser/{flowChanges-BxutPLYO.js → flowChanges-fBiAeTzR.js} +954 -487
  8. package/dist/browser/{flowWorkspace-Dg4mqfa6.js → flowWorkspace-MqcEfg7T.js} +3 -3
  9. package/dist/browser/{icons-p2A9zs8t.js → icons-6oQ8Q9Wm.js} +4298 -4252
  10. package/dist/browser/preview.js +354 -36
  11. package/dist/browser/workbench.js +21 -10
  12. package/dist/browser/{workbenchSelect-LRp_Xjeq.js → workbenchSelect-DpLbIr29.js} +1 -1
  13. package/dist/common/authoring.d.ts +207 -0
  14. package/dist/common/authoringSchema.d.ts +1293 -0
  15. package/dist/common/control-api-conformance.js +975 -505
  16. package/dist/common/control-api-errors.d.ts +2 -1
  17. package/dist/common/control-api.d.ts +81 -0
  18. package/dist/common/control-api.js +973 -586
  19. package/dist/common/control-requests.d.ts +128 -0
  20. package/dist/common/control-requests.js +3122 -346
  21. package/dist/common/decision.js +12 -2
  22. package/dist/common/flow-encoding.js +12 -2
  23. package/dist/common/flow-semantics.d.ts +9 -0
  24. package/dist/common/flow-semantics.js +28 -3
  25. package/dist/common/integration-trigger.js +12 -2
  26. package/dist/common/lib-DrKav3HG.js +11403 -0
  27. package/dist/common/mcp.d.ts +120 -11
  28. package/dist/common/mcp.js +423 -51
  29. package/dist/common/openapi.js +12 -2
  30. package/dist/common/poll-trigger.js +12 -2
  31. package/dist/common/scheduler.js +12 -2
  32. package/dist/common/webhook-trigger.js +12 -2
  33. package/package.json +7 -1
  34. package/skills/open-flow/SKILL.md +32 -0
  35. package/skills/open-flow/references/flow-authoring.md +356 -0
  36. package/skills/open-flow/references/flow-n8n-conversion.md +196 -0
@@ -6794,7 +6794,7 @@ var decisionQuestion = discriminatedUnion("type", [
6794
6794
  criteria: strings
6795
6795
  })
6796
6796
  ]);
6797
- var managed = object$1({
6797
+ var managedFields = object$1({
6798
6798
  ...ports,
6799
6799
  name: text,
6800
6800
  executor: union([
@@ -6853,7 +6853,8 @@ var managed = object$1({
6853
6853
  }).optional()
6854
6854
  })
6855
6855
  ])
6856
- }).transform(limitDecisionTask);
6856
+ });
6857
+ var managed = managedFields.transform(limitDecisionTask);
6857
6858
  var operand = union([object$1({
6858
6859
  kind: literal("value"),
6859
6860
  value: json.optional(),
@@ -7028,6 +7029,10 @@ var node = union([
7028
7029
  })
7029
7030
  })
7030
7031
  ]);
7032
+ strictObject(condition), strictObject(wait), strictObject(webhook), managedFields.shape.executor.options[0].omit({ kind: true }).strict(), managedFields.shape.executor.options[1].omit({ kind: true }).strict(), managedFields.shape.executor.options[2].omit({ kind: true }).strict(), managedFields.shape.executor.options[3].omit({ kind: true }).strict(), managedFields.shape.executor.options[4].omit({
7033
+ kind: true,
7034
+ notification: true
7035
+ }).strict();
7031
7036
  var edge = object$1({
7032
7037
  source: text,
7033
7038
  target: text,
@@ -7107,6 +7112,11 @@ var shapes = {
7107
7112
  ...at,
7108
7113
  node
7109
7114
  },
7115
+ "graph.node.replace": {
7116
+ ...at,
7117
+ before: node,
7118
+ node
7119
+ },
7110
7120
  "graph.node.delete": at,
7111
7121
  "graph.node.field.set": union([
7112
7122
  object$1({
@@ -6801,7 +6801,7 @@ var decisionQuestion = discriminatedUnion("type", [
6801
6801
  criteria: strings
6802
6802
  })
6803
6803
  ]);
6804
- var managed = object({
6804
+ var managedFields = object({
6805
6805
  ...ports,
6806
6806
  name: text,
6807
6807
  executor: union([
@@ -6860,7 +6860,8 @@ var managed = object({
6860
6860
  }).optional()
6861
6861
  })
6862
6862
  ])
6863
- }).transform(limitDecisionTask);
6863
+ });
6864
+ var managed = managedFields.transform(limitDecisionTask);
6864
6865
  var operand = union([object({
6865
6866
  kind: literal("value"),
6866
6867
  value: json.optional(),
@@ -7035,6 +7036,10 @@ var node = union([
7035
7036
  })
7036
7037
  })
7037
7038
  ]);
7039
+ strictObject(condition), strictObject(wait), strictObject(webhook), managedFields.shape.executor.options[0].omit({ kind: true }).strict(), managedFields.shape.executor.options[1].omit({ kind: true }).strict(), managedFields.shape.executor.options[2].omit({ kind: true }).strict(), managedFields.shape.executor.options[3].omit({ kind: true }).strict(), managedFields.shape.executor.options[4].omit({
7040
+ kind: true,
7041
+ notification: true
7042
+ }).strict();
7038
7043
  var edge = object({
7039
7044
  source: text,
7040
7045
  target: text,
@@ -7114,6 +7119,11 @@ var shapes = {
7114
7119
  ...at,
7115
7120
  node
7116
7121
  },
7122
+ "graph.node.replace": {
7123
+ ...at,
7124
+ before: node,
7125
+ node
7126
+ },
7117
7127
  "graph.node.delete": at,
7118
7128
  "graph.node.field.set": union([
7119
7129
  object({
@@ -9603,7 +9603,7 @@ var decisionQuestion = discriminatedUnion("type", [
9603
9603
  criteria: strings
9604
9604
  })
9605
9605
  ]);
9606
- var managed = object({
9606
+ var managedFields = object({
9607
9607
  ...ports,
9608
9608
  name: text,
9609
9609
  executor: union([
@@ -9662,7 +9662,8 @@ var managed = object({
9662
9662
  }).optional()
9663
9663
  })
9664
9664
  ])
9665
- }).transform(limitDecisionTask);
9665
+ });
9666
+ var managed = managedFields.transform(limitDecisionTask);
9666
9667
  var operand = union([object({
9667
9668
  kind: literal("value"),
9668
9669
  value: json.optional(),
@@ -9837,6 +9838,10 @@ var node = union([
9837
9838
  })
9838
9839
  })
9839
9840
  ]);
9841
+ strictObject(condition), strictObject(wait), strictObject(webhook), managedFields.shape.executor.options[0].omit({ kind: true }).strict(), managedFields.shape.executor.options[1].omit({ kind: true }).strict(), managedFields.shape.executor.options[2].omit({ kind: true }).strict(), managedFields.shape.executor.options[3].omit({ kind: true }).strict(), managedFields.shape.executor.options[4].omit({
9842
+ kind: true,
9843
+ notification: true
9844
+ }).strict();
9840
9845
  var edge = object({
9841
9846
  source: text,
9842
9847
  target: text,
@@ -9916,6 +9921,11 @@ var shapes = {
9916
9921
  ...at,
9917
9922
  node
9918
9923
  },
9924
+ "graph.node.replace": {
9925
+ ...at,
9926
+ before: node,
9927
+ node
9928
+ },
9919
9929
  "graph.node.delete": at,
9920
9930
  "graph.node.field.set": union([
9921
9931
  object({
@@ -5917,7 +5917,7 @@ var decisionQuestion = discriminatedUnion("type", [
5917
5917
  criteria: strings
5918
5918
  })
5919
5919
  ]);
5920
- var managed = object({
5920
+ var managedFields = object({
5921
5921
  ...ports,
5922
5922
  name: text,
5923
5923
  executor: union([
@@ -5976,7 +5976,8 @@ var managed = object({
5976
5976
  }).optional()
5977
5977
  })
5978
5978
  ])
5979
- }).transform(limitDecisionTask);
5979
+ });
5980
+ var managed = managedFields.transform(limitDecisionTask);
5980
5981
  var operand = union([object({
5981
5982
  kind: literal("value"),
5982
5983
  value: json.optional(),
@@ -6151,6 +6152,10 @@ var node = union([
6151
6152
  })
6152
6153
  })
6153
6154
  ]);
6155
+ strictObject(condition), strictObject(wait), strictObject(webhook), managedFields.shape.executor.options[0].omit({ kind: true }).strict(), managedFields.shape.executor.options[1].omit({ kind: true }).strict(), managedFields.shape.executor.options[2].omit({ kind: true }).strict(), managedFields.shape.executor.options[3].omit({ kind: true }).strict(), managedFields.shape.executor.options[4].omit({
6156
+ kind: true,
6157
+ notification: true
6158
+ }).strict();
6154
6159
  var edge = object({
6155
6160
  source: text,
6156
6161
  target: text,
@@ -6230,6 +6235,11 @@ var shapes = {
6230
6235
  ...at,
6231
6236
  node
6232
6237
  },
6238
+ "graph.node.replace": {
6239
+ ...at,
6240
+ before: node,
6241
+ node
6242
+ },
6233
6243
  "graph.node.delete": at,
6234
6244
  "graph.node.field.set": union([
6235
6245
  object({
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@oomol-lab/open-flow",
3
- "version": "0.1.0-beta.56",
3
+ "version": "0.1.0-beta.58",
4
4
  "description": "TypeScript contracts and Browser runtime for Open Flow.",
5
5
  "license": "Apache-2.0",
6
6
  "repository": {
@@ -10,6 +10,10 @@
10
10
  },
11
11
  "types": "./dist/index.d.ts",
12
12
  "exports": {
13
+ "./package.json": "./package.json",
14
+ "./skills/open-flow/SKILL.md": "./skills/open-flow/SKILL.md",
15
+ "./skills/open-flow/references/flow-authoring.md": "./skills/open-flow/references/flow-authoring.md",
16
+ "./skills/open-flow/references/flow-n8n-conversion.md": "./skills/open-flow/references/flow-n8n-conversion.md",
13
17
  ".": {
14
18
  "types": "./dist/index.d.ts"
15
19
  },
@@ -136,12 +140,14 @@
136
140
  },
137
141
  "files": [
138
142
  "dist",
143
+ "skills",
139
144
  "README.md",
140
145
  "NOTICE",
141
146
  "LICENSE"
142
147
  ],
143
148
  "peerDependencies": {
144
149
  "effect": "4.0.0-rc.112",
150
+ "zod": "^4.6.5",
145
151
  "react": "^18.3.1 || ^19.0.0",
146
152
  "react-dom": "^18.3.1 || ^19.0.0"
147
153
  },
@@ -0,0 +1,32 @@
1
+ ---
2
+ name: open-flow
3
+ description: Create, inspect, edit, check, run, and publish persistent Open Flow workflows through an existing Server, or assess and convert n8n workflows to Open Flow. Use for workflow operations, not changes to the Open Flow implementation.
4
+ ---
5
+
6
+ # Open Flow
7
+
8
+ Use `<!-- agentic:var flowCommand -->` to operate the selected deployment.
9
+ Consult the references relevant to the task:
10
+
11
+ - [Flow capabilities and examples](references/flow-authoring.md): inspect, edit,
12
+ connect, validate, run and publish; concurrency and Run diagnostics.
13
+ - [n8n conversion](references/flow-n8n-conversion.md): represent collections,
14
+ branches, provider operations and state while preserving source behavior.
15
+
16
+ <!-- agentic:if localDevelopment -->
17
+
18
+ Run commands from this repository's root. The development CLI connects to the
19
+ existing local Server by default, using `OPEN_FLOW_PORT` (default `3001`) and
20
+ `OPEN_FLOW_TOKEN`, or the token generated by `bun run dev`. It reads the root
21
+ `.env`. If the local Server has not been started, report that prerequisite.
22
+ Do not start or reconfigure a Server merely to perform a Flow operation.
23
+
24
+ To select another Server, the user must provide both `OPEN_FLOW_URL` and
25
+ `OPEN_FLOW_TOKEN` in the environment. Never read, print, or copy credential files
26
+ into prompts or command arguments. Connector and LLM configuration stay on the
27
+ Server; do not duplicate them in the CLI.
28
+ <!-- agentic:endif -->
29
+
30
+ Keep the requested boundary: editing a Draft does not authorize a Run,
31
+ publication, or enabling automatic execution. Report the resulting Flow and
32
+ Revision, verification result, and any unresolved configuration.
@@ -0,0 +1,356 @@
1
+ # Build and operate Open Flow workflows
2
+
3
+ `<!-- agentic:var flowCommand -->` operates persistent workflows on the selected
4
+ Server. Commands with `--json` return machine-readable results. Help and local
5
+ schemas work offline; Flow data and provider discovery require the Server.
6
+
7
+ ## The working model
8
+
9
+ A **Flow** has an editable **Draft**. Each saved change creates a **Revision**.
10
+ A **Run** executes a fixed version starting at a Trigger. A **Publication** makes
11
+ a Revision Live; enabling the Flow allows its automatic Triggers to execute.
12
+ Saving a Draft, running it, publishing it, and enabling it are separate actions.
13
+ Choose the actions covered by the user's request. A Run can have external effects.
14
+
15
+ Nodes describe business operations. **Execution edges** determine which nodes
16
+ run and in what order. **Input bindings** supply their data. A binding does not
17
+ create an execution edge. A Condition selects named execution branches; its
18
+ branch names are not output ports.
19
+
20
+ The authoring interface accepts business configuration, named inputs and source
21
+ text. It builds internal definitions, ports and Module identities for you.
22
+ `schema TYPE` supplies the current contract and a node example; `schema edit`
23
+ supplies the edit operations. Use these when a configuration is unfamiliar.
24
+
25
+ ## Find a Flow or a relevant part
26
+
27
+ ```bash
28
+ <!-- agentic:var flowCommand --> list --json
29
+ <!-- agentic:var flowCommand --> create "Order summary" --json
30
+ <!-- agentic:var flowCommand --> show FLOW_ID --json
31
+ <!-- agentic:var flowCommand --> read FLOW_ID --json
32
+ <!-- agentic:var flowCommand --> search FLOW_ID --input '{"query":"Customer summary","type":"agent"}' --json
33
+ <!-- agentic:var flowCommand --> read FLOW_ID --input '{"revision":"REVISION","nodes":["NODE"]}' --json
34
+ <!-- agentic:var flowCommand --> read FLOW_ID --input '{"revision":"REVISION","text":{"node":"NODE","field":"prompt","start":1,"lines":40}}' --json
35
+ ```
36
+
37
+ A known Flow ID avoids a list lookup. `show` gives lifecycle and publication
38
+ state. `read` gives a graph outline, selected node details, or a text excerpt;
39
+ `nodes` and `text` are alternative modes. `search` finds matches in names,
40
+ configuration and source text, optionally restricted by node type.
41
+
42
+ The returned `revision` pins subsequent reads and the eventual edit to the same
43
+ snapshot. Pagination uses `nextCursor` for lists, `nextOffset` for search, and
44
+ `nextStart` for text. Keep the Revision when reading more matches or text pages.
45
+ Long text is complete when `truncated` is false. Read as much context as the
46
+ change needs; a small edit need not fetch every node or every prompt.
47
+
48
+ ## Save changes
49
+
50
+ ```bash
51
+ <!-- agentic:var flowCommand --> schema edit --json
52
+ <!-- agentic:var flowCommand --> schema code --json
53
+ <!-- agentic:var flowCommand --> edit FLOW_ID --file edits.json --json
54
+ ```
55
+
56
+ An edit request contains `baseRevision`, `requestId`, and an ordered `edits`
57
+ array. The batch is atomic. Use the observed Revision and a unique request ID
58
+ for each new change; retain both when retrying an uncertain submission.
59
+ Examples below use `REVISION` and uppercase node placeholders for observed IDs.
60
+ Their request IDs are illustrative; choose fresh IDs when adapting them.
61
+
62
+ `read`, `search`, and `edit` accept `--input` (JSON, `@file`, or `-`) or `--file`
63
+ (path or `-`). Use one input mechanism per command. Nested strings are literal:
64
+ a `code` value of `@transform.js` does not load that file.
65
+
66
+ | Operation | Effect |
67
+ | --------------------------------- | ----------------------------------------------------------------------------------- |
68
+ | `node.add` | Create a node with optional business configuration, input bindings and code/prompt. |
69
+ | `node.update` | Patch metadata or configuration; `clear` removes selected paths. |
70
+ | `node.remove` | Remove a node. |
71
+ | `input.set` | Set a named input's source. |
72
+ | `edge.connect`, `edge.disconnect` | Change execution routing, with an optional Condition `branch`. |
73
+ | `text.edit` | Replace one exact occurrence in code or prompt. |
74
+ | `text.set` | Replace the entire code or prompt. |
75
+
76
+ `node.add.as` declares a batch-local alias. Later operations in that batch use
77
+ `$alias`; later requests use stable references from the response's `nodes` map.
78
+ Updates recursively merge objects, including JSON schemas; arrays replace whole
79
+ arrays. An empty object preserves existing fields. For example,
80
+ `clear: [["config", "inputs", "amount", "schema", "type"]]` removes that constraint.
81
+ Absence, explicit null, an unset binding and an inherited default are distinct.
82
+
83
+ ### Connect execution and data
84
+
85
+ This complete edit adds a Manual Trigger, a calculation, and a formatter. It
86
+ needs no Connector or model. `total` is a business output; `amount` is a named
87
+ input whose binding reads it. Both execution edges and data bindings are visible.
88
+
89
+ ```json
90
+ {
91
+ "baseRevision": "REVISION",
92
+ "requestId": "example-code-and-data",
93
+ "edits": [
94
+ { "op": "node.add", "as": "start", "type": "manual", "name": "Start" },
95
+ {
96
+ "op": "node.add",
97
+ "as": "calculate",
98
+ "type": "code",
99
+ "name": "Calculate total",
100
+ "config": { "outputs": { "total": { "schema": { "type": "number" }, "nullable": false } } },
101
+ "inputs": { "prices": { "kind": "value", "value": [12, 30] } },
102
+ "code": "export default ({prices}) => ({total: prices.reduce((sum, price) => sum + price, 0)})"
103
+ },
104
+ {
105
+ "op": "node.add",
106
+ "as": "format",
107
+ "type": "code",
108
+ "name": "Format total",
109
+ "config": { "outputs": { "text": { "schema": { "type": "string" }, "nullable": false } } },
110
+ "inputs": { "amount": { "kind": "output", "node": "$calculate", "port": "total" } },
111
+ "code": "export default ({amount}) => ({text: `Total: ${amount}`})"
112
+ },
113
+ { "op": "edge.connect", "source": "$start", "target": "$calculate" },
114
+ { "op": "edge.connect", "source": "$calculate", "target": "$format" }
115
+ ]
116
+ }
117
+ ```
118
+
119
+ Code uses JavaScript ESM: a default-exported function receives a named input
120
+ record and returns a record matching `config.outputs`. Collections can be JSON
121
+ arrays inside a field. Bindings to new Code, Agent, LLM, Wait and Approval inputs
122
+ automatically declare inputs accepting JSON; `config.inputs` adds business
123
+ constraints or defaults where needed.
124
+
125
+ Common sources are `{"kind":"value","value":...}`,
126
+ `{"kind":"output","node":"NODE","port":"PORT"}`, and
127
+ `{"kind":"variable","name":"VARIABLE"}`. An output source may omit `port`
128
+ when there is one output, or select a nested `field`. Each node schema advertises
129
+ supported sources. A Trigger cannot read downstream results before the Run starts.
130
+ Schema `{}` accepts dynamic JSON; it does not convert objects or arrays into text.
131
+
132
+ ### Change one prompt rule
133
+
134
+ For an existing Agent whose prompt contains `Include customer email.`, this edit
135
+ changes that rule while retaining the rest of the prompt and node configuration.
136
+ Read the target text to choose an exact, unique match.
137
+
138
+ ```json
139
+ {
140
+ "baseRevision": "REVISION",
141
+ "requestId": "example-prompt-edit",
142
+ "edits": [
143
+ {
144
+ "op": "text.edit",
145
+ "node": "AGENT_NODE",
146
+ "field": "prompt",
147
+ "oldText": "Include customer email.",
148
+ "newText": "Omit customer email."
149
+ }
150
+ ]
151
+ }
152
+ ```
153
+
154
+ Zero or multiple matches reject the replacement. A longer surrounding excerpt
155
+ can disambiguate it. `text.set` suits an intentional full rewrite. LLM message
156
+ templates live in `config.template`, rather than the Agent's `prompt` field.
157
+
158
+ ### Request structured model output
159
+
160
+ An LLM node supports message templates, conversation history and model settings.
161
+ In this example, `MODEL_ID` is a model supported by the deployment and
162
+ `SOURCE_NODE` has one output containing an order. `{{order}}` interpolates the
163
+ bound business input. `resultSchema` defines the result without manually building
164
+ an output port.
165
+
166
+ ```json
167
+ {
168
+ "baseRevision": "REVISION",
169
+ "requestId": "example-structured-output",
170
+ "edits": [
171
+ {
172
+ "op": "node.add",
173
+ "as": "summary",
174
+ "type": "llm",
175
+ "name": "Summarize order",
176
+ "config": {
177
+ "mode": "json",
178
+ "model": { "model": "MODEL_ID" },
179
+ "template": [{ "role": "user", "content": "Summarize this order: {{order}}" }],
180
+ "resultSchema": {
181
+ "type": "object",
182
+ "properties": { "summary": { "type": "string" } },
183
+ "required": ["summary"],
184
+ "additionalProperties": false
185
+ }
186
+ },
187
+ "inputs": { "order": { "kind": "output", "node": "SOURCE_NODE" } }
188
+ },
189
+ { "op": "edge.connect", "source": "SOURCE_NODE", "target": "$summary" }
190
+ ]
191
+ }
192
+ ```
193
+
194
+ A downstream node can bind the sole result and select `field: "summary"`.
195
+ For model-driven tool use, `schema agent` describes prompts, tools and structured
196
+ results. For classification, `schema decision` describes named questions and
197
+ answer objects. A Decision answer still needs a Condition if it should control
198
+ execution. Schemas constrain data shape; task-specific tests establish whether a
199
+ model's answers are useful.
200
+
201
+ ### Put an existing operation behind a condition
202
+
203
+ Suppose `SOURCE_NODE` outputs `total` and directly precedes `TARGET_NODE`.
204
+ This edit inserts a threshold gate. The target runs only for totals above 100;
205
+ its existing data bindings stay unchanged. The same pattern can guard an external
206
+ write, notification, or a local calculation.
207
+
208
+ ```json
209
+ {
210
+ "baseRevision": "REVISION",
211
+ "requestId": "example-condition",
212
+ "edits": [
213
+ {
214
+ "op": "node.add",
215
+ "as": "gate",
216
+ "type": "condition",
217
+ "name": "Above threshold",
218
+ "config": {
219
+ "match": "first",
220
+ "branches": [
221
+ {
222
+ "name": "large",
223
+ "when": {
224
+ "left": { "kind": "output", "node": "SOURCE_NODE", "port": "total" },
225
+ "operator": ">",
226
+ "right": { "kind": "value", "value": 100 }
227
+ }
228
+ }
229
+ ]
230
+ }
231
+ },
232
+ { "op": "edge.disconnect", "source": "SOURCE_NODE", "target": "TARGET_NODE" },
233
+ { "op": "edge.connect", "source": "SOURCE_NODE", "target": "$gate" },
234
+ { "op": "edge.connect", "source": "$gate", "target": "TARGET_NODE", "branch": "large" }
235
+ ]
236
+ }
237
+ ```
238
+
239
+ `match: "first"` selects the first matching branch; `"all"` allows multiple
240
+ matches. `otherwise` handles unmatched execution if connected. Predicates can
241
+ combine expressions with `all` or `any`; see `schema condition`. Merely binding
242
+ data from a Condition's upstream node does not guard a side effect.
243
+
244
+ ## Provider actions, events and other node types
245
+
246
+ ```bash
247
+ <!-- agentic:var flowCommand --> connector search "<provider and operation>" --flow FLOW_ID --json
248
+ <!-- agentic:var flowCommand --> connector show ACTION_ID --flow FLOW_ID --json
249
+ <!-- agentic:var flowCommand --> schema --flow FLOW_ID --input '{"action":"ACTION_ID"}' --json
250
+ <!-- agentic:var flowCommand --> connector connections SERVICE --flow FLOW_ID --json
251
+ <!-- agentic:var flowCommand --> trigger search "<provider and event>" --json
252
+ <!-- agentic:var flowCommand --> trigger show TRIGGER_KEY --json
253
+ ```
254
+
255
+ Discovery supplies actual Action IDs, Trigger keys, ports and Connections. A
256
+ search match is a candidate; its schema describes the operation and data. An
257
+ unavailable action and an action lacking an active Connection are different
258
+ problems. Actions marked `authenticated: false` need no account. Connection
259
+ selection rules come from the selected node contract.
260
+
261
+ | Capability | Relevant schema and configuration |
262
+ | ------------------------------- | ----------------------------------------------------------------------------------------------------------------------- |
263
+ | Provider read or write | `connector`: discovered `action`, optional `connectionId`, named input bindings. |
264
+ | Provider event | `poll` or `integration`: discovered `key`, Connection and any static inputs; polling also has a schedule. |
265
+ | Manual, HTTP or scheduled entry | `manual`, `webhook`, `cron`: business payload fields or schedule. A Manual Trigger has no output parameters. |
266
+ | Workflow failure handler | `error`: published upstream Flows' automatic Run failures; not a node-level catch or a handler for manual Run failures. |
267
+ | Fixed HTTP operation | `openapi`: an OpenAPI source, path and method; resolved authentication choices and ports appear in node details. |
268
+ | Reusable constants | `value`: named JSON values and optional output constraints. |
269
+ | Durable interaction | `wait`, `approval`: prompt and named inputs; resume through the Run's Wait ID. |
270
+
271
+ Connector and LLM services are configured on the Server. Missing capabilities
272
+ should be described in terms of the required operation or event, without silently
273
+ replacing the requested Flow with direct provider calls outside it.
274
+
275
+ ## Validation and execution
276
+
277
+ An accepted edit returns `saved: true`, the new `revision`, alias-to-node mappings,
278
+ and `validation`. A Draft may save with diagnostics. `valid`, `invalid` and
279
+ `unavailable` describe validation, not whether the write happened.
280
+
281
+ ```bash
282
+ <!-- agentic:var flowCommand --> check FLOW_ID --revision REVISION --json
283
+ <!-- agentic:var flowCommand --> run FLOW_ID --source draft --trigger TRIGGER_ID --expected-revision REVISION --idempotency-key RUN_KEY --wait --json
284
+ <!-- agentic:var flowCommand --> runs result RUN_ID --json
285
+ ```
286
+
287
+ Use the edit's validation or request a check of a specific Revision. Structural
288
+ validity does not demonstrate business behavior, model quality or runtime account
289
+ access. An authorized test Run can exercise meaningful input cases. Draft Run
290
+ readiness concerns the selected Trigger's path and dependencies; publishing and
291
+ Live Runs require the complete Flow to be ready.
292
+
293
+ A sole Manual Trigger is selected automatically; otherwise specify `--trigger`.
294
+ `--outputs` supplies named Trigger outputs. `--input` supplies per-node input
295
+ overrides; command help gives their shape. Live Runs use `--source live` and
296
+ `--expected-publication` instead of `--expected-revision`.
297
+
298
+ ### Inspect or continue an existing Run
299
+
300
+ ```bash
301
+ <!-- agentic:var flowCommand --> runs show RUN_ID --json
302
+ <!-- agentic:var flowCommand --> runs events RUN_ID --json
303
+ <!-- agentic:var flowCommand --> runs wait RUN_ID --timeout 60000 --json
304
+ <!-- agentic:var flowCommand --> runs resolve RUN_ID WAIT_ID approve --json
305
+ ```
306
+
307
+ A Wait or Approval suspends the existing Run. `run.waits` carries its Wait IDs;
308
+ resolution uses `continue`, `approve` or `reject` as appropriate to that wait and
309
+ the authorized decision. A client timeout also leaves the operation running.
310
+ Waiting again observes the same Run; starting another Run repeats execution.
311
+
312
+ | Exit code | Meaning |
313
+ | --------- | ------------------------------------------------------------------------------------------ |
314
+ | `0` | Command succeeded or asynchronous work was accepted; inspect the returned status. |
315
+ | `1` | Command error or unsuccessful terminal Run; inspect the error or Run events. |
316
+ | `2` | Run is blocked on an unresolved Wait or Approval. |
317
+ | `3` | Client wait expired or publication is pending; retain its identity and continue observing. |
318
+
319
+ `--timeout` is a wait budget in milliseconds (default 60000). Event following
320
+ with `runs events RUN_ID --follow --json` emits NDJSON; `nextAfter` supports
321
+ resuming. `runs results`, `runs read-result` and `runs download-result` expose
322
+ large results without requiring the whole value in one response.
323
+
324
+ ## Publish and open
325
+
326
+ ```bash
327
+ <!-- agentic:var flowCommand --> publish FLOW_ID --expected-revision REVISION --expected-publication PUBLICATION_OR_NONE --idempotency-key PUBLISH_KEY --json
328
+ <!-- agentic:var flowCommand --> enable FLOW_ID --expected-publication PUBLICATION --json
329
+ <!-- agentic:var flowCommand --> workbench FLOW_ID --json
330
+ <!-- agentic:var flowCommand --> open FLOW_ID
331
+ ```
332
+
333
+ `none` means no prior Live Publication was observed. Publication and enablement
334
+ are for a requested release or automatic execution, and are unnecessary for a
335
+ Draft test Run. `publications wait` follows an accepted pending publication.
336
+
337
+ `workbench` returns a URL; `open` opens the system browser. Browser authentication
338
+ belongs to the host. An open Workbench receives Revision notifications, so a CLI
339
+ edit does not require a page reload.
340
+
341
+ ## Recover without losing another change or repeating an effect
342
+
343
+ - **Revision conflict:** another writer changed the Draft. Read the latest
344
+ relevant state, recompute the edit, and use a new request ID. Merely replacing
345
+ `baseRevision` can overwrite the other writer's intent.
346
+ - **`flow.mutation-outcome-unknown`:** the submission may have succeeded. Preserve
347
+ its identity, key and complete payload. Only an identical retry can safely
348
+ resolve that uncertainty; a new key describes a new mutation.
349
+ - **Saved with diagnostics:** the edit happened. Repair the saved Revision or
350
+ investigate unavailable validation; resubmitting it is not a validation step.
351
+ - **Failed Run:** events and results identify the failing node and available
352
+ inputs. Consider already-completed external effects before running it again.
353
+
354
+ A useful completion report identifies the Flow and Revision, what changed,
355
+ what was actually checked or executed, and any remaining blocker. Its detail
356
+ should match the task.