Workflow Nodes And Branches
Workflow nodes describe what Dawn runs after a trigger fires. Agent-run nodes call agents. Control nodes shape graph behavior with fan-out, joins, conditions, and bounded loops.
Node Model
Workflow definitions store executable work as steps. On the canvas, each step is a node.
| Field | Applies to | Meaning |
|---|---|---|
nodeKey | All nodes | Stable graph identifier. Other nodes depend on this value. |
order | All nodes | Display and planning order. |
name | All nodes | Human-readable node label. |
stepType | All nodes | agent_run or control. |
dependsOn | All nodes | Parent node keys that must finish before this node is considered. |
prompt | agent_run | Instructions sent to the selected agent. |
agentProfileId | agent_run | Optional per-step agent override. |
settingsJson | control | JSON string with control-node settings. |
Root nodes use an empty dependsOn list. They become executable after the trigger/start node completes.
Agent-Run Nodes
agent_run is the main work node. It launches a child Dawn conversation for the workflow step, runs the selected agent, and records the final output.
Use an agent_run node for:
- PR review;
- issue or work item triage;
- CI inspection;
- summarization;
- result preparation;
- any step that needs Dawn tools, sources, memory, skills, or Prompt Commands.
The prompt can include normal instructions or a Prompt Command invocation:
/pr-review
Review the pull request that triggered this workflow. Focus on correctness, regressions, security-sensitive changes, and missing tests.
Prompt Commands are resolved at runtime the same way they are resolved in chat. The workflow still uses the workflow event context and the selected agent’s allowed tools and sources.
Control Nodes
Control nodes use stepType: "control" and a settingsJson JSON string.
| Control type | Value | Purpose |
|---|---|---|
| No-op | noop | Completes immediately. Useful as a placeholder or named graph junction. |
| Fan-out | fanout | Marks an intentional split before parallel branches. |
| Join | join | Waits for upstream branches and decides whether downstream work can run. |
| Condition | condition | Routes execution to one pass branch or one fail branch. |
| Loop | loop | Repeats upstream agent-run nodes until a condition matches or a max iteration count is reached. |
If settingsJson is missing or invalid, Dawn treats the control node as noop.
Shared Control Settings
{
"controlType": "join",
"joinPolicy": "all_successful",
"quorum": 1,
"condition": {
"path": "upstream.review.output.hasFindings",
"operator": "equals",
"value": true
},
"maxIterations": 3,
"repeatNodeKeys": ["review"],
"passNodeKeys": ["publish"],
"failNodeKeys": ["request_changes"]
}
Only the fields relevant to the selected controlType are used.
Fan-Out
Fan-out is mostly a canvas/documentation node. It completes immediately and makes it clear that several downstream branches are intended to run independently.
{
"controlType": "fanout"
}
You can also skip the fan-out node and make several agent_run nodes depend on the same parent, or no parent at all, when you want parallel root work.
Join
Join nodes coordinate parallel branches.
{
"controlType": "join",
"joinPolicy": "all_terminal"
}
Supported joinPolicy values:
| Value | Behavior |
|---|---|
all_successful | Complete only when all upstream dependencies completed successfully. |
all_terminal | Complete when every upstream dependency is terminal, even if some failed or were skipped. |
first_successful | Complete when any upstream dependency completed successfully. |
quorum | Complete when at least quorum upstream dependencies completed successfully. |
For PR reviews with independent branches, all_terminal is often better than all_successful because it lets a summary step report partial failures instead of blocking the whole workflow.
Conditions
A condition node evaluates a small JSON condition against the run context and upstream outputs. It must have exactly one pass target and one fail target.
{
"controlType": "condition",
"condition": {
"path": "upstream.review.output.hasFindings",
"operator": "equals",
"value": true
},
"passNodeKeys": ["post_findings"],
"failNodeKeys": ["post_clean_result"]
}
Supported operators:
| Operator | Behavior |
|---|---|
exists | True when the path exists. |
not_exists | True when the path does not exist. |
equals | True when the resolved value equals value or equals, compared as text. Default operator. |
not_equals | True when the path is missing or the value does not equal value or equals. |
contains | True when the resolved value contains the expected value as text, case-insensitive. |
Supported condition root fields:
| Root path | Meaning |
|---|---|
manualInput | JSON passed to a manual or agent-started run. |
triggerEvent | Normalized event JSON. |
subject.kind | Subject kind for the run. |
subject.externalId | Provider subject ID or key. |
subject.title | Subject title. |
subject.url | Subject URL. |
upstream.{nodeKey}.Status | Upstream step status. |
upstream.{nodeKey}.OutputText | Upstream text output. |
upstream.{nodeKey}.output | Upstream structured output JSON. |
Condition paths are dot-separated property paths. They do not support array indexing, JavaScript expressions, or arbitrary functions.
Condition Branch Rules
For a condition node:
conditionmust containpathorleft.passNodeKeysmust contain exactly one node key.failNodeKeysmust contain exactly one node key.- Pass and fail targets must be different.
- Each pass/fail target must include the condition node in its
dependsOn. - No other node may depend directly on the condition node unless it is the pass or fail target.
Loops
Loop nodes repeat one or more upstream agent_run nodes. The loop queues another iteration only when its condition evaluates false and the max iteration count has not been reached.
{
"controlType": "loop",
"condition": {
"path": "upstream.review.output.ready",
"operator": "equals",
"value": true
},
"repeatNodeKeys": ["review"],
"maxIterations": 3
}
Loop rules:
maxIterationsmust be at least 2.maxIterationscannot exceed 25.repeatNodeKeysis required.- A condition path is required.
- Repeated nodes must exist.
- Repeated nodes must be upstream of the loop node.
- Repeated nodes must be
agent_runnodes.
Use loops sparingly. They are useful for bounded refinement, such as “ask for missing information, then re-check readiness.” They are not a replacement for long-running polling.
Dependency And Status Behavior
Downstream nodes only become ready when dependency gates allow them. If an upstream dependency fails, downstream nodes can be skipped unless a join or condition explicitly handles that path.
Step status values are documented in Workflow Runs And Statuses.
Canvas Layout
layoutJson is UI-only data. It can record node positions and viewport state, but it does not affect execution. Execution is driven by steps, nodeKey, dependsOn, and control-node settingsJson.
Agents creating workflows should not rely on layout data for correctness. Build a valid graph first, then let the canvas auto-arrange it.