@oomol-lab/open-flow 0.1.0-beta.55 → 0.1.0-beta.57
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/README.md +1 -1
- package/dist/browser/{createResourceDialog-4H5_lZ6s.js → createResourceDialog-C23SBjYd.js} +2 -2
- package/dist/browser/flow-authoring-edge.d.ts +3 -3
- package/dist/browser/flow-authoring-node.d.ts +30 -46
- package/dist/browser/flow-authoring.js +9215 -21030
- package/dist/browser/flow-change-schema.d.ts +267 -1
- package/dist/browser/flow-change.d.ts +19 -104
- package/dist/browser/flow-change.js +154 -298
- package/dist/browser/{flowChanges-ZzG-f9cg.js → flowChanges-fBiAeTzR.js} +2347 -2216
- package/dist/browser/{flowWorkspace-ChpRaTMX.js → flowWorkspace-MqcEfg7T.js} +118 -293
- package/dist/browser/{icons-CdAB9wyS.js → icons-6oQ8Q9Wm.js} +4309 -4454
- package/dist/browser/lib-DrKav3HG.js +11403 -0
- package/dist/browser/preview.css +1 -1
- package/dist/browser/preview.js +9609 -9548
- package/dist/browser/ui-idTooltip.d.ts +11 -0
- package/dist/browser/ui.d.ts +5 -0
- package/dist/browser/ui.js +83 -1
- package/dist/browser/workbench.css +1 -1
- package/dist/browser/workbench.js +227 -417
- package/dist/browser/{workbenchSelect-BRZN4ish.js → workbenchSelect-DpLbIr29.js} +1 -1
- package/dist/common/authoring.d.ts +207 -0
- package/dist/common/authoringSchema.d.ts +1293 -0
- package/dist/common/control-api-conformance.js +1060 -623
- package/dist/common/control-api-errors.d.ts +2 -1
- package/dist/common/control-api.d.ts +87 -6
- package/dist/common/control-api.js +1058 -705
- package/dist/common/control-requests.d.ts +128 -0
- package/dist/common/control-requests.js +2913 -1145
- package/dist/common/decision.js +6337 -6371
- package/dist/common/flow-agent.d.ts +1 -1
- package/dist/common/flow-connectionUsage.d.ts +1 -2
- package/dist/common/flow-encoding.d.ts +2 -4
- package/dist/common/flow-encoding.js +131 -182
- package/dist/common/flow-graph.d.ts +10 -10
- package/dist/common/flow-semantics.d.ts +13 -9
- package/dist/common/flow-semantics.js +9051 -9232
- package/dist/common/flowInspection.d.ts +3 -21
- package/dist/common/integration-trigger.js +8653 -8687
- package/dist/common/lib-DrKav3HG.js +11403 -0
- package/dist/common/mcp.d.ts +120 -12
- package/dist/common/mcp.js +537 -188
- package/dist/common/openapi.js +6337 -6371
- package/dist/common/poll-trigger.js +8653 -8687
- package/dist/common/run-events.js +0 -1
- package/dist/common/scheduler.d.ts +3 -9
- package/dist/common/scheduler.js +128 -209
- package/dist/common/webhook-trigger.js +6337 -6371
- package/package.json +7 -1
- package/skills/open-flow/SKILL.md +32 -0
- package/skills/open-flow/references/flow-authoring.md +356 -0
- package/skills/open-flow/references/flow-n8n-conversion.md +196 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@oomol-lab/open-flow",
|
|
3
|
-
"version": "0.1.0-beta.
|
|
3
|
+
"version": "0.1.0-beta.57",
|
|
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.
|
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
# Convert n8n behavior into Open Flow
|
|
2
|
+
|
|
3
|
+
An n8n export describes a workflow's behavior and its n8n-specific machinery.
|
|
4
|
+
Use the behavior to design an Open Flow graph with current node contracts.
|
|
5
|
+
Equivalent results may need a different number of nodes or a different graph.
|
|
6
|
+
[Flow authoring](flow-authoring.md) covers `<!-- agentic:var flowCommand -->`,
|
|
7
|
+
atomic edits, input bindings and execution.
|
|
8
|
+
|
|
9
|
+
The requested outcome can be a feasibility assessment, a complete conversion,
|
|
10
|
+
or a useful partial Draft. Unresolved behavior limits what can be claimed as
|
|
11
|
+
converted; it does not prevent saving an agreed partial result. Running,
|
|
12
|
+
publishing and enabling remain separate actions within the user's authorization.
|
|
13
|
+
|
|
14
|
+
## Choose a representation
|
|
15
|
+
|
|
16
|
+
| Source behavior | Open Flow building blocks | What determines a good fit |
|
|
17
|
+
| --------------------------------------------- | ----------------------------------------------- | ------------------------------------------------------------------------------ |
|
|
18
|
+
| Scheduled, webhook or provider event | Cron, Webhook, Poll or Integration Trigger | Schedule/timezone, event payload, delivery and response behavior. |
|
|
19
|
+
| Provider read or write | Connector | Exact operation, input/output shape, account and number of calls. |
|
|
20
|
+
| Field shaping, filtering, aggregation or join | Code with named input/output fields | Explicit collection representation, ordering, keys and empty-input behavior. |
|
|
21
|
+
| IF or Switch | Condition and named execution branches | Predicate, first/all matches, fallback route and data sent onward. |
|
|
22
|
+
| Prompt plus model and output parser | LLM with template, inputs and `resultSchema` | Supported model, result shape and any parser repair behavior. |
|
|
23
|
+
| Agent with tools or memory | Agent where its current contract fits | Tool permissions, state lifetime and how context is supplied. |
|
|
24
|
+
| HTTP request | OpenAPI where an actual operation contract fits | Method, parameters, auth, response format and error behavior. |
|
|
25
|
+
| Human response or durable pause | Wait or Approval | Who resumes it, payload, timing, notification and external response lifecycle. |
|
|
26
|
+
| Workflow failure handling | Error Trigger where its scope fits | Which failures trigger it and what failure data it receives. |
|
|
27
|
+
|
|
28
|
+
Use `schema TYPE` and provider discovery for the actual deployment. A node's
|
|
29
|
+
name alone does not establish equivalence. Provider operations can differ even
|
|
30
|
+
when both products use the same service name. Model, parser, tool, memory and
|
|
31
|
+
retrieval nodes connected by specialized AI edges often form one semantic unit;
|
|
32
|
+
those edges do not translate directly into execution edges.
|
|
33
|
+
|
|
34
|
+
## Records, collections and item identity
|
|
35
|
+
|
|
36
|
+
n8n passes arrays of items and many nodes process each item automatically.
|
|
37
|
+
Open Flow Code receives one named input record; a collection is an explicit
|
|
38
|
+
array field in that record. Passing an array to a Connector does not imply one
|
|
39
|
+
call per element. This distinction matters most for external writes. See
|
|
40
|
+
[n8n data structure](https://docs.n8n.io/build/work-with-data/understand-n8ns-data-structure.md).
|
|
41
|
+
|
|
42
|
+
For example, a source step that filters paid orders and sums their amounts can
|
|
43
|
+
be represented by a Code node with an `orders` input and `count` and `total`
|
|
44
|
+
outputs. Assuming numeric amounts, its code can be:
|
|
45
|
+
|
|
46
|
+
```javascript
|
|
47
|
+
export default ({ orders }) => {
|
|
48
|
+
const paid = orders.filter((order) => order.status === 'paid')
|
|
49
|
+
return {
|
|
50
|
+
count: paid.length,
|
|
51
|
+
total: paid.reduce((sum, order) => sum + order.amount, 0),
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
Declare those business outputs in `config.outputs` and bind the input to the
|
|
57
|
+
actual upstream collection. Empty input produces zero count and total. If the
|
|
58
|
+
source accepts null or string amounts, preserve that behavior explicitly. If
|
|
59
|
+
its next step sends one message per order, this aggregation would change the
|
|
60
|
+
behavior; preserve the individual calls or discuss a batch-message redesign.
|
|
61
|
+
|
|
62
|
+
n8n also links output items to their originating items. An expression such as
|
|
63
|
+
`$('Customer').item.json.email` depends on that lineage, whereas `.first()`
|
|
64
|
+
explicitly chooses a position. Neither implies an arbitrary first available
|
|
65
|
+
customer. An Open Flow representation can use a single record when the relation
|
|
66
|
+
is one-to-one, or an explicit keyed join when working with collections. Missing
|
|
67
|
+
and duplicate keys need the source's intended behavior. See
|
|
68
|
+
[n8n item linking](https://docs.n8n.io/build/work-with-data/reference-data/link-data-items.md).
|
|
69
|
+
|
|
70
|
+
### Expression examples
|
|
71
|
+
|
|
72
|
+
| n8n intent | Possible Open Flow expression |
|
|
73
|
+
| -------------------------------------- | ------------------------------------------------------------------------------------------------------ |
|
|
74
|
+
| Read `orderId` from the current item | Bind a named `order` input; Code reads `order.orderId`, or select an upstream output's `field`. |
|
|
75
|
+
| Read all records from an earlier step | Bind its explicit array output and process the array. |
|
|
76
|
+
| Read a linked customer for each order | Pass the linked record explicitly, or join collections on the real customer key. |
|
|
77
|
+
| Interpolate an order in a model prompt | Bind `order` to Agent/LLM and use `{{order}}`. |
|
|
78
|
+
| Read a file or attachment | Use the selected Trigger/Connector's file or artifact contract; there is no implicit n8n binary store. |
|
|
79
|
+
| Read environment or execution metadata | Use an equivalent supported binding, or an explicit business input when appropriate. |
|
|
80
|
+
|
|
81
|
+
n8n helpers such as `$input`, `$json` and `$node` are not Open Flow JavaScript
|
|
82
|
+
globals. Rewrite their meaning using named inputs. Execution-time clocks, timezones
|
|
83
|
+
and persisted state may also affect the result; an ordinary JavaScript value is
|
|
84
|
+
only equivalent when those lifetimes agree.
|
|
85
|
+
|
|
86
|
+
## Branches control execution separately from data
|
|
87
|
+
|
|
88
|
+
Consider “if an order total exceeds 100, notify operations; otherwise archive it.”
|
|
89
|
+
The Open Flow Condition reads the total, selects a named branch, and execution
|
|
90
|
+
edges reach the notification or archive node. Both destinations bind their
|
|
91
|
+
payload from the original order output.
|
|
92
|
+
|
|
93
|
+
The [condition example](flow-authoring.md#put-an-existing-operation-behind-a-condition)
|
|
94
|
+
shows inserting such a gate without altering the destination's input bindings.
|
|
95
|
+
A data reference to an upstream node does not restrict when a side effect runs.
|
|
96
|
+
|
|
97
|
+
Preserve the meaning of source branch indexes: inspect what each output of the
|
|
98
|
+
specific node represents. For multi-case routing, `match: "first"` and
|
|
99
|
+
`match: "all"` support different behavior; `otherwise` is the unmatched route.
|
|
100
|
+
For item-by-item IF routing, partitioning a collection may be necessary before
|
|
101
|
+
choosing execution branches. One condition over an array is not automatically
|
|
102
|
+
one condition per item.
|
|
103
|
+
|
|
104
|
+
Merge behavior also depends on join mode, keys, ordering, duplicates and absent
|
|
105
|
+
inputs. Code can implement a bounded, explicit join. A generic connection
|
|
106
|
+
between two predecessors does not reproduce every Merge mode.
|
|
107
|
+
|
|
108
|
+
## Provider access and credentials
|
|
109
|
+
|
|
110
|
+
```bash
|
|
111
|
+
<!-- agentic:var flowCommand --> connector search "<provider and operation>" --flow FLOW_ID --json
|
|
112
|
+
<!-- agentic:var flowCommand --> schema --flow FLOW_ID --input '{"action":"ACTION_ID"}' --json
|
|
113
|
+
<!-- agentic:var flowCommand --> connector connections SERVICE --flow FLOW_ID --json
|
|
114
|
+
<!-- agentic:var flowCommand --> trigger search "<provider and event>" --json
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
Select real Action IDs, Trigger keys and Connections from discovery. An n8n
|
|
118
|
+
credential ID is not an Open Flow Connection ID. Exports can also contain secrets
|
|
119
|
+
inside URLs, headers, expressions or Code; keep those out of Drafts and reports.
|
|
120
|
+
Use supported credential bindings for the selected operation. A missing account
|
|
121
|
+
can leave a Draft incomplete without implying that the action itself is absent.
|
|
122
|
+
|
|
123
|
+
For HTTP Request conversion, `schema openapi` describes source URL, operation
|
|
124
|
+
selection and supported authentication. Check the actual operation's response,
|
|
125
|
+
non-success status, redirect, binary and retry requirements against that contract.
|
|
126
|
+
An invented API specification does not establish support for an unknown operation.
|
|
127
|
+
|
|
128
|
+
A provider event may expose an ID where the source expected a full record. A
|
|
129
|
+
Connector read can supply the missing data if it preserves the desired behavior.
|
|
130
|
+
Likewise, a polling Trigger may own state or deduplication that a schedule plus
|
|
131
|
+
list action would need to reproduce explicitly.
|
|
132
|
+
|
|
133
|
+
## Models and stateful interactions
|
|
134
|
+
|
|
135
|
+
A standard prompt/model/parser cluster can often become one LLM node. The
|
|
136
|
+
[structured result example](flow-authoring.md#request-structured-model-output)
|
|
137
|
+
shows a message template, a bound input and a result schema. Business rules that
|
|
138
|
+
depend on particular fields may also need validation before a side effect.
|
|
139
|
+
A result schema alone does not reproduce an arbitrary parser's retry or repair
|
|
140
|
+
policy.
|
|
141
|
+
|
|
142
|
+
Agent tools, memory, retrievers and vector stores affect both available actions
|
|
143
|
+
and state lifetime. Inspect them as part of the source behavior. A successful
|
|
144
|
+
single prompt response does not establish equivalence with a stateful conversation.
|
|
145
|
+
|
|
146
|
+
Wait and Approval suspend a Run with a durable Wait ID. `runs resolve` continues
|
|
147
|
+
that Run. Match the source's resume payload, timing and external interaction
|
|
148
|
+
before calling it equivalent. Forms, conversational memory, delayed responses and
|
|
149
|
+
webhook response lifecycles may require capabilities beyond a simple pause;
|
|
150
|
+
a polling loop inside Code does not provide those lifecycles.
|
|
151
|
+
|
|
152
|
+
## Failures and execution settings
|
|
153
|
+
|
|
154
|
+
Source execution settings can change the number of processed items, output on
|
|
155
|
+
empty results, retries and failure routes. Account for settings such as
|
|
156
|
+
`executeOnce`, `alwaysOutputData`, `retryOnFail`, `onError` and legacy
|
|
157
|
+
`continueOnFail` when present. Their effective behavior depends on the source
|
|
158
|
+
node and n8n version; use its implementation or a representative execution when
|
|
159
|
+
the export is insufficient evidence.
|
|
160
|
+
|
|
161
|
+
The observable questions are whether a failed operation is retried, whether a
|
|
162
|
+
retry repeats a side effect, which output receives failure data, and whether the
|
|
163
|
+
workflow ultimately fails or continues. Handling a returned error item and
|
|
164
|
+
handling a thrown exception can be different paths. Preserve both when relevant;
|
|
165
|
+
do not infer their payload or route from the setting's label.
|
|
166
|
+
|
|
167
|
+
Open Flow Error Triggers observe automatic Run failures of published upstream
|
|
168
|
+
Flows. They expose `workflow`, `execution` and `error`; they do not implement a
|
|
169
|
+
node's continue-on-error route or catch manual Run failures. Node-level recovery
|
|
170
|
+
needs a separately supported design.
|
|
171
|
+
|
|
172
|
+
## Describe gaps and verify the requested result
|
|
173
|
+
|
|
174
|
+
Useful distinctions for a conversion report are:
|
|
175
|
+
|
|
176
|
+
- **Converted:** current contracts express the required behavior.
|
|
177
|
+
- **Needs configuration:** the design fits but needs an account or business value.
|
|
178
|
+
- **Missing provider capability:** the required event or operation is absent
|
|
179
|
+
from the available catalog. Describe its inputs, outputs and affected behavior.
|
|
180
|
+
- **Behavioral mismatch:** execution, state, lineage or response semantics need
|
|
181
|
+
a redesign or cannot currently be preserved. More catalog searching will not
|
|
182
|
+
resolve an execution-model mismatch.
|
|
183
|
+
|
|
184
|
+
Discovery effort should follow the uncertainty. A close search result warrants
|
|
185
|
+
contract inspection; a broad catalog query can help resolve ambiguous terminology.
|
|
186
|
+
There is no prescribed query count or requirement to produce a full inventory
|
|
187
|
+
before a useful local edit. When a gap would change the promised result, explain
|
|
188
|
+
it and align on the reduced scope or redesign before implementing that choice.
|
|
189
|
+
|
|
190
|
+
A saved, valid graph establishes structural correctness. Behavioral comparison
|
|
191
|
+
needs representative inputs and observable results: empty and multiple items,
|
|
192
|
+
branch boundaries, duplicate join keys, failures and external call counts as
|
|
193
|
+
relevant. Test execution stays within the user's authorization. Reports should
|
|
194
|
+
distinguish what was mapped, saved, checked and actually run, identify remaining
|
|
195
|
+
gaps, and link the resulting Flow/Revision when one was created. Annotations and
|
|
196
|
+
disabled nodes need mention only when their omission or behavior matters.
|