Skip to content

Flow Control and Error Handling

Execution rules summary

There are strict rules that are followed by every node in the flow:

  1. To execute, all ports of the node that have connected edges must be resolved
    1. A port is resolved once at least one of its connected edges is resolved.
      1. An edge is resolved, once its source node is executed without an error.
  2. The node can only be executed once within the flow run.
  3. If there was an error during the node's execution,
    1. Its output ports don't resolve.
    2. Its flow-control.md output port resolves with true showing that execution was completed.
    3. Its #error-handling ports resolve with true and the error message.

Dependencies

Within the flow, every node can have or not have dependencies. These dependencies are generated from the edges that are connected to the input ports of the node. Generally, the execution engine starts executing the node once all its dependencies are resolved.

The example above has 3 random number nodes, the ones on the left have no dependencies, and the one on the right has 2. The flow will be executed starting from 2 nodes on the left (and they will be executed in parallel), and will be finished with executing the node on the right, once its both dependencies are resolved (executed without an error).

Connecting an edge to the node's input port makes it dependant on the node (or nodes) it's connected to through this edge.

Chaingraph allows connecting one port to multiple ones as well as multiple ports to one.

  • One-to-many is simple - the same value will be sent to all the connected input ports.
  • Many-to-one is not intended to be used as it's shown on the image, since it will produce unpredictable behaviour - the Create Message node will be executed with the Text that that arrived first, and the second resolved edge (and its source node) will be ignored. This type of connection is commonly used in cases when the flow design guarantees that only one of the connected edges is going to be resolved within the flow run. A good example of this is shown in #error-handlingsection.

Flow control ports

Every node has built-in ports in its header intended for additional control of its execution cycle. Both ports are of boolean type.

  • Input port: if there are edges, connected to it, once at least one of these edges is resolved:
    • If the port receives false, the node will go to "skipped" state, which prevents it from being executed in the current flow run no matter the other ports state.
    • If the port receives true, it starts executing, once all its input ports are resolved.
  • Output port:
    • Resolves with true once the execution of the node is finished no matter how (error state resolves the port in the same way as the success one).
    • There's no possible way for this port to resolve with false.

On the image above there's a random number that is generated within (0;100) boundary, and then the flow is split into 2 branches, depending on if the generated value is greater than 50 or not. Create Message nodes are controlled by the result of the comparison performed by the Branch node. Flow control ports with Not node placed before one of them make sure that either one or another Create Message node will be executed.

Error Handling

Every node has Error Handling expander with 2 built-in ports:

  • Error (boolean): resolves with true if there was an error during the node's execution. Having an error always means that output ports of the node (excluding flow-control.md and Error Handling ones) were not resolved.
  • Error Message (text): resolves with the text of the error message.

Builders are free to react to any error in the way they prefer, but there are some good practices we use in our agents that may be useful.

The first one is with the use of events.md: all the nodes that may potentially fail (the ones including web requests or complex computations) have their Error Handling ports connected to Event Emitters. They all may emit the same event, or different ones, based on how you plan to handle the errors.

Event listener node with the correct Event Name provided allows you to start a "sub-flow" (small and independent part of your big flow) once the error occurred.

The second one:

The flow above shows an example of how many-to-one connections can be used to handle errors that may occur within the flow to guarantee its completion. The Handlebars Template node is going to be executed either with a balance or with an error on its place instead of the balance.

If we imagine an LLM getting the Rendered Text of Handlebars Template node somewhere further in the flow, it will see the error and produce a relevant response, instead of not being executed at all because of a failed dependency (ERC20 Token Balance node).

Licensed under BUSL-1.1