Zum Inhalt springen
Farbschema wählenSprache wählen

Template-Namensräume

Die Konfiguration eines Workflow-Knotens kann ${{ … }}-Tokens enthalten. Jedes Token benennt einen Namensraum und einen Pfad darin; die Engine setzt den referenzierten Wert ein, bevor der Knoten ausgeführt wird.

Namensräume sind isoliert: Jeder Resolver verarbeitet ausschließlich seine eigenen Tokens und lässt jeden anderen Namensraum Byte für Byte unverändert. Die Resolver können daher nacheinander über dieselbe Zeichenkette laufen, ohne sich gegenseitig zu stören.

Welche Namensräume ein Knoten auflöst, hängt von seiner Art ab – die Abdeckung ist nicht einheitlich, und die Matrix weiter unten ist maßgeblich.

Namensraum Adressiert Aufgelöst aus
steps.<key>.<field> Das Ergebnis einer vorgelagerten Agent-Schritt-Aufgabe. <field> ist eines von branch, summary, pr_url, cost. tasks.git_branch sowie task_outcomes.summary / pr_url / cost_usd
trigger.<field> Der Payload, der den Lauf gestartet hat. Die trigger_context-Map des Laufs
inputs.<name>[.<slot>] Die deklarierten Eingaben eines App-Laufs. Text-, Zahlen-, Auswahl- und Checkbox-Eingaben lösen direkt auf; eine file-Eingabe stellt die Slots path, url, bytes, original_filename, mime, size_bytes und sha256_hex bereit. trigger_context.inputs und die app_uploads-Zeilen des Laufs
nodes.<key>.<path> Das Ergebnis-JSON eines beliebigen vorgelagerten Knotens – auch eines Nicht-Agent-Knotens. Die result-Spalte des Kindlaufs
resources.<name>.<field> Die nicht geheime Konfiguration einer Workspace-Ressource. Die öffentliche Konfiguration der resources-Zeile
secrets.<name> Ein Credential-Wert. Spät aufgelöst, durch die Credential-Schicht – nie durch einen Notify-Text, einen Classify-Anhang oder eine Connector-Eingabe

Derselbe nodes.*-Namensraum ersetzt in einem von zwei Modi. Der Modus ist pro Konsument festgelegt – er ist keine Entscheidung pro Token.

Modus Gilt für Verhalten
Text notify_*-Felder, der Anhang-Ausdruck von llm_classify Ersetzt in eine Zeichenkette. Ein Nicht-String-Wert wird als sein JSON-Text dargestellt. Ein nicht auflösbares Token bleibt wörtlich stehen, damit eine Fehlkonfiguration sichtbar bleibt, statt die Nachricht stillschweigend zu leeren.
Typisiert Die inputs eines connector-Knotens Ersetzt in einen JSON-Wertebaum. Ein nicht auflösbares Token lässt den Knoten fehlschlagen.

Im typisierten Modus wird eine Zeichenkette, die ausschließlich aus einem Token besteht, durch den referenzierten JSON-Wert selbst ersetzt – mit erhaltenem Typ:

# `rows` kommt als JSON-Array an, nicht als JSON-kodierte Zeichenkette.
inputs:
rows: "${{ nodes.collect.output.rows }}"

Ein Token innerhalb einer längeren Zeichenkette wird weiterhin als Text interpoliert, denn das Ergebnis muss eine Zeichenkette bleiben:

# `label` kommt als Zeichenkette "batch 42 of run alpha" an.
inputs:
label: "batch ${{ nodes.collect.output.count }} of run ${{ trigger.name }}"

Objekt-Schlüssel werden nie als Template behandelt – nur Werte, rekursiv durch Objekte und Arrays.

nodes.<key>.<path> löst in zwei Schritten auf:

  1. Eine exakte Feld-Übereinstimmung auf dem Ergebnisobjekt gewinnt. Damit löst jede bereits bestehende einstufige Referenz weiterhin genau so auf wie zuvor – einschließlich eines Feldes, dessen Wert JSON-null ist.
  2. Andernfalls wird der Punktpfad in das Ergebnis hinein gelaufen. Ein Objektfeld steigt ab; ein Segment, das sich als Ganzzahl lesen lässt, adressiert einen Array-Index. Ein Objektfeld, das buchstäblich 0 heißt, gewinnt weiterhin gegenüber der Array-Lesart.
inputs:
first_row: "${{ nodes.query.output.rows.0 }}"
city: "${{ nodes.query.output.rows.0.address.city }}"

Ein Pfad, der nichts erreicht, ist nicht aufgelöst – unterscheidbar von einem Feld, das tatsächlich null enthält. Die Tiefe ändert nicht, was ein Wert bedeutet:

Ergebnis Textmodus Typisierter Modus
Pfad löst zu einem Wert auf (auch null) Dargestellt (null wird zu null) Eingesetzt
Pfad erreicht nichts Token bleibt wörtlich stehen Knoten schlägt fehl

Eine Referenz ist auf 32 Segmente begrenzt, gezählt über die gesamte logische Referenz – nodes, den Knotenschlüssel und jedes Pfadsegment. Die Obergrenze gilt gemeinsam mit Gate-Bedingungen, sodass ein Template und eine Bedingung für dieselbe Referenz dasselbe Budget erhalten. Eine Referenz über der Grenze löst nicht auf.

Nur nodes.* hat mehrstufige Pfade:

Namensraum Pfadtiefe
steps.* 1 – ein fester Satz von vier Feldern
trigger.* 1 – eine flache Suche im Trigger-Kontext
inputs.* 1, plus ein fester Datei-Slot-Suffix
nodes.* N – erst exaktes Feld, dann der Punktpfad-Lauf

An jedem Knotenmodul gemessen. Die Asymmetrien sind real und tragend.

Knotenart / getemplateter Slot steps.* trigger.* inputs.* nodes.* resources.*
agent-Prompt ja ja ja nein nein
agent-Prompt innerhalb eines loop-Körpers ja ja nein nein nein
human-Prompt ja ja nein nein nein
loop-over-Ausdruck ja ja nein nein nein
notify_*-Felder ja ja nein ja (Text) ja
llm_classify-Anhang-Ausdruck ja ja ja ja (Text) ja
code-Quelltext ja ja ja nein nein
connector-inputs ja ja ja ja (typisiert) nein
jede andere Art nein nein nein nein nein

„Jede andere Art“ – gate, end, transform, db_query, db_execute, http_request, imap_ack, wait_event, app – löst keinen ${{ }}-Namensraum auf.

Zwei Asymmetrien werden leicht übersehen:

  • Ein agent-Prompt löst inputs.* auf oberster Ebene auf, nicht aber innerhalb eines loop-Körpers.
  • Der Payload von llm_classify wird überhaupt nicht getemplatet. Nur sein Anhang-Ausdruck.

Es gibt zwei Obergrenzen. Sie regeln unterschiedliche Pfade und sind bewusst nicht dieselbe Zahl.

Obergrenze Regelt Bei Überschreitung
8 MiB Den Payload eines connector-Knotens – die aufgelösten inputs, die er erhält, und alles, was er in sein Laufergebnis schreibt: die Ausgabe eines Erfolgs, die Fehlermeldung eines Fehlschlags Der Knoten schlägt laut fehl und nennt den Knotenschlüssel und die tatsächliche Größe. Nie gekürzt.
1 MiB Den Inline-Bytes-Zweig des Datei-Slot-Namensraums, ${{ inputs.<name>.bytes }} Der bytes-Slot wird übersprungen; das Token bleibt wörtlich stehen, damit ein nachgelagerter Knoten es sichtbar machen kann

Die Connector-Obergrenze ist absichtlich symmetrisch. Der Payload eines Connectors wird in die result-Spalte seines Kindlaufs geschrieben, und genau diese Spalte liest der nodes.*-Namensraum. Ein ungedeckelter Payload würde daher einen Knoten später zur ungedeckelten typisierten Eingabe, und der Eingabewächter würde gegen den konsumierenden Knoten auslösen – für einen Payload, den der erzeugende Knoten angelegt hat. Eine Konstante deckelt beide Richtungen, sodass der Knoten, der einen zu großen Payload erzeugt hat, auch der Knoten ist, der fehlschlägt.

Das gilt auch für einen fehlgeschlagenen Lauf. Ein Fehlschlag verwirft die Ausgabe, schreibt aber die Fehlermeldung des Gasts in dasselbe result, wo ${{ nodes.<key>.error }} sie genauso liest wie .output – die Fehlermeldung wird deshalb an derselben Obergrenze gemessen, und eine zu große Meldung lässt den Knoten fehlschlagen, der sie erzeugt hat, statt weiterzureisen.

Der Eingabewächter läuft nach der typisierten Auflösung und misst damit, was der Connector wirklich erhalten würde – einschließlich der durch Ersetzung eingefügten Ganzwerte.

Die typisierte Ersetzung fügt einen ganzen Wert ein, sodass eine einzelne Referenz das vollständige Ergebnis eines vorherigen Knotens tragen kann. Oberhalb der Obergrenze reist der Payload gar nicht mehr inline.

Das unterstützte Muster ist, einen Namen plus einen Pfad zu übergeben und den Connector die Bytes aus seiner eigenen gebundenen Ressource streamen zu lassen – über die Egress-Autorität, die diese Ressource ohnehin freischaltet:

# Statt die Dokument-Bytes einzubetten, reist eine Referenz darauf.
inputs:
documents:
- name: "invoice-2026-08.pdf"
path: "/exports/2026/08/invoice-2026-08.pdf"

Die nodes.*-Referenzen eines connector-Knotens werden beim Speichern, Installieren oder Seeden geprüft – nicht beim ersten Lauf. Die vollständige Spezifikation liegt in diesem Moment vor, eine kaputte Referenz ist also genau dort entscheidbar.

Abgelehnt Grund
Der referenzierte Knotenschlüssel existiert nicht im Workflow Ein Tippfehler würde sonst erst Monate später beim ersten echten Lauf auffallen
Der Knoten referenziert sein eigenes Ergebnis Sein Ergebnis existiert nicht, während er läuft
Der referenzierte Knoten ist nicht vorgelagert im DAG Sein Ergebnis existiert noch nicht, wenn dieser Knoten läuft

Vorgelagert heißt: rückwärts erreichbar über die Kanten des Graphen plus die Enthaltensein-Kante des Schleifenkörpers – ein in einem loop verschachtelter Knoten sieht berechtigterweise alles, was sein übergeordneter Rahmen sieht.

Das Connector-Eigenschaftenfeld im Workflow-Builder wertet dieselben drei Regeln bereits während der Eingabe aus und benennt die vorgelagerten Knotenschlüssel, die vom ausgewählten Knoten aus tatsächlich referenzierbar sind.