Entry and exit

A graph has two boundaries: entry, where the request arrives, and exit, where the answer leaves. Both obey strict rules — breaking them used to fail quietly, throwing half the work away rather than stopping the run.

Exactly one entry

An entry is the run’s input, not a start marker. The engine parses the same input object for every entry node, so a second one cannot carry a second input: it duplicates the first and starts a second branch that is synchronised with nothing. Both chains run in full, and both are billed.

Two entries are therefore the graph.multiple_entry error. It is unconditional: there is no draft state in which two entries lead to something valid. The error does not stop you from saving the graph, but it does block deploy and run.

The editor will not let you create a second entry: dropping one from the palette is ignored when the canvas already has an entry, and when you paste a ready-made snippet its entry is mapped onto the existing one — every edge from it lands on the real entry.

The entry’s two outputs

  • output — the message. For chat, Telegram and webhooks this is a string with no fields. When the run was started with an arbitrary JSON object (a manual run, the API, a call from another workflow), it is that whole object.
  • data — the trigger context, a fixed shape: trigger, workflow_id, execution_id, workspace_id, user_id, chat.session_id and the telegram / webhook / cron blocks.

At least one exit, and it has to be reachable

A graph with no exit gets the graph.no_exit warning. The worse case is an exit that exists but is reached by no exec or execute_data edge. Such an exit never runs, and the execution ends with an empty result — the validator rejects it with exec.exit_no_exec_trigger.

A template reference does not start a node: {{ nodes.<id>.output }} reads a value but never makes the exit fire.

What the exit does

  • The end port takes the final value. The Output Expression (output_mapping) field, when non-empty, replaces whatever arrived on end.
  • A separate files input takes file references, and they leave together with the answer: images, audio and attachments are shown next to the chat message.
  • The Error message (error_text) field sets the text a user sees after an unhandled failure. error (a short, safe description of the failure), error_code, error_id (the reference code for support), failed_node_id and failed_node_type are available inside it. Technical detail — a provider’s reply, the text of a database query — is not, at any setting: this message is read by the person talking to your workflow, not by you. The full picture stays in the node card and the run logs.

Several exits: only for mutually exclusive branches

Every exit that ran writes into one and the same result object. The winner is not the one that finished last, but the last one in the order the nodes are listed in the graph definition — reordering that list changes the answer. In chat the rule is different: the exit that started streaming first is the one shown, and the other one’s tokens go nowhere.

Two exits that can fire in the same run are therefore exec.multi_exit_race: an error at deploy and run, a warning while you are still editing.

If / Else
Exit
Exit
  • Execute + Data
Each leg of a condition may have its own exit: exactly one of them runs.

How to fix the race

Merge the branches into one exit. If they genuinely run in parallel, put a wait_all in front of it and wire every branch into its barrier_in handle. Giving each parallel branch its own exit is not a way out — that is precisely the shape in which one answer overwrites the other.