Pipelines
Pipelines enable durable, multi-step workflow orchestration. Each pipeline is a DAG (Directed Acyclic Graph) of stages that execute commands, await human approvals, or evaluate gates.
Create Pipeline
curl -X POST https://api.caged.dev/v1/pipelines \
-H "Authorization: Bearer caged_sk_..." \
-H "Content-Type: application/json" \
-d '{
"name": "deploy-to-prod",
"description": "Build, test, and deploy to production",
"stages": [
{
"name": "build",
"type": "command",
"command": "npm run build",
"timeout": "5m"
},
{
"name": "test",
"type": "command",
"command": "npm test",
"depends_on": ["build"]
},
{
"name": "approve-deploy",
"type": "await_approval",
"config": {
"message": "Approve deployment to production?",
"channels": ["slack", "dashboard"],
"sla_timeout": "30m"
},
"depends_on": ["test"]
},
{
"name": "deploy",
"type": "command",
"command": "npm run deploy",
"depends_on": ["approve-deploy"]
}
],
"defaults": {
"template": "node-20",
"on_failure": "stop",
"retry": {
"max_attempts": 2,
"backoff": "5s"
}
}
}'
Response 201 Created
{
"id": "pipe-a1b2c3d4",
"account_id": "acc-x1y2z3",
"name": "deploy-to-prod",
"description": "Build, test, and deploy to production",
"status": "active",
"version": 1,
"stages": [...],
"defaults": {...},
"created_at": "2026-08-02T10:00:00Z",
"updated_at": "2026-08-02T10:00:00Z"
}
List Pipelines
curl https://api.caged.dev/v1/pipelines \
-H "Authorization: Bearer caged_sk_..."
Response 200 OK
[
{
"id": "pipe-a1b2c3d4",
"name": "deploy-to-prod",
"status": "active",
"version": 1,
"created_at": "2026-08-02T10:00:00Z"
}
]
Get Pipeline
curl https://api.caged.dev/v1/pipelines/pipe-a1b2c3d4 \
-H "Authorization: Bearer caged_sk_..."
Returns the full pipeline definition.
Delete Pipeline
Archives a pipeline (soft delete). Existing runs are preserved.
curl -X DELETE https://api.caged.dev/v1/pipelines/pipe-a1b2c3d4 \
-H "Authorization: Bearer caged_sk_..."
Response 204 No Content
Start Run
Trigger a new execution of a pipeline.
curl -X POST https://api.caged.dev/v1/pipelines/pipe-a1b2c3d4/runs \
-H "Authorization: Bearer caged_sk_..." \
-H "Content-Type: application/json" \
-d '{
"trigger": "api",
"env": {
"NODE_ENV": "production",
"DEPLOY_TARGET": "us-east-1"
},
"repo": "https://github.com/myorg/myapp",
"branch": "main"
}'
Response 201 Created
{
"id": "run-e5f6g7h8",
"pipeline_id": "pipe-a1b2c3d4",
"pipeline_name": "deploy-to-prod",
"status": "pending",
"trigger": "api",
"input": {
"env": {"NODE_ENV": "production", "DEPLOY_TARGET": "us-east-1"},
"repo": "https://github.com/myorg/myapp",
"branch": "main"
},
"created_at": "2026-08-02T10:05:00Z"
}
List Runs
curl https://api.caged.dev/v1/pipelines/pipe-a1b2c3d4/runs \
-H "Authorization: Bearer caged_sk_..."
Query params: limit (default 20), offset (default 0).
Response 200 OK
[
{
"id": "run-e5f6g7h8",
"pipeline_id": "pipe-a1b2c3d4",
"pipeline_name": "deploy-to-prod",
"status": "running",
"trigger": "api",
"started_at": "2026-08-02T10:05:00Z",
"duration_ms": 45000
}
]
Get Run
curl https://api.caged.dev/v1/pipelines/pipe-a1b2c3d4/runs/run-e5f6g7h8 \
-H "Authorization: Bearer caged_sk_..."
Returns full run details including all stage statuses.
Cancel Run
curl -X POST https://api.caged.dev/v1/pipelines/pipe-a1b2c3d4/runs/run-e5f6g7h8/cancel \
-H "Authorization: Bearer caged_sk_..."
Response 204 No Content
Run State
Pipeline runs include a key/value state store for sharing data between stages. State is scoped to the run — no cross-pipeline or cross-run leakage.
List Run State
Retrieve all state entries for a run.
curl https://api.caged.dev/v1/pipelines/pipe-a1b2c3d4/runs/run-e5f6g7h8/state \
-H "Authorization: Bearer caged_sk_..."
Response 200 OK
[
{
"key": "build.artifact",
"value": "s3://caged-artifacts/run-e5f6g7h8/app.zip",
"type": "string",
"mime_type": "",
"size_bytes": 52,
"created_by": "build",
"created_at": "2026-08-02T10:06:00Z",
"expires_at": "2026-08-09T10:06:00Z"
},
{
"key": "analysis_results",
"value": "{\"files\": [\"src/main.ts\"], \"score\": 85}",
"type": "json",
"mime_type": "application/json",
"size_bytes": 42,
"created_by": "analyze",
"created_at": "2026-08-02T10:05:30Z",
"expires_at": "2026-08-09T10:05:30Z"
}
]
Get State Entry
Retrieve a single state entry by key.
curl https://api.caged.dev/v1/pipelines/pipe-a1b2c3d4/runs/run-e5f6g7h8/state/analysis_results \
-H "Authorization: Bearer caged_sk_..."
Response 200 OK
{
"key": "analysis_results",
"value": "{\"files\": [\"src/main.ts\"], \"score\": 85}",
"type": "json",
"mime_type": "application/json",
"size_bytes": 42,
"created_by": "analyze",
"created_at": "2026-08-02T10:05:30Z",
"expires_at": "2026-08-09T10:05:30Z"
}
Response 404 Not Found if key doesn't exist.
Set State Entry
Create or update a state entry.
curl -X PUT https://api.caged.dev/v1/pipelines/pipe-a1b2c3d4/runs/run-e5f6g7h8/state/my_key \
-H "Authorization: Bearer caged_sk_..." \
-H "Content-Type: application/json" \
-d '{
"value": {"status": "complete", "items": 42},
"type": "json",
"mime_type": "application/json",
"created_by": "api",
"ttl_seconds": 86400
}'
| Field | Type | Required | Description |
|---|---|---|---|
value |
any | Yes | The value to store (string or JSON object) |
type |
string | No | string, json, file, patch, artifact (default: string) |
mime_type |
string | No | MIME type for binary/file types |
created_by |
string | No | Identifier for the creator (stage name, api, etc.) |
ttl_seconds |
integer | No | Time-to-live in seconds (default: 604800 = 7 days, max: 2592000 = 30 days) |
Response 200 OK
{
"key": "my_key",
"value": "{\"status\": \"complete\", \"items\": 42}",
"type": "json",
"mime_type": "application/json",
"size_bytes": 35,
"created_by": "api",
"created_at": "2026-08-02T10:10:00Z",
"expires_at": "2026-08-03T10:10:00Z"
}
Validation Errors 400 Bad Request:
- Key exceeds 256 characters
- Value exceeds 1 MB
- Run exceeds 100 state entries
- Run exceeds 10 MB total state size
- TTL exceeds 30 days
Delete State Entry
Remove a state entry.
curl -X DELETE https://api.caged.dev/v1/pipelines/pipe-a1b2c3d4/runs/run-e5f6g7h8/state/temp_data \
-H "Authorization: Bearer caged_sk_..."
Response 204 No Content
State Entry Fields
| Field | Type | Description |
|---|---|---|
key |
string | Unique key within the run (max 256 chars) |
value |
string | Stored value (JSON-serialized for non-string types) |
type |
string | Value type: string, json, file, patch, artifact |
mime_type |
string | MIME type (for file/artifact types) |
size_bytes |
integer | Size of value in bytes |
created_by |
string | Stage name or identifier that created the entry |
created_at |
string | ISO 8601 creation timestamp |
expires_at |
string | ISO 8601 expiration timestamp |
State Limits
| Limit | Value |
|---|---|
| Max key length | 256 characters |
| Max value size | 1 MB |
| Max entries per run | 100 |
| Max total size per run | 10 MB |
| Default TTL | 7 days |
| Max TTL | 30 days |
Get Run Stages
curl https://api.caged.dev/v1/pipelines/pipe-a1b2c3d4/runs/run-e5f6g7h8/stages \
-H "Authorization: Bearer caged_sk_..."
Response 200 OK
[
{
"id": "stg-i9j0k1l2",
"name": "build",
"type": "command",
"status": "succeeded",
"attempt": 1,
"exit_code": 0,
"duration_ms": 12000,
"started_at": "2026-08-02T10:05:01Z",
"completed_at": "2026-08-02T10:05:13Z"
},
{
"id": "stg-m3n4o5p6",
"name": "test",
"type": "command",
"status": "running",
"attempt": 1,
"started_at": "2026-08-02T10:05:14Z"
}
]
Pipeline Fields
| Field | Type | Description |
|---|---|---|
id |
string | Unique pipeline ID |
account_id |
string | Owner account |
name |
string | Pipeline name (unique per account) |
description |
string | Human-readable description |
status |
string | active or archived |
version |
integer | Incremented on each update |
stages |
array | Stage definitions (see below) |
defaults |
object | Default settings for all stages |
Stage Definition
| Field | Type | Description |
|---|---|---|
name |
string | Unique stage name within pipeline |
type |
string | command, await_approval, gate, eval |
command |
string | Command to execute (for command type) |
template |
string | Sandbox template (default from pipeline defaults) |
timeout |
string | Execution timeout (e.g., "5m", "1h") |
retry |
object | Retry policy (max_attempts, backoff, max_backoff) |
on_failure |
string | stop (default) or continue |
depends_on |
array | Stage names this stage depends on |
condition |
object | Conditional execution rules |
env |
object | Environment variables for this stage |
config |
object | Type-specific configuration |
Stage Types
command
Runs a shell command in an isolated sandbox. The sandbox is created, command executed, and sandbox destroyed for each stage.
await_approval
Pauses the run and requests human approval via configured channels (dashboard, Slack, email). The run resumes when approved or is canceled if rejected.
{
"type": "await_approval",
"config": {
"message": "Deploy to production?",
"channels": ["slack", "dashboard"],
"sla_timeout": "30m",
"auto_decision": "reject"
}
}
gate
Evaluates a condition (trust score, cost threshold, custom expression). Passes or fails instantly.
{
"type": "gate",
"config": {
"trust_above": 80,
"cost_below": 5.00,
"fail_fast": true
}
}
Gate Config Fields:
| Field | Type | Description |
|---|---|---|
trust_above |
int | Minimum trust score (0-100) to pass |
cost_below |
float | Maximum cost in USD to pass |
expression |
string | Custom CEL expression (coming soon) |
state_key |
string | State key for dynamic evaluation |
fail_fast |
bool | Stop pipeline immediately on failure |
eval
Runs a Cage Eval scenario or suite and evaluates gate conditions. Supports regression detection against historical baselines.
{
"type": "eval",
"config": {
"scenario_name": "code-review",
"min_pass_rate": 0.9,
"max_cost_usd": 1.00,
"fail_on_regression": true,
"baseline_count": 5,
"regression_threshold": 0.1
}
}
Eval Config Fields:
| Field | Type | Description |
|---|---|---|
scenario_id |
UUID | ID of the scenario to run |
scenario_name |
string | Name of the scenario (alternative to ID) |
suite_id |
UUID | Run all scenarios in a suite |
suite_name |
string | Suite name (alternative to ID) |
min_pass_rate |
float | Minimum pass rate (0-1) to pass gate |
max_cost_usd |
float | Maximum allowed cost for the eval run |
fail_on_regression |
bool | Block if score regresses vs baseline |
baseline_count |
int | Number of previous runs for baseline (default: 5) |
regression_threshold |
float | Max allowed score drop (default: 0.1 = 10%) |
store_result_in_state |
bool | Save eval result to pipeline state |
result_state_key |
string | State key for result (default: eval_result) |
a2a
Delegates work to an external A2A-compatible agent. See A2A Protocol for details.
{
"type": "a2a",
"config": {
"agent_url": "https://agent.example.com",
"skill_id": "code-review",
"prompt": "Review the PR changes",
"max_cost_usd": 2.00
}
}
Gate Results
For eval and gate stages, the stage response includes a gate_result field with evaluation details:
{
"id": "stg-m3n4o5p6",
"name": "quality-check",
"type": "eval",
"status": "failed",
"gate_result": {
"passed": false,
"failed_checks": [
{
"type": "min_pass_rate",
"expected": "0.90",
"actual": "0.75",
"passed": false,
"message": "Pass rate 75.0% below required 90.0%"
},
{
"type": "regression",
"expected": ">= 85.0% (baseline)",
"actual": "75.0%",
"passed": false,
"message": "Score regressed 11.8% vs baseline (85.0% → 75.0%)"
}
],
"passed_checks": [
{
"type": "max_cost",
"expected": "< $1.0000",
"actual": "$0.4500",
"passed": true
}
],
"message": "Eval gate failed: 2 check(s) failed",
"evaluated_at": "2026-08-02T10:15:00Z",
"score": 0.75,
"total_cost": 0.45,
"baseline_score": 0.85,
"baseline_count": 5,
"score_delta": -0.10,
"is_regression": true,
"regression_pct": 11.8
}
}
Gate Check Types:
| Type | Description |
|---|---|
eval_status |
Eval run status (passed/failed/errored) |
min_pass_rate |
Minimum assertion pass rate |
max_cost |
Maximum cost threshold |
regression |
Score regression vs baseline |
trust |
Trust score threshold |
cost |
Accumulated cost threshold |
expression |
Custom expression evaluation |
Run Status
| Status | Description |
|---|---|
pending |
Created but not yet started |
running |
At least one stage is executing |
paused |
Waiting for human approval |
succeeded |
All stages completed successfully |
failed |
A stage failed (no recovery) |
canceled |
Manually canceled |
Stage Status
| Status | Description |
|---|---|
pending |
Not yet started |
waiting |
Waiting for dependencies |
running |
Currently executing |
paused_approval |
Waiting for human approval |
succeeded |
Completed successfully |
failed |
Failed after all retries |
skipped |
Skipped due to conditional |
canceled |
Run was canceled |