CI/CD Pipeline – A Complete Agentic Net Example with Error Handling

CI/CD Pipeline – A Complete Agentic Net Example with Error Handling

This guide demonstrates a real-world CI/CD Pipeline built as an Agentic Net. Unlike the simple linear showcase, this example includes error paths, conditional routing, and multiple postsets – showing how production agentic processes handle success, failure, and decision branches.

You’ll see all six transition types working together with proper error handling:

  • PASS – Conditional routing based on branch type
  • MAP – Transform commit data into build payload
  • HTTP – Call CI service with success/failure paths
  • LLM – AI quality analysis with pass/fail routing
  • AGENT – Intelligent deployment decisions with review option
  • COMMAND – Execute deployment with success/failure handling

Pipeline Overview

A code commit flows through validation, building, testing, quality analysis, deployment decision, and execution – with proper error handling at each stage:

Place Structure

Main Flow (y=200)

Place X Purpose Initial Tokens
p-commit 50 Incoming code commits 1 (sample commit)
p-feature-build 250 Feature branch commits (y=150) 0
p-main-build 250 Main branch commits (y=250) 0
p-build-payload 400 Normalized build configuration 0
p-test-results 600 Successful test results 0
p-quality-report 800 Quality analysis passed 0
p-deploy-decision 1000 Approved for deployment 0
p-deployed 1200 Successfully deployed 0

Error Paths (y=350)

Place X Purpose Triggered By
p-build-failed 550 Build or test failures t-build-test (error)
p-quality-failed 800 Quality issues detected t-analyze (quality fail)
p-manual-review 1000 Needs human review t-decide (uncertain)
p-deploy-failed 1200 Deployment failed t-deploy (error)

Transition Details

1. t-route (PASS) – Branch-Based Routing

Routes commits to different build paths based on branch type. Demonstrates conditional emit with multiple postsets.

{
  "id": "t-route",
  "kind": "pass",
  "mode": "SINGLE",

  "presets": {
    "commit": {
      "placeId": "p-commit",
      "host": "default@localhost:8080",
      "arcql": "FROM $ LIMIT 1",
      "take": "FIRST",
      "consume": true
    }
  },

  "postsets": {
    "feature": { "placeId": "p-feature-build", "host": "default@localhost:8080" },
    "main": { "placeId": "p-main-build", "host": "default@localhost:8080" }
  },

  "action": { "type": "pass" },

  "emit": [
    { "to": "feature", "from": "@input.data", "when": "branch == 'feature'" },
    { "to": "main", "from": "@input.data", "when": "branch == 'main'" }
  ]
}

Key Pattern: Multiple postsets with when conditions route tokens to different places based on data.

2. t-prepare (MAP) – Build Configuration

Transforms raw commit data into a structured build payload with computed fields.

{
  "id": "t-prepare",
  "kind": "map",
  "mode": "SINGLE",

  "presets": {
    "feature": {
      "placeId": "p-feature-build",
      "host": "default@localhost:8080",
      "arcql": "FROM $ LIMIT 1",
      "take": "FIRST",
      "consume": true
    },
    "main": {
      "placeId": "p-main-build",
      "host": "default@localhost:8080",
      "arcql": "FROM $ LIMIT 1",
      "take": "FIRST",
      "consume": true
    }
  },

  "postsets": {
    "payload": { "placeId": "p-build-payload", "host": "default@localhost:8080" }
  },

  "action": {
    "type": "map",
    "template": {
      "buildId": "BUILD-${input.data.commitId}",
      "commitId": "${input.data.commitId}",
      "branch": "${input.data.branch}",
      "author": "${input.data.author}",
      "message": "${input.data.message}",
      "files": "${input.data.files}",
      "buildConfig": {
        "priority": "${input.data.branch == 'main' ? 'high' : 'normal'}",
        "runTests": true,
        "coverage": true
      },
      "status": "pending",
      "createdAt": "${input.data.timestamp}"
    }
  },

  "emit": [
    { "to": "payload", "from": "@response", "when": "success" }
  ]
}

Key Pattern: Multiple presets (feature + main) converge into single output with enriched structure.

3. t-build-test (HTTP) – CI Service Call

Calls external CI service with success/error routing to different postsets.

{
  "id": "t-build-test",
  "kind": "task",
  "mode": "SINGLE",

  "presets": {
    "payload": {
      "placeId": "p-build-payload",
      "host": "default@localhost:8080",
      "arcql": "FROM $ LIMIT 1",
      "take": "FIRST",
      "consume": true
    }
  },

  "postsets": {
    "success": { "placeId": "p-test-results", "host": "default@localhost:8080" },
    "failed": { "placeId": "p-build-failed", "host": "default@localhost:8080" }
  },

  "action": {
    "type": "http",
    "method": "POST",
    "url": "https://ci-service.example.com/builds",
    "headers": {
      "Content-Type": "application/json",
      "Authorization": "Bearer ${env.CI_TOKEN}"
    },
    "body": {
      "buildId": "${payload.data.buildId}",
      "commitId": "${payload.data.commitId}",
      "branch": "${payload.data.branch}",
      "config": "${payload.data.buildConfig}"
    },
    "timeout": 300000,
    "retry": {
      "maxAttempts": 3,
      "backoffMs": 5000
    }
  },

  "emit": [
    { "to": "success", "from": "@response", "when": "success" },
    { "to": "failed", "from": "@response", "when": "error" }
  ]
}

Key Pattern: when: "success" and when: "error" route HTTP results to appropriate places.

4. t-analyze (LLM) – AI Quality Analysis

Uses AI to analyze test results and code quality, routing to pass/fail based on analysis.

{
  "id": "t-analyze",
  "kind": "task",
  "mode": "SINGLE",

  "presets": {
    "results": {
      "placeId": "p-test-results",
      "host": "default@localhost:8080",
      "arcql": "FROM $ LIMIT 1",
      "take": "FIRST",
      "consume": true
    }
  },

  "postsets": {
    "passed": { "placeId": "p-quality-report", "host": "default@localhost:8080" },
    "failed": { "placeId": "p-quality-failed", "host": "default@localhost:8080" }
  },

  "action": {
    "type": "llm",
    "nl": "Analyze these test results and determine code quality. Return JSON with: quality ('pass' or 'fail'), score (0-100), issues (array of problems), and summary.",
    "system": "You are a senior code quality analyst. Be strict about test coverage (>80%) and code quality. Return valid JSON only."
  },

  "emit": [
    { "to": "passed", "from": "@response", "when": "quality == 'pass'" },
    { "to": "failed", "from": "@response", "when": "quality == 'fail'" }
  ]
}

Key Pattern: LLM output field (quality) determines routing via when condition.

5. t-decide (AGENT) – Deployment Decision

Autonomous AI agent makes deployment decisions with three-way routing: approve, review, or reject.

{
  "id": "t-decide",
  "kind": "agent",
  "mode": "SINGLE",

  "presets": {
    "report": {
      "placeId": "p-quality-report",
      "host": "default@localhost:8080",
      "arcql": "FROM $ LIMIT 1",
      "take": "FIRST",
      "consume": true
    }
  },

  "postsets": {
    "approved": { "placeId": "p-deploy-decision", "host": "default@localhost:8080" },
    "review": { "placeId": "p-manual-review", "host": "default@localhost:8080" }
  },

  "action": {
    "type": "agent",
    "nl": "Review this quality report and decide: 1) 'approved' if quality score >= 85 and no critical issues, 2) 'review' if score 70-84 or minor concerns, 3) 'rejected' if score < 70. Create a deployment decision token with: decision, reason, riskLevel, and recommendations.",
    "maxIterations": 5
  },

  "emit": [
    { "to": "approved", "from": "@response", "when": "decision == 'approved'" },
    { "to": "review", "from": "@response", "when": "decision == 'review'" }
  ]
}

Key Pattern: Agent’s decision field drives conditional routing to different paths.

6. t-deploy (COMMAND) – Execute Deployment

Executes deployment scripts with success/failure error handling.

{
  "id": "t-deploy",
  "kind": "command",
  "mode": "SINGLE",

  "presets": {
    "decision": {
      "placeId": "p-deploy-decision",
      "host": "default@localhost:8080",
      "arcql": "FROM $ LIMIT 1",
      "take": "FIRST",
      "consume": true
    }
  },

  "postsets": {
    "success": { "placeId": "p-deployed", "host": "default@localhost:8080" },
    "failed": { "placeId": "p-deploy-failed", "host": "default@localhost:8080" }
  },

  "action": {
    "type": "command",
    "inputPlace": "decision",
    "dispatch": [{ "executor": "bash", "channel": "default" }],
    "await": "ALL",
    "timeoutMs": 600000
  },

  "emit": [
    { "to": "success", "from": "@result", "when": "success" },
    { "to": "failed", "from": "@result", "when": "error" }
  ]
}

Key Pattern: Command execution results route to success or failure places.

Sample Token Flow

Initial Commit Token

{
  "commitId": "abc123def",
  "branch": "main",
  "author": "developer@company.com",
  "message": "feat: add user authentication",
  "files": ["src/auth.ts", "src/login.ts", "tests/auth.test.ts"],
  "timestamp": "2026-01-06T10:30:00Z"
}

After MAP (Build Payload)

{
  "buildId": "BUILD-abc123def",
  "commitId": "abc123def",
  "branch": "main",
  "author": "developer@company.com",
  "message": "feat: add user authentication",
  "files": ["src/auth.ts", "src/login.ts", "tests/auth.test.ts"],
  "buildConfig": {
    "priority": "high",
    "runTests": true,
    "coverage": true
  },
  "status": "pending",
  "createdAt": "2026-01-06T10:30:00Z"
}

After LLM Analysis

{
  "quality": "pass",
  "score": 92,
  "issues": [],
  "summary": "All tests passing with 94% coverage. Code follows best practices.",
  "testResults": {
    "passed": 47,
    "failed": 0,
    "skipped": 2
  },
  "coverage": 94.2
}

After AGENT Decision

{
  "decision": "approved",
  "reason": "Quality score 92% exceeds threshold. No critical issues detected.",
  "riskLevel": "low",
  "recommendations": [
    "Consider adding integration tests for auth flow"
  ],
  "approvedAt": "2026-01-06T10:35:00Z"
}

Error Handling Patterns

Pattern 1: HTTP Success/Error Split

"emit": [
  { "to": "success-place", "from": "@response", "when": "success" },
  { "to": "error-place", "from": "@response", "when": "error" }
]

Pattern 2: Field-Based Routing

"emit": [
  { "to": "high-priority", "from": "@response", "when": "priority == 'high'" },
  { "to": "normal-priority", "from": "@response", "when": "priority == 'normal'" },
  { "to": "low-priority", "from": "@response", "when": "priority == 'low'" }
]

Pattern 3: Threshold-Based Routing

"emit": [
  { "to": "approved", "from": "@response", "when": "score >= 85" },
  { "to": "review", "from": "@response", "when": "score >= 70 && score < 85" },
  { "to": "rejected", "from": "@response", "when": "score < 70" }
]

Complete PNML

{
  "net": {
    "places": {
      "p-commit": { "id": "p-commit", "x": 50, "y": 200, "tokens": 1, "label": "Commit" },
      "p-feature-build": { "id": "p-feature-build", "x": 250, "y": 150, "tokens": 0, "label": "Feature" },
      "p-main-build": { "id": "p-main-build", "x": 250, "y": 250, "tokens": 0, "label": "Main" },
      "p-build-payload": { "id": "p-build-payload", "x": 400, "y": 200, "tokens": 0, "label": "Payload" },
      "p-test-results": { "id": "p-test-results", "x": 600, "y": 200, "tokens": 0, "label": "Tests" },
      "p-quality-report": { "id": "p-quality-report", "x": 800, "y": 200, "tokens": 0, "label": "Quality" },
      "p-deploy-decision": { "id": "p-deploy-decision", "x": 1000, "y": 200, "tokens": 0, "label": "Decision" },
      "p-deployed": { "id": "p-deployed", "x": 1200, "y": 200, "tokens": 0, "label": "Deployed" },
      "p-build-failed": { "id": "p-build-failed", "x": 550, "y": 350, "tokens": 0, "label": "Build Failed" },
      "p-quality-failed": { "id": "p-quality-failed", "x": 800, "y": 350, "tokens": 0, "label": "Quality Failed" },
      "p-manual-review": { "id": "p-manual-review", "x": 1000, "y": 350, "tokens": 0, "label": "Manual Review" },
      "p-deploy-failed": { "id": "p-deploy-failed", "x": 1200, "y": 350, "tokens": 0, "label": "Deploy Failed" }
    },
    "transitions": {
      "t-route": { "id": "t-route", "x": 150, "y": 200, "label": "PASS" },
      "t-prepare": { "id": "t-prepare", "x": 325, "y": 200, "label": "MAP" },
      "t-build-test": { "id": "t-build-test", "x": 500, "y": 200, "label": "HTTP" },
      "t-analyze": { "id": "t-analyze", "x": 700, "y": 200, "label": "LLM" },
      "t-decide": { "id": "t-decide", "x": 900, "y": 200, "label": "AGENT" },
      "t-deploy": { "id": "t-deploy", "x": 1100, "y": 200, "label": "COMMAND" }
    },
    "arcs": {
      "a1": { "id": "a1", "source": "p-commit", "target": "t-route" },
      "a2": { "id": "a2", "source": "t-route", "target": "p-feature-build" },
      "a3": { "id": "a3", "source": "t-route", "target": "p-main-build" },
      "a4": { "id": "a4", "source": "p-feature-build", "target": "t-prepare" },
      "a5": { "id": "a5", "source": "p-main-build", "target": "t-prepare" },
      "a6": { "id": "a6", "source": "t-prepare", "target": "p-build-payload" },
      "a7": { "id": "a7", "source": "p-build-payload", "target": "t-build-test" },
      "a8": { "id": "a8", "source": "t-build-test", "target": "p-test-results" },
      "a9": { "id": "a9", "source": "t-build-test", "target": "p-build-failed" },
      "a10": { "id": "a10", "source": "p-test-results", "target": "t-analyze" },
      "a11": { "id": "a11", "source": "t-analyze", "target": "p-quality-report" },
      "a12": { "id": "a12", "source": "t-analyze", "target": "p-quality-failed" },
      "a13": { "id": "a13", "source": "p-quality-report", "target": "t-decide" },
      "a14": { "id": "a14", "source": "t-decide", "target": "p-deploy-decision" },
      "a15": { "id": "a15", "source": "t-decide", "target": "p-manual-review" },
      "a16": { "id": "a16", "source": "p-deploy-decision", "target": "t-deploy" },
      "a17": { "id": "a17", "source": "t-deploy", "target": "p-deployed" },
      "a18": { "id": "a18", "source": "t-deploy", "target": "p-deploy-failed" }
    }
  }
}

Key Takeaways

  • Multiple postsets enable branching agentic processes with error paths
  • Conditional emit (when) routes tokens based on data values
  • success/error built-in conditions handle HTTP and command failures
  • Field-based routing lets AI outputs drive agentic process decisions
  • Error places (y=350) create clear visual separation from success path
  • All 6 transitions work together in a realistic production agentic process

This CI/CD Pipeline demonstrates how Agentic Nets handle real-world complexity with proper error handling, conditional routing, and intelligent decision-making.

Related Guides

Leave a Reply

Your email address will not be published. Required fields are marked *