Four things the python SDK turned up, each fixed where every client sees it. A key no port declares is now an error rather than a silent drop, on the return, the yield and the emit alike — the contract the docs already stated. The SDK reads literal yields at sync time, so a typo fails before anything runs, and an emission of one fails the call rather than being logged where nobody looks. NaN and infinity are refused at the port. JSON cannot spell either, so one that travelled came back as a 500, a socket frame that stopped the canvas, or a metric batch the database dropped whole. An artifact input takes `@run:<id>.<output>` or a bare digest, resolved on the engine — so the CLI, the run dialog and a python caller mean the same thing, and a sweep can pass one at all. Node timeouts are off by default. The clock measured silence, which a training node is full of, and remote workers had already stopped enforcing it — their heartbeat reset it. Now a heartbeat proves the agent rather than the node, ninety seconds of nothing fails the call either way, and the engine touches work it is still running so a long node is not redelivered at sixty seconds. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019V5bsYGNxcgPs4xXmTPx69
158 lines
6.5 KiB
Markdown
158 lines
6.5 KiB
Markdown
# The flow editor
|
|
|
|
The canvas is where most of the work happens. It floats its chrome over a
|
|
full-bleed graph, so what you are looking at is always the flow.
|
|
|
|
## The canvas
|
|
|
|
Nodes are laid out for you — left to right on a desktop, top to bottom on a
|
|
phone — and the arrangement is recomputed as the graph changes. There is
|
|
nothing to drag and nothing to tidy.
|
|
|
|
That is on purpose. The edges come from message names, so a stored layout would
|
|
be a second, weaker description of the same thing, and something to merge when
|
|
two people edit the same flow. It also keeps flows honest: a graph nobody can
|
|
hand-arrange is one worth splitting.
|
|
|
|
What is drawn:
|
|
|
|
- **Your nodes**, with a status dot — running, succeeded, failed, or nothing at
|
|
all when idle. Status is always named in words too, never colour alone.
|
|
- **Edges**, which pulse when a value goes down them. Click one to inspect it.
|
|
- **Endpoints** — anything wired into this flow that is not a node in it: a
|
|
dashboard control writing a message, a tile reading one, a node in another
|
|
flow on the far side of a dotted name. Drawn as labelled boxes at the
|
|
boundary, so a value never appears to come from nowhere.
|
|
|
|
Values are live. The editor holds a websocket to the engine, and the connection
|
|
banner tells you when it is not.
|
|
|
|
## Adding a node
|
|
|
|
**Add node** on the dock, or ⌘K / Ctrl-K for the command palette, which also
|
|
jumps between flows and offers your shared nodes. Pick a type and it appears on
|
|
the canvas with its panel open.
|
|
|
|
## The node panel
|
|
|
|
Floats on the right; a full-screen sheet on a phone.
|
|
|
|
**Consumes** and **Provides** are the ports. Each row is a message name, a
|
|
payload type, and — on an output — a *streaming* toggle for ports that publish
|
|
repeatedly during one execution. The name field suggests messages already in
|
|
the flow, which is usually how you wire something: type the name that already
|
|
exists.
|
|
|
|
Renaming an output renames the message everywhere it is read. Inputs are not
|
|
renamed, because an input is more often re-pointed at a different message than
|
|
renamed.
|
|
|
|
**Settings** is generated from the node type's parameter schema — so an MQTT
|
|
node shows broker, topic and QoS, and an ntfy node shows server, topic and
|
|
priority. A field marked as a credential renders as a picker over your stored
|
|
[secrets](operations.md) instead of a text box.
|
|
|
|
A Function node gets a second settings section where you add your own: a
|
|
setting is a constant of this node's code and arrives as an argument beside its
|
|
ports. See [Where a node's values come from](../concepts/values.md).
|
|
|
|
**Timeout** (Function nodes) is how many seconds the code may be *silent*
|
|
before it is stopped: it measures silence, not duration, so a node that yields
|
|
every few seconds can run for hours under a timeout of 300. Left empty there is
|
|
no limit, which is the default — set one where a node going quiet means it is
|
|
stuck rather than working. A `0` says so explicitly.
|
|
|
|
**Code** is the editor. It saves as you type and applies on ⌘S; the node
|
|
reloads without the flow stopping. A node file defines `process(...)`; if it
|
|
defines exactly one public function under another name, that one is used
|
|
instead.
|
|
|
|
**Shared** turns a node's code into a library entry other flows can reuse.
|
|
Editing a shared node edits the copy every flow using it runs, which is the
|
|
point and also the caution.
|
|
|
|
!!! note "Not in the panel (yet)"
|
|
|
|
`device` and `device_policy` — which machine a node's code runs on — are set
|
|
through the API rather than the panel. See
|
|
[Remote workers](../code/workers.md).
|
|
|
|
## The flow panel
|
|
|
|
Click the canvas title to open the flow's own settings.
|
|
|
|
- **Running** — the switch that starts and stops the flow. Stopped means none
|
|
of its subscriptions, schedules or webhooks exist.
|
|
- **Mode** — `live` or `batch`. Live reacts to what arrives; batch only runs
|
|
when a run asks it to. See [Runs](../concepts/runs.md).
|
|
- **Inputs** — messages the flow takes from outside, with the value each starts
|
|
from. For a batch flow these are also the run's parameters.
|
|
- **Outputs** (batch only) — which messages a run reports as its result.
|
|
- **Contents** — a reminder that this flow's name namespaces every message
|
|
inside it.
|
|
|
|
## Inspecting an edge
|
|
|
|
Click a wire. You get the last payload that went down it, when, and a sparkline
|
|
of its recent numeric history. You can also republish that value from the node
|
|
that produced it, which re-runs everything downstream — the fastest way to test
|
|
a change without waiting for the real sensor.
|
|
|
|
## The dock
|
|
|
|
Along the bottom, floating over the canvas.
|
|
|
|
| Control | What it does |
|
|
|---|---|
|
|
| **Add node** | opens the palette |
|
|
| **Fit** | returns to the view the flow opened with |
|
|
| **Run** | injects a value by hand; on a batch flow, opens the parameters dialog |
|
|
| **Pause / Resume** | holds messages instead of running them |
|
|
| **Step** | releases exactly one held message |
|
|
| **Publish** | puts the draft live |
|
|
| **Discard** | throws the draft away |
|
|
| **Issues** | what is stopping this flow from running, per node |
|
|
| **Logs** | what the nodes printed, filterable |
|
|
|
|
Pause and step together are how you test a flow before it moves anything
|
|
physical: pause it, inject a value, step it through, watch the values appear on
|
|
the edges, then publish.
|
|
|
|
## Shortcuts
|
|
|
|
| Chord | Action |
|
|
|---|---|
|
|
| ⌘K / Ctrl-K | command palette |
|
|
| ⌘S / Ctrl-S | publish the flow — or, with focus in the code editor, apply the code |
|
|
| ⌘Z / ⌘⇧Z | undo / redo (the flow; the code editor has its own) |
|
|
| ⌘C / ⌘V | copy and paste nodes, including between flows |
|
|
|
|
## Drafts and publishing
|
|
|
|
Saving writes a draft; the engine keeps running what was published. Publishing
|
|
promotes it and reloads.
|
|
|
|
If someone else saved the same flow while you were working, publishing answers
|
|
with a conflict rather than overwriting them. The Flows list offers **Publish
|
|
all changes** when several flows are sitting on drafts.
|
|
|
|
## Issues
|
|
|
|
The canvas validates as you edit and marks the node each issue belongs to:
|
|
|
|
- a port that needs a message nothing in reach provides
|
|
- a message that exists but has never held a value
|
|
- a dependency cycle
|
|
- a node reading a message it also writes, with nothing to start it from
|
|
- code that did not load
|
|
- a webhook with no shared secret (advisory — it does not stop the flow)
|
|
|
|
A flow with any of these except the last does not run, and the health summary
|
|
on Home counts it.
|
|
|
|
## See also
|
|
|
|
- [Flows, nodes and messages](../concepts/flows.md) — the model behind the canvas
|
|
- [Node types](../reference/node-types.md) — everything the palette offers
|
|
- [Writing node code](../code/nodes.md) — what goes in the editor
|