Skip to main content

Node Types

Every workflow is a directed graph of nodes. Each node has a type that determines what it does at runtime, and a config object that controls its behavior. Nodes are connected by edges; the runtime follows edges to determine execution order.


Palette categories​

CategoryNode types
Coreagent, classify, end, note
Toolsfile_search, guardrails, mcp
Logicif_else, while_loop, user_approval, sub_workflow
Datatransform, set_state

There is also a built-in start node that every workflow begins from. It is added automatically and cannot be deleted.

Every node supports on_error

Any node's config accepts on_error: skip to let the rest of the graph continue past that node's failure instead of halting the run — see Run Infrastructure → Resilience & fault handling.


Core​

agent​

Runs an AI agent for one turn. The node sends a prompt to an LLM and stores the response in workflow state.

Modes:

ModeHow to configure
Prompt modeFill in system_prompt directly in the properties panel
Skill modeSet skill_id to reference a saved Skill. The skill's system prompt, tools, and knowledge are merged in

Config fields:

FieldDescription
system_promptInline instructions for the agent (Prompt mode)
skill_idID of a Skill to load (Skill mode — overrides inline prompt)
modelModel override. Leave blank to use the instance default
toolsList of tool names to enable for this node
knowledge_idsKnowledge bases to search before the agent responds
execution_modeauto (default) or review — see Run Infrastructure
input_keyState key to read as the user message. Defaults to input
output_keyState key to write the agent response into. Defaults to output

classify​

Routes workflow execution along one of several labelled edges based on AI classification.

The node sends the current state to an LLM with a list of categories. The model returns one category label, and the runtime follows the matching outgoing edge.

Config fields:

FieldDescription
categoriesComma-separated or JSON list of label strings (e.g. positive, negative, neutral)
system_promptOptional instruction to guide the classification model
modelModel override
input_keyState key with the text to classify

Edges: Draw one outgoing edge per category label. Label the edge with the exact category string.

Label matching: The runtime matches the model's output against your category list using these rules in order:

  1. Exact match (case-insensitive) — preferred.
  2. Partial match — if the LLM adds punctuation or a trailing explanation, the runtime checks whether any class label appears as a substring of the output.
  3. Fallback — if neither matches, the first category in the list is used, and a warning is logged. The workflow does not stop.
tip

Always list the most likely or safest category first so the fallback is a sensible default.

The workflow stops with an error only if the categories list is empty — validate your classify nodes before publishing (the graph validator rejects empty class lists at stage time).


end​

Terminates workflow execution and marks the run as complete. Every workflow must have at least one end node.

Config fields: none — this node requires no configuration.


note​

A sticky-note annotation on the canvas. Notes are not executed; they exist purely for documentation and team communication within the editor.

Config fields:

FieldDescription
contentThe text to display on the canvas

Tools​

Performs a vector search over one or more Knowledge bases and injects the retrieved chunks into workflow state.

Config fields:

FieldDescription
knowledge_idsList of Knowledge base IDs to search
query_keyState key containing the search query. Defaults to input
output_keyState key to write retrieved context into. Defaults to context
top_kNumber of chunks to retrieve (default: 5)

guardrails​

Evaluates content against a list of rules using an LLM call. If the content fails any rule, the workflow halts immediately with an error — execution does not continue to downstream nodes.

Config fields:

FieldDescription
rulesList of rule strings to enforce (one per line in the editor), e.g. "No PII in output", "Must cite a source"
input_keyState key with the content to check

The model is asked to reply PASS or FAIL: <reason>. The runtime handles all outcomes:

LLM outputWhat happens
Begins with PASSWorkflow continues to the next node
Begins with FAILWorkflow halts immediately; the reason is surfaced as the run's error message
Empty outputTreated as an error (not a silent pass) — run halts with [guardrails: LLM returned empty output]

A node_complete SSE event is emitted before the node_error event, so the run timeline always has a complete record of every node that executed.


mcp​

Calls an external tool via the Model Context Protocol. Connects to a remote MCP server (HTTP or SSE transport), invokes a specific tool, and writes the result into workflow state.

Config fields:

FieldDescription
server_urlHTTP(S) URL of the MCP server (e.g. https://my-mcp.example.com/mcp)
tool_nameName of the tool to call on the server
argumentsJSON object of arguments to pass to the tool
output_keyState key to write the tool response into (default: output)
auth_tokenBearer token for the MCP server. Stored encrypted; displayed as •••••••• in the UI and API responses. Leave blank if the server requires no auth.

Security:

  • server_url is validated against an SSRF allowlist before the request is sent. Private IP ranges (10.x, 192.168.x, 169.254.x, 127.x, ::1, etc.) and link-local addresses are blocked to prevent server-side request forgery.
  • auth_token is stored encrypted at rest and is never returned in API responses — editing the node shows the sentinel value ••••••••. To update the token, type a new value; to keep the existing one, leave it as-is.
MCP server naming

If you are using hrida-mcpo as the MCP server, the server name in config.json must match the agent or Digital Employee slug (e.g. hr-agent). The tool endpoint will be at {mcpo_base_url}/{server_name}/tools/call.


Logic​

if_else​

Evaluates a Python expression against the current workflow state and branches execution.

Config fields:

FieldDescription
conditionPython expression that evaluates to True or False. State variables are available via state and input (e.g. state.get('score', 0) > 0.8)
true_labelLabel of the outgoing edge to follow when the condition is True (default: true)
false_labelLabel of the outgoing edge to follow when the condition is False (default: false)

Edges: Draw two outgoing edges labelled to match true_label and false_label.

Expression context:

VariableValue
stateFull workflow state dictionary — state['key'] or state.get('key', default)
inputThe current workflow input string

Allowed built-ins: abs, all, any, bool, dict, enumerate, filter, float, int, len, list, map, max, min, reversed, round, set, sorted, str, sum, tuple, zip.

isinstance and repr are not available

Unlike every other built-in listed above, these two can't be added to the sandbox — the underlying expression library (simpleeval) hardcodes both in its own safety blocklist for defense-in-depth, rejected at evaluator construction time no matter how the sandbox is configured. If you need a type check, compare against a literal instead (e.g. type(state['x']) == type('') won't work either — restructure the workflow to avoid needing runtime type introspection, or do the check in an upstream transform/agent node using plain Python string/value comparisons).

Validation: The expression is syntax-checked when you stage or publish the workflow. Errors surface as validation warnings before the workflow can go live.

If the expression raises an error at runtime, the condition defaults to False (takes the false branch) and a warning is attached to that node's node_complete event — visible in the run stream/timeline, not just the server log.


while_loop​

A conditional router that repeats a subgraph path until a condition becomes False or a maximum iteration count is reached. The node emits one of two output values on each execution — "continue" or "done" — and the runtime follows the matching outgoing edge.

Config fields:

FieldDescription
conditionPython expression evaluated on each pass. Same context as if_else — state and input are available. When True the loop continues; when False execution exits.
max_iterationsHard limit on iterations (1–100, default: 10). When reached, the loop exits regardless of the condition to prevent runaway workflows.

Edges: Draw two outgoing edges from this node:

Edge labelWhen followed
continueCondition is True and max_iterations not yet reached — loop body executes
doneCondition is False or max_iterations reached — loop exits

Iteration counter: The current iteration count is stored in workflow state under the key _while_{node_id}_iter. Downstream nodes can read this key (e.g. in a transform or if_else) if they need to know how many times the loop has run.

Example — retry until quality passes:

start
→ set_state [state.quality = 0]
→ while_loop [condition: state.get('quality', 0) < 0.8, max_iterations: 5]
→ (continue) → agent → set_state [state.quality = ...] → while_loop
→ (done) → end
BFS execution model

The runtime uses BFS (breadth-first) topological execution. True back-edges (a node downstream of while_loop looping back to it) are placed in a special "last level" and run once per workflow execution. For genuine multi-iteration loops, the while_loop node itself re-evaluates its condition each time it is reached in the BFS traversal — effective when the loop body updates the condition variable and the graph topology forms a cycle.

If the condition expression fails at runtime, it defaults to False (exits the loop) and a warning is attached to that node's node_complete event — visible in the run stream/timeline, not just the server log.


user_approval​

Pauses workflow execution and creates an inbox task for a human reviewer. Unlike agent nodes in review mode (which run the LLM first and pause on its output), user_approval pauses immediately — the configured prompt text itself is what the reviewer sees and decides on.

Config fields:

FieldDescription
promptText shown to the reviewer as the task description
review_groupWho can see and decide the task — a space role (e.g. lifecycle_manager) or an admin-console group (group:{id}), selectable in the properties panel
review_timeout_minutesMinutes before the task expires (minimum 15, server-enforced)
timeout_actionWhat happens if no one decides in time: auto_proceed, reject, or escalate
timeout_escalate_groupOnly used when timeout_action is escalate — the role or group the task is reassigned to

When this node is reached, the run pauses and an inbox task is created. The reviewer sees it in Dashboard > Inbox, decides (approve / reject / delegate), and the run resumes from the next node in sequence — user_approval does not branch by edge label. See Inbox for the full decision flow.


Data​

transform​

Applies a Python expression to reshape or compute values in workflow state.

Config fields:

FieldDescription
expressionPython expression. The result is assigned to output_key. State variables are available as locals
input_keyState key to read (exposed as value in the expression)
output_keyState key to write the result into

Expression context:

VariableValue
stateFull workflow state dictionary
inputCurrent workflow input string
valueShorthand for the value at input_key in state

Allowed built-ins: Same whitelist as if_else — abs, all, any, bool, dict, enumerate, filter, float, int, len, list, map, max, min, reversed, round, set, sorted, str, sum, tuple, zip. isinstance/repr are not available (see the note above if_else's expression context).

Example: Strip whitespace from a string:

value.strip()

Compute a word count:

len(value.split())

Build a summary string using state keys:

f"Score: {state.get('score', 0):.2f} — {state.get('label', 'unknown')}"

Validation: Syntax is checked at stage/publish time. If an expression fails at runtime, the error is written as the node's output (prefixed [transform error: ...]) rather than crashing the run, giving you a visible signal without losing the full run timeline.


set_state​

Sets a key in workflow state. The value supports the same sandboxed Python expressions as transform and if_else — useful for counters, computed flags, or dynamic values, not just static literals.

Config fields:

FieldDescription
state_keyThe state key to write
state_valueA literal string (e.g. pending), or an expression referencing state/input (e.g. state['count'] + 1). If the value isn't a valid expression, it's stored as the literal text — existing static-value workflows are unaffected

sub_workflow​

Invokes another published workflow inline and uses its final output as this node's output. Wired by the workflow author at build time — the target is fixed in the graph, not decided dynamically.

Config fields:

FieldDescription
workflow_idThe published workflow to invoke (selected from a dropdown of published workflows)
input_expressionOptional Python expression for the child's input (e.g. state['summary']). Leave blank to pass the previous node's output
Recursion is not detected

Unlike the trigger_workflow tool, a sub_workflow node does not guard against calling itself or forming a cycle (A → B → A). Avoid wiring a workflow's sub_workflow node back to itself or to an ancestor in its own call chain — this can hang until the workflow's wall-clock timeout is reached.

If you need an AI agent to decide at runtime whether and which workflow to delegate to, use the trigger_workflow tool on an agent node instead — it includes a built-in recursion guard.

The child run is linked back to the parent

The run this node spawns records parent_run_id/parent_node_id pointing back to the calling run and this node — so the full call chain (however many levels deep) can be viewed as a tree instead of disconnected runs. See Traceability & Audit Log → chain correlation.


Edges and conditions​

Edges connect an output connector on one node to an input connector on another. Most edges are unconditional — the runtime follows them automatically after the source node finishes.

For classify and if_else, edges carry a label matching the node's output (a category name, or true/false). The runtime follows only the edge(s) whose label matches — every node reachable solely through a non-matching branch is skipped, not just left unexecuted in isolation.

user_approval does not branch by edge label — the run always continues to the next node in sequence after a decision. while_loop emits "continue" or "done" and the runtime skips all nodes reachable only through the non-matching branch (same blocking logic as if_else and classify).

To label an edge: click the edge after drawing it and type the label in the properties panel.


Canvas tips​

  • Add a node: Drag from the palette onto the canvas.
  • Connect nodes: Hover over a node until connectors appear; drag from a connector to another node.
  • Delete: Select a node or edge and press Delete / Backspace.
  • Multi-select: Hold Shift and click multiple nodes; drag to box-select.
  • Zoom: Scroll wheel, or use the zoom controls in the bottom-right.
  • Auto-arrange: The AI Assist generate feature places new nodes with automatic layout. Manual positioning is always available by dragging.
Hrida.ai is proprietary software of Zlabs Innovation. See the license for terms. © 2026 Zlabs Innovation.