Node Types

AgentFlow provides eight node types that can be combined to build any workflow — from simple automation to complex multi-stage pipelines with loops, human oversight, and more.

AI Task

Executes Claude Code CLI with custom instructions. This is the primary node for AI-powered code generation, review, refactoring, and analysis.

PropertyTypeDescription
instructions*stringThe prompt sent to Claude. Supports variable substitution and {output.NODE_ID} references.
agentstringAgent name referencing .claude/agents/{name}.md for system instructions.
modelstringClaude model override for this node: "opus", "sonnet", or "haiku". Defaults to pipeline/global setting.
requires_toolsstring[]MCP tools that must be available for this task.
retry{ max, delay }Retry policy for failed invocations.
timeoutnumberMax execution time in seconds.
How AI Task executes
bash
# With agent:
claude --agent code-reviewer --print "Review changed files for security issues"

# Without agent:
claude --print "Generate unit tests for src/utils.ts"

# Cost is extracted from Claude CLI stderr:
# Looks for "Total cost: $X.XX" or "total_cost_usd: X.XX"

Info

AI Task is the only node type that incurs token costs. Costs are automatically parsed from the Claude CLI output and stored in the database for tracking. Output caching can skip re-execution if the node's instructions haven't changed since the last successful run.

Shell Command

Executes any bash command. Use for running tests, building projects, linting, deploying, or any CLI operation.

PropertyTypeDescription
instructions*stringThe bash command to execute.
retry{ max, delay }Retry on non-zero exit code.
timeoutnumberKill process after N seconds.
Execution
bash
# Commands run via:
bash -c "{instructions}"

# stdout and stderr are streamed to the live log viewer
# Exit code 0 = success, non-zero = failure
Examples
text
npm run test -- --coverage
cargo build --release
docker compose up -d
eslint src/ --fix

Git Operation

Runs git commands as part of your pipeline. Functionally identical to Shell but semantically distinct for clarity on the canvas.

PropertyTypeDescription
instructions*stringThe git command to execute.
retry{ max, delay }Retry on failure.
timeoutnumberMax execution time.
Examples
text
git checkout -b feature/auto-fixes
git add -A && git commit -m "feat: AI-generated changes"
git push origin HEAD
git merge origin/main --no-edit

Parallel

A container node that runs all its children simultaneously and waits for every child to complete before continuing.

PropertyTypeDescription
children*string[]Array of child node IDs to run concurrently.
instructionsstringOptional description (not executed).
Behavior
text
1. All child nodes are spawned concurrently via tokio::task::JoinSet
2. Results are processed in completion order (not spawn order)
3. Execution blocks until ALL children complete
4. Status = "success" only if ALL children succeed
5. Status = "failed" if ANY child fails
6. Individual child status is tracked separately
Example: parallel testing
json
{
  "id": "node-parallel",
  "name": "Run All Checks",
  "type": "parallel",
  "instructions": "Run lint, test, and type-check in parallel",
  "children": ["node-lint", "node-test", "node-typecheck"],
  "inputs": [],
  "outputs": [],
  "position": { "x": 250, "y": 150 }
}

Loop

Iterates over a list of items, executing child steps for each one. Supports configurable separators (newline, comma, custom), max iteration caps, and injects per-item variables into child node instructions.

PropertyTypeDescription
instructions*stringThe list of items to iterate over, or an expression that produces a list.
children*string[]Array of child node IDs to execute for each loop item.
loop_configLoopConfigConfiguration for loop behavior (separator, max iterations, timeout, model).
retry{ max, delay }Retry policy for the entire loop.
timeoutnumberMax execution time for the entire loop.
Loop configuration
json
{
  "loop_config": {
    "separator": "newline",   // "newline" | "comma" | custom string
    "max_iterations": 100,    // Cap iterations (1-1000)
    "timeout": 600,           // Per-loop timeout in seconds
    "model": "sonnet"         // Model override for AI children
  }
}
Loop variables injected per iteration
text
$LOOP_ITEM   — The current item from the list
$LOOP_INDEX  — Zero-based index of the current iteration
$LOOP_COUNT  — Total number of items in the list

# Example: if instructions = "file1.ts\nfile2.ts\nfile3.ts"
# Iteration 0: $LOOP_ITEM="file1.ts", $LOOP_INDEX=0, $LOOP_COUNT=3
# Iteration 1: $LOOP_ITEM="file2.ts", $LOOP_INDEX=1, $LOOP_COUNT=3
# Iteration 2: $LOOP_ITEM="file3.ts", $LOOP_INDEX=2, $LOOP_COUNT=3
Example: review each changed file
json
{
  "id": "node-loop",
  "name": "Review Each File",
  "type": "loop",
  "instructions": "src/auth.ts\nsrc/api.ts\nsrc/db.ts",
  "children": ["node-review"],
  "loop_config": {
    "separator": "newline",
    "max_iterations": 50
  },
  "inputs": [],
  "outputs": [],
  "position": { "x": 250, "y": 150 }
}

Loop-aware cost estimation

Pre-run cost estimates account for loop iterations — the estimated cost of child AI Task nodes is multiplied by the expected iteration count. Set max_iterations to cap both runtime and estimated cost.

Info

Loop nodes use Arc-wrapped read-only data for parallel child spawns, eliminating deep-clone overhead. Results are processed in completion order via Tokio JoinSet for maximum throughput.

Approval Gate

Pauses pipeline execution and waits for a human to approve or reject before continuing. Essential for production deployments and sensitive operations.

PropertyTypeDescription
instructions*stringMessage shown to the approver explaining what they're approving.
timeoutnumberAuto-fail if no response after N seconds.
Behavior
text
1. Node enters "running" state
2. Emits "approval-requested" event: { runId, nodeId, name }
3. UI shows approval dialog with the node instructions
4. Blocks until respond_to_approval(approved: bool) is called
5. If approved → status "success", approval_state "approved"
6. If rejected → status "failed", approval_state "rejected"
7. If timeout → status "failed" (no approval received)

Resume behavior

When resuming a failed pipeline, approval gates that were previously approved are automatically re-approved — you won't be asked again for steps that already passed.

Sub-pipeline

References and executes another saved pipeline. Enables composable, reusable workflow modules.

PropertyTypeDescription
pipeline_ref*stringName of the pipeline to execute (matches filename without .pipeline.json).
instructionsstringOptional description.
Behavior
text
1. Loads {project}/.claude/pipelines/{pipeline_ref}.pipeline.json
2. Executes the full pipeline recursively (run_pipeline_loop)
3. Circular references are detected and blocked:
   - Ancestor pipeline names are tracked through the chain
   - If pipeline_ref appears in ancestors → error
4. Cost is aggregated from all nodes in the sub-pipeline
5. Sub-pipeline success/failure propagates to parent
Example
json
{
  "id": "node-deploy",
  "name": "Deploy to Staging",
  "type": "sub-pipeline",
  "instructions": "Execute the staging deployment pipeline",
  "pipeline_ref": "deploy-staging",
  "inputs": [],
  "outputs": [],
  "position": { "x": 250, "y": 300 }
}

Validation

Sub-pipeline nodes must have pipeline_ref set. The referenced pipeline must exist at execution time. Circular references (A calls B which calls A) are caught and result in a validation error.

Comment

A non-executing annotation node for documenting pipeline sections, leaving notes for teammates, and organizing complex workflows visually. Comment nodes are completely ignored during execution.

PropertyTypeDescription
instructions*stringThe comment text displayed on the canvas.
Example
json
{
  "id": "node-comment-1",
  "name": "Deployment Notes",
  "type": "comment",
  "instructions": "This section handles the staging deployment. Requires VPN access and valid AWS credentials.",
  "inputs": [],
  "outputs": [],
  "position": { "x": 50, "y": 600 }
}

Info

Comment nodes have no edges, no execution logic, and no cost. They exist purely for documentation on the canvas. Use them to annotate complex pipeline sections or leave notes for your team.

Common Properties

All node types share these properties:

Retry Policy

{
  "retry": {
    "max": 3,    // Maximum number of attempts (1 = no retries)
    "delay": 10  // Seconds to wait between retries
  }
}

Each attempt is tracked in the database with its own attempt number, exit code, and log output.

Timeout

{
  "timeout": 300  // Kill process after 300 seconds (5 minutes)
}

When a timeout fires, the process receives SIGTERM. If it doesn't exit within a grace period, SIGKILL is sent.

Execution Status

StatusMeaning
pendingNot yet reached in execution order
runningCurrently executing
successCompleted with exit code 0 (or approved)
failedNon-zero exit, timeout, rejection, or error
skippedConditional edge not satisfied
cancelledPipeline was cancelled by user