The canvas is a drag-and-drop pipeline editor (built on Drawflow) for wiring repeatable
agent workflows out of typed nodes: fetch a page, summarize with Claude, pause for human
approval, push to Telegram. The canvas is just a view over a graph JSON — hitting Run
converts the graph you currently see into a staged run (topological sort; independent
nodes execute in parallel). Every run stores a snapshot of the flow definition
(runs/<id>/flow_snapshot.json) plus per-node params, output, duration, and errors
(runs/<id>/steps.json), so any run can be replayed or audited later.
Demo: fetch → AI summary → approve → notify
(flows/demo_daily_digest.json) from the flow selector.Parameter names below are exactly what flow_engine.py reads from params.
Any string param marked templatable accepts `` (see next section).
Runs a predefined console action (a registered local command) and captures its output.
action_id — id of a registered action (picked from the palette).tg node.Spawns a one-shot headless Claude CLI (claude -p) with your prompt on stdin.
prompt (templatable, required), model (e.g. sonnet; optional),
allow_tools (boolean — adds --dangerously-skip-permissions).{"model":"sonnet","prompt":"Summarize:\n"}.allow_tools off for flows that ingest untrusted input (web/file
content flows into the prompt — prompt injection is your risk to accept).
ANTHROPIC_API_KEY is stripped from the child env so the CLI stays on subscription
billing.Spawns Codex CLI as a read-only red team (codex exec --sandbox read-only) — it can
inspect the workroot but cannot write files. Use it for second opinions and reviews, not
for making changes.
prompt (templatable, required)."Red-team this plan for failure modes:\n".Human approval checkpoint. Pauses the run, pushes a Telegram button card (Approve / Reject), and waits. Anything other than approve stops the flow.
message (templatable; shown in the approval card), timeout (seconds,
default 7200).approved (on the approve path only).{"message":"Send this?\n","timeout":3600}.Runs a PowerShell command (powershell -NoProfile -Command <cmd>).
cmd (required), timeout (seconds, default 600).{"cmd":"Get-ChildItem C:\\Users\\me\\reports | Select -Last 5"}.cmd — upstream data
templated into a command string is an injection surface. The node raises an error if
the template appears; pass data between nodes via readfile/writefile instead.Downloads an http/https URL (2 MB cap, 30 s timeout) and optionally strips HTML tags.
url (templatable, required, must start with http:///https://),
strip_html (boolean, default true).claude node for finer cleanup.{"url":"https://news.ycombinator.com/","strip_html":true}.Sends a Telegram message via the configured bot.
text (templatable, required; truncated to 3800 chars on send).sent or failed.{"text":"📰 Daily digest:\n"}.Sleeps for a fixed interval — useful to space out API calls or wait for a file drop.
seconds (default 10, capped at 600).Reads a local text file via Python (UTF-8 first, falling back through
utf-8-sig / cp950 / big5 — avoids console codepage mangling). The path supports glob
patterns; with a glob it auto-picks the newest match by lexicographic sort, so dated
filenames like report_2026-08-03.json resolve to the latest one.
path (templatable, required; glob allowed).{"path":"Z:\\daily_info\\digest_*.json"}.Writes (or appends) text to a local file as UTF-8 via Python.
path (templatable, required), content (templatable),
append (boolean, default false; append mode adds a trailing newline).wrote <resolved path>.{"path":"C:\\Users\\me\\out\\digest.md","content":"","append":false}.resolve().relative_to(home) — substring tricks and .. traversal don’t work;
writes outside home are refused.BM25 full-text search (CJK-friendly) over your locally indexed markdown folders.
query (templatable, required), k (number of hits, default 5).---, first 6000 chars, each prefixed
[source].{"query":"warrant liquidity rules","k":5} feeding a claude node.Runs N parallel Claude calls on the same prompt from different angles (default angle set: optimistic / critical fault-finding / data-driven / user perspective / contrarian), then optionally merges them into one balanced conclusion with a final Claude call.
prompt (templatable, required), n (default 3, capped at 5),
model (default sonnet), angles (list of strings, optional),
merge (boolean, default true).--- if merge is
false (4000-char cap).Runs N parallel attempts at the prompt, then a judge call scores them on your criteria and the winning attempt’s text is passed downstream.
prompt (templatable, required), n (default 3, capped at 5),
model (default sonnet), criteria (default
"correctness, completeness, actionability").Inlines the stages of a registered server-side pipeline into the flow.
pipeline_id. Only useful if you have pipelines registered; most users won’t
need this node.Every node stores its output under its node id in a shared results map. Downstream
nodes reference it with double-brace templating, exactly:
n1, n2, … — visible in the exported/saved flow
JSON; ids match [A-Za-z0-9_-]). Whitespace inside the braces is tolerated:
`` also works.result
in the run detail if a prompt looks empty.prompt (claude/codex/swarm/tournament), message (gate),
text (tg), url (fetch), path (readfile/writefile), content (writefile),
query (kb). Not cmd (shell) — deliberately refused, see above.flow_snapshot.json records the exact graph that ran;
steps.json records per-node status, params, result (4000-char cap), duration, and
error.POST /api/runs/<id>/retry?mode=…:
original — rerun from that run’s snapshot: guaranteed-reproducible, even if the
flow was edited or deleted since.current — rerun from the currently saved version of the same flow id: picks up
your fixes. Fails with an explanation if the run was an unsaved canvas version or
the flow was deleted (retry with original instead).retry_of lineage back to the source run, and reports whether
the current version differs from the snapshot.