Ein Workflow ist ein gerichteter Graph aus typisierten Knoten, die durch Kanten verbunden sind, im visuellen Builder erstellt und als YAML serialisiert. Die kanonische Form wird durch ein einzelnes JSON-Schema definiert, das aus derselben Zod-Quelle generiert wird, gegen die die Web-App validiert (web/src/lib/api-schemas-workflow.ts). Dokument, Editor und Laufzeit können daher nie voneinander abweichen.
Jeder aus dem Builder exportierte Workflow beginnt mit einer Modeline, die den yaml-language-server deines Editors auf das Schema zeigt und so Inline-Validierung sowie Autovervollständigung für Knotenarten bietet:
Stufen annotieren vorhandene Graph-Knoten; sie erzeugen weder Ausführungskanten
noch eine zweite Laufzeit. Jedes node_key muss einen Knoten desselben Workflows
benennen und darf nur einmal vorkommen. role ist bewusst ein offenes
semantisches Label, damit eigene und Marketplace-Workflows ihr Vokabular nutzen
können (häufig plan, implement und review). who ist optionale Metadaten
für den vorgesehenen Agenten, das Profil oder den Owner.
Feld
Typ
Hinweise
node_key
string
Erforderlicher Schlüssel eines vorhandenen Workflow-Knotens.
Führt einen KI-Coding-Agenten mit einem Prompt aus.
gate
Verzweigt anhand eines Prädikats auf verschiedene Ausgangs-Handles.
human
Hält an und wartet auf eine menschliche Entscheidung oder Eingabe.
end
Terminalknoten.
code
Führt ein Bash/Python/TypeScript/Go/Rust/C#-Snippet aus (Standard: Bash). Ungebunden: hermetischer Container, kein Netzwerk/DB. Ein Python/TypeScript-Node kann resource_bindings deklarieren, um in der berechtigungsgeführten Sandbox mit geprüftem Egress + host-vermitteltem, abgesichertem DB-Aufruf zu laufen (ADR 0058).
db_query
Liest aus einer gebundenen PostgreSQL-Ressource. params lösen ${{ nodes.* }}/${{ trigger.* }}/${{ steps.* }} typisiert auf (#990); der SQL-Text selbst wird bewusst nie templatisiert.
db_execute
Schreibt in eine gebundene PostgreSQL-Ressource. params lösen Referenzen wie db_query (#990); SQL-Text nie templatisiert.
http_request
Führt einen ausgehenden HTTP-Aufruf durch (SSRF-geschützt, IP-gebunden). url, headers und body lösen ${{ }}-Referenzen typisiert auf (#990); die aufgelöste URL durchläuft dieselbe SSRF-Prüfung wie eine literale.
transform
Formt Daten zwischen Knoten um.
notify_telegram
Sendet eine Telegram-Nachricht.
notify_email
Sendet eine E-Mail. Optional attachments (#1050): bis zu 5 Einträge aus content_b64 (Base64 oder eine ${{ nodes.<key>.<field> }}-Referenz), filename, content_type; 10 MiB dekodiert gesamt. Ein unauflösbarer oder nicht dekodierbarer Anhang lässt den Knoten laut fehlschlagen — eine Rechnungsmail geht nie hohl raus.
notify_webhook
Sendet einen POST-Request an einen Webhook.
notify_discord
Sendet eine Discord-Nachricht.
loop
Iteriert über eine Sammlung. over ist ein TYPISIERTER Wert-Slot (#990 Teil 2): eine einzelne ${{ nodes.<key>.<field> }}-/${{ trigger.<field> }}-Referenz, die zu einem Array auflöst, oder ein statisches JSON-Array-Literal. Die alte String-Interpolationsform wurde entfernt — ein gemischter String schlägt laut mit Migrationshinweis fehl.
wait_event
Hält an, bis ein externes Ereignis eintrifft.
llm_classify
Klassifiziert Eingaben mit einem LLM.
imap_ack
Bestätigt eine IMAP-Nachricht.
app
Ruft eine bereitgestellte App auf. inputs löst ${{ }}-Referenzen typisiert auf (#990).
connector
Führt einen Marketplace-Connector-Knoten aus. Optionaler resources-Pin (#1044): {"<resource_kind>": "<Resource-Name>"} wählt, WELCHE gleichartige Workspace-Resource jede benötigte Art bindet; eine ungepinnte Art behält den deterministischen first-by-name-Default, ein gepinnter, nicht existierender Name lässt den Lauf laut fehlschlagen.
ssh_exec
Führt EINEN Befehl auf einer gebundenen ssh_host-Ressource aus (#1049). Der command ist STATISCH (kein ${{ }}-Templating — das wäre ein Shell-Injection-Kanal); dynamische Daten laufen über stdin_b64. Die Ausgabe (stdout/stderr/exit_code) ist byte-gekappt; ein Remote-Exit ungleich 0 lässt den Knoten fehlschlagen. Host/Port werden SSRF-geprüft und IP-gepinnt; Key/Passwort kommen nur aus dem Ressourcen-Secret.
Ergebnisse vorgelagerter Knoten gelangen über SC_NODE_INPUTS an einen Knoten; ein Trigger-Payload über SC_TRIGGER_CONTEXT. Wie du einen Workflow im visuellen Builder erstellst, zeigt das Tutorial „Deinen ersten Workflow erstellen”.