The workflow editor
The workflow editor is conversational-first, in two panes. On the left, the copilot composer — describe the job in plain language and the copilot proposes the trigger and steps for you, looking up real MCP tool names from the workspace's connections before it proposes a tool step. On the right, the pipeline pane — a Trigger card and a vertical strip of step cards, each of which expands into an inline inspector for direct editing. Neither lane is a fallback: the composer is the fastest way to rough a pipeline in, the strip is where you tune it.
The header carries the Workflow's name as an inline-editable field (Enter commits, Escape reverts), a save indicator, a Published or Draft chip, an Edit | Runs segmented control, the Run popover, and Publish. Because a Workflow builds nothing, Publish is instant — no build progress, no waiting; edits go live the moment you publish them.
Below 1180px of viewport width the two panes can't sit side by side, so a Compose | Pipeline segmented control swaps between them — with a pending-proposal count badged on Compose and an issue count on Pipeline. Both panes stay mounted through the flip, so nothing you typed is lost.
The trigger card
The Trigger card sits at the top of the pipeline pane, showing its kind and a one-line summary; clicking it expands the full trigger editor in place — a choice of Manual, Form, Webhook, Slack, or Schedule, each with its own draft-time configuration. (What each kind authenticates and delivers is covered in Triggers.)
- Manual needs no configuration — fire it from the Run popover.
- Form opens a field-schema builder: each row sets a Label, a Key (the
identifier
@trigger.<key>addresses), a Type (Text, Long text, Number, Select, Checkbox, or Date — Select additionally takes a comma-separated options list), and a Required toggle. - Webhook shows a note at draft time: publishing is what unlocks the live Ingress token card, where Generate token mints the token and reveals it exactly once — "Copy this now — we store only a hash" — with the ingress URL beside it, and Rotate token (behind a destructive confirmation) replaces it later.
- Slack shows the routing rules — a channel-id restriction, an "Only @mentions" toggle, an "Include direct messages" toggle — plus a live binding card with a Team select over the workspace's connected Slack integrations and a Bind / Update binding button. Draft rule edits don't change what's live until you push the update.
- Schedule is a five-field cron input, evaluated in UTC, with a live human-readable preview and a Valid / Unrecognized status chip.
The step strip
Under the trigger, each step renders as a card — a kind icon, its name or slug, and a one-line summary (the tool and connection it calls, the preset it prompts, the Agent it delegates to). A hairline spine connects the cards, and hovering a connector reveals a + that opens the add-step menu: the seven kinds, each with a one-line description, plus "Describe it instead", which hands off to the copilot composer. Nested steps — a For each body, a Branch's lanes — render indented under their container, and the loop kind is hidden inside a loop body, since loops don't nest.
Cards carry their diagnostics as issue-count badges, and pending copilot proposals render as dashed ghost cards at the position they'd land — an add at its target slot, an update or removal overlaid on the card it targets. Applying a proposal solidifies the ghost with a brief flash on the card it touched.
Step inspectors
Clicking a card expands its inspector inline, accordion-style — at most one thing is expanded at a time. What's inside depends on the kind:
- Tool — a connection select (with each connection's health state), a searchable tool picker over what the connection's server actually exposes, and argument fields. When the platform has the tool's input schema cached from a health probe, the args render as schema-aware fields; otherwise they're name-keyed template fields, with a raw-JSON toggle either way.
- Infer — a preset select and a prompt editor; optionally a structured output schema and an output-token cap.
- Agent — a picker over the workspace's published Agents, an instructions editor, and the session mode (fresh, or Slack-thread continuity where the trigger allows it).
- For each / Branch / Filter / State — the list to iterate, condition rows (a reference picker, an operator, a value), and state key/value rows.
Prompt and instructions editors support @ references: typing @ opens an
autocomplete listing everything addressable from that step's position —
trigger fields, earlier steps' outputs, state keys, @item inside a loop,
@now — each tagged with its source. Accepted references insert as atomic
chips that serialize back to the literal @token. The sources are computed
per position, so a step can never be offered a reference to something that
runs after it.
Deep infer and agent forms also offer Open full editor, which moves the form into a drawer with more room. And tool and infer steps carry a Test step popover that runs the real step server-side against a sample scope — side effects are real (a tool test genuinely calls the live server), and the result, success or failure, renders inline.
Running it manually
The header's Run popover dispatches through the same route production ingress uses — a real run, not a preview. Its body adapts to the trigger kind: manual and Slack triggers get a message textarea, form triggers get the real rendered field inputs, webhook triggers get a JSON payload textarea, and schedule triggers get just a "Fire now" confirmation, since a schedule carries no payload.
Runs always execute the Workflow's published snapshot, never the draft. If the Workflow is unpublished or has drifted since its last publish, the popover replaces the submit control with an amber note — "runs dispatch the published version" — and an inline Publish now button. On success it confirms "Run started" with a View run link into the run's step timeline, and the pipeline pane overlays live per-step progress on the strip until you dismiss it.
Publishing
Publish validates the pipeline, not just the syntax. Errors block it:
an empty pipeline, more than 50 declared steps, a missing or duplicate step
slug, an agent step bound to no Agent or to one with no published version,
a tool step on a connection that's missing, disabled, or personal rather
than workspace-scoped (unattended runs use workspace authority), an empty
prompt, a reference that's illegal for its position (@item outside a
loop, @steps pointing forward), and an invalid cron expression. One check
is deliberately only a warning: a tool name absent from the connection's
cached tool list — the server's live answer stays authoritative, so publish
proceeds.
Diagnostics attach to the step they concern — the card badges them, the inspector lists them — and every finding carries an "ask copilot to fix" affordance that pre-fills the composer with the issue.
After publishing, a second signal can appear: staleness. The published snapshot is re-checked against the workspace's live resources, so deleting a connection a published tool step uses, or unpublishing an Agent a published agent step binds, surfaces a warning on the Workflow — the affected step will fail at run time until you fix and republish.
The Runs tab
The Runs segment lists every run — trigger glyph, when it started, duration, status, and the failure message for failed runs. Opening one replays it as the same strip the editor uses, now as a timeline: per-step status badges, durations, iteration counters on loops, and attempt counts where a step retried. Live runs stream their progress in as it happens.
Clicking a step opens a drawer with every instance the run's ledger holds for it — a loop body step yields one per iteration — showing status, attempt, duration, and the step's rendered input and output. Agent steps embed the child run's full chat transcript in place, approvals included, so an open-ended step has the same depth here that a chat run has. Run URLs are shareable and survive reload.