Pipelines
Orchestrate multi-step agent workflows using directed acyclic graphs (DAGs).
Pipelines define the execution flow for agent work in Nenjo. Each pipeline is a directed acyclic graph (DAG) of steps connected by edges, where each step performs a unit of work -- running an agent, evaluating a gate, executing a script, or coordinating a council.
Core concepts
A pipeline consists of three primitives:
- Steps (nodes) -- Units of work such as agent tasks, quality gates, lambda scripts, cron loops, councils, or terminal states.
- Edges -- Directed connections between steps that define execution order.
- Conditions -- Rules on edges that determine which path to follow based on the previous step's result (
on_pass,on_fail, etc.).
Every pipeline has exactly one entry point (a step with no incoming edges) and at least one terminal step where execution ends.
Data model
Pipeline
| Field | Type | Description |
|---|---|---|
id | UUID | Unique identifier |
name | string | Human-readable name |
description | string? | Optional description |
trigger | string | When to execute: ticket.ready or cron |
is_active | boolean | Whether the pipeline can be executed |
is_default | boolean | Whether this is the user's default pipeline |
max_retries | integer | Maximum retry attempts on failure (default: 3) |
metadata | JSON | Arbitrary metadata (e.g., schedule for cron, entry_step_ids for editor) |
created_by | UUID | Owner user ID |
Pipeline step
| Field | Type | Description |
|---|---|---|
id | UUID | Unique identifier |
pipeline_id | UUID | Parent pipeline |
name | string | Display name |
step_type | string | One of: agent, council, gate, cron, lambda, terminal |
agent_id | UUID? | Agent to run (for agent steps) |
council_id | UUID? | Council to run (for council steps) |
role_id | UUID? | Role to use (resolves to an agent, for agent/cron steps) |
lambda_id | UUID? | Lambda script to run (for lambda/cron steps) |
config | JSON | Step-specific configuration |
position_x | float | X coordinate in the visual editor |
position_y | float | Y coordinate in the visual editor |
order_index | integer | Ordering hint for entry-point resolution |
Pipeline edge
| Field | Type | Description |
|---|---|---|
id | UUID | Unique identifier |
pipeline_id | UUID | Parent pipeline |
source_step_id | UUID | Step this edge originates from |
target_step_id | UUID | Step this edge points to |
condition | string | When to follow: always, on_pass, on_fail, on_review_pass, on_review_fail |
metadata | JSON | Optional edge metadata |
Trigger types
Pipelines are activated by a trigger:
ticket.ready-- Executes when a ticket transitions to thereadystate. This is the default trigger for task-driven pipelines.cron-- Executes on a recurring schedule. See Cron and scheduling for details.
Execution lifecycle
- The pipeline is loaded with its steps and edges.
- The entry step is identified (the step with no incoming edges, or via
metadata.entry_step_ids). - The entry step executes and produces a
StepResultwith apassedboolean. - The executor evaluates outgoing edges from the current step. The first edge whose condition is satisfied by the step result is followed.
- The next step executes, and the process repeats.
- Execution ends when a terminal step is reached or no matching outgoing edge is found.
The executor is bounded to steps.len() * 100 iterations to prevent infinite loops on misconfigured pipelines.
Project assignment
Pipelines are assigned to projects. When a ticket in a project becomes ready, the project's assigned pipeline (or the user's default pipeline) is executed. One pipeline can be marked as the default using the set-default endpoint.
API
All pipeline routes are under /api/v1/pipelines and require authentication.
Pipeline CRUD
# List all pipelines
curl -H "Authorization: Bearer $TOKEN" \
https://your-instance.com/api/v1/pipelines
# Create a pipeline
curl -X POST \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "Code Review Pipeline",
"trigger": "ticket.ready",
"max_retries": 3
}' \
https://your-instance.com/api/v1/pipelines
# Get pipeline with steps and edges
curl -H "Authorization: Bearer $TOKEN" \
https://your-instance.com/api/v1/pipelines/$PIPELINE_ID
# Update a pipeline
curl -X PATCH \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"is_active": false}' \
https://your-instance.com/api/v1/pipelines/$PIPELINE_ID
# Delete a pipeline
curl -X DELETE \
-H "Authorization: Bearer $TOKEN" \
https://your-instance.com/api/v1/pipelines/$PIPELINE_ID
# Set as default pipeline
curl -X POST \
-H "Authorization: Bearer $TOKEN" \
https://your-instance.com/api/v1/pipelines/$PIPELINE_ID/set-default
# Manually trigger a cron pipeline
curl -X POST \
-H "Authorization: Bearer $TOKEN" \
https://your-instance.com/api/v1/pipelines/$PIPELINE_ID/triggerSteps CRUD
# Add a step
curl -X POST \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "Developer",
"step_type": "agent",
"role_id": "ROLE_UUID"
}' \
https://your-instance.com/api/v1/pipelines/$PIPELINE_ID/steps
# Update a step
curl -X PATCH \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"name": "Senior Developer"}' \
https://your-instance.com/api/v1/pipelines/$PIPELINE_ID/steps/$STEP_ID
# Delete a step
curl -X DELETE \
-H "Authorization: Bearer $TOKEN" \
https://your-instance.com/api/v1/pipelines/$PIPELINE_ID/steps/$STEP_IDEdges CRUD
# Add an edge
curl -X POST \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"source_step_id": "STEP_A_UUID",
"target_step_id": "STEP_B_UUID",
"condition": "on_pass"
}' \
https://your-instance.com/api/v1/pipelines/$PIPELINE_ID/edges
# Delete an edge
curl -X DELETE \
-H "Authorization: Bearer $TOKEN" \
https://your-instance.com/api/v1/pipelines/$PIPELINE_ID/edges/$EDGE_IDNext steps
- Step types -- Detailed reference for each step type
- Edges and conditions -- How edge conditions control flow
- DAG validation -- Rules your pipeline must follow
- Executions -- Runtime context and monitoring