DEV Community

Cover image for I Let an AI Agent Fix My Broken CI/CD Pipeline and Here's What Happened
Vishvesh Patel for DevOpsLesson

Posted on

I Let an AI Agent Fix My Broken CI/CD Pipeline and Here's What Happened

A hands-on guide to Agentic AI in CI/CD. Build a self-healing pipeline that triages failures, opens PRs, and remediates issues with real GitHub Actions code you can copy today.

In this post I'll show you what "agentic" AI actually means for DevOps, then walk you through building a self-healing GitHub Actions pipeline that automatically triages a failed build and opens a fix PR. All code included. 🚀

The 2 AM Problem Every DevOps Engineer Knows

You've been there. A deploy fails at 2 AM. PagerDuty screams. You stumble to your laptop, open the pipeline logs, scroll through 4,000 lines of noise, and discover... a flaky test and a bumped dependency broke the build.

Twenty minutes of your life, gone. For a fix that was, honestly, kind of obvious.

Now imagine the pipeline had already diagnosed it, opened a pull request with the fix, and pinged you with a one-line summary before the pager even went off.

That's agentic DevOps, and it's the single biggest shift in CI/CD this year.

What "Agentic" Actually Means (Without the Hype)

Let's cut through the marketing. There are three levels of AI in a pipeline:

Level What it does Example
Assistive Suggests code as you type Copilot autocomplete
Generative Produces a whole artifact on request "Write me a Dockerfile"
Agentic Perceives → decides → acts in a loop Detects a failure, writes a fix, opens a PR, re-runs the job

An agentic system has:

  1. Perception — it reads logs, test output, and diffs.
  2. Reasoning — an LLM decides why something failed.
  3. Tools — it can actually do things: open PRs, comment, re-run jobs, roll back.
  4. A feedback loop — it observes the result of its action and tries again if needed.

flowchart

Let's Build One 🛠️

We'll build a minimal but real self-healing pipeline in GitHub Actions. When tests fail, an AI agent will:

  1. Grab the failure logs
  2. Ask an LLM to diagnose the root cause
  3. Post a diagnosis as a PR comment (and optionally open a fix PR)

You only need a GitHub repo and an API key (OpenAI, Anthropic, or your Copilot/Azure endpoint).

flowchart LR
    PR[Pull Request] --> T{test job}
    T -->|pass| M[✅ ready to merge]
    T -->|fail| G[diagnose job<br/>if: failure]
    G --> L[collect logs]
    L --> AI[🤖 LLM diagnosis]
    AI --> C[💬 comment on PR]
    AI -.optional.-> FIX[open fix PR]
Enter fullscreen mode Exit fullscreen mode

Step 1: The Baseline Pipeline

Here's a normal test workflow, nothing magic yet.

# .github/workflows/ci.yml
name: CI

on:
  pull_request:

jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: 20
      - run: npm ci
      - run: npm test
Enter fullscreen mode Exit fullscreen mode

Step 2: Capture the Failure

The trick: only trigger the agent when the test job fails. We add a second job that depends on the first and runs on failure.

  diagnose:
    needs: test
    if: failure()          # 👈 only runs when `test` failed
    runs-on: ubuntu-latest
    permissions:
      pull-requests: write  # so the agent can comment
      contents: read
    steps:
      - uses: actions/checkout@v4

      - name: Collect failure logs
        run: |
          npm ci
          # capture test output (stdout + stderr) into a file
          npm test > test-output.log 2>&1 || true
Enter fullscreen mode Exit fullscreen mode

Step 3: The Agent, Diagnose With an LLM

Here's the heart of it. A small script sends the logs to an LLM and asks for a structured diagnosis.

// scripts/diagnose.js
import fs from "node:fs";
import OpenAI from "openai";

const client = new OpenAI({ apiKey: process.env.OPENAI_API_KEY });

const logs = fs.readFileSync("test-output.log", "utf8").slice(-6000); // last 6k chars

const prompt = `
You are a senior DevOps engineer. A CI pipeline just failed.
Analyze the logs below and respond in this exact markdown format:

**Root cause:** <one sentence>
**Confidence:** <low | medium | high>
**Suggested fix:** <concrete, actionable steps>
**Is this flaky?:** <yes | no>

--- LOGS ---
${logs}
`;

const res = await client.chat.completions.create({
  model: "gpt-4o-mini",
  messages: [{ role: "user", content: prompt }],
  temperature: 0.1,
});

const diagnosis = res.choices[0].message.content;
fs.writeFileSync("diagnosis.md", diagnosis);
console.log(diagnosis);
Enter fullscreen mode Exit fullscreen mode

Step 4: Let the Agent Act

Now we wire the diagnosis back into the PR as a comment. This is the "agentic" part, it takes an action in your workflow.

      - name: Diagnose with AI
        env:
          OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
        run: node scripts/diagnose.js

      - name: Post diagnosis to PR
        uses: actions/github-script@v7
        with:
          script: |
            const fs = require('fs');
            const body = fs.readFileSync('diagnosis.md', 'utf8');
            await github.rest.issues.createComment({
              owner: context.repo.owner,
              repo: context.repo.repo,
              issue_number: context.issue.number,
              body: `## 🤖 AI Pipeline Diagnosis\n\n${body}`
            });
Enter fullscreen mode Exit fullscreen mode

The Result

Push a PR that breaks a test, and within ~30 seconds you get a comment like:

🤖 AI Pipeline Diagnosis

Root cause: formatDate() returns undefined because the date-fns upgrade to v3 changed the import path.
Confidence: high
Suggested fix: Change import { format } from 'date-fns' to the named subpath import, or pin date-fns@2.
Is this flaky?: no

No log-scrolling. No 2 AM archaeology. Just a diagnosis waiting for you. ✨

Leveling Up: From Diagnosis to Auto-Fix

The comment version is safe and a great starting point. When you trust it, you can go further:

  • Open a fix PR automatically :- have the agent generate a patch and use peter-evans/create-pull-request to open it.
  • Auto-rerun flaky tests :- if the agent says flaky: yes, re-trigger the job instead of paging a human.
  • Gate on confidence :- only auto-act on high confidence; escalate the rest.
      - name: Auto-retry flaky failures
        if: contains(fromJSON(steps.diag.outputs.result).flaky, 'yes')
        run: gh workflow run ci.yml --ref ${{ github.head_ref }}
        env:
          GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
Enter fullscreen mode Exit fullscreen mode

The Guardrails You Must Not Skip 🛡️

Agentic pipelines are powerful, which means they're also a new attack surface. Before you ship this:

  • Least privilege :- give the agent only the token scopes it needs (pull-requests: write, not admin).
  • Human-in-the-loop for writes :- auto-comment freely, but require review before auto-merge.
  • Never feed secrets to the LLM :- scrub logs of tokens and env vars before sending.
  • Cap the blast radius :- rate-limit agent actions and add a kill switch (a repo variable like AGENT_ENABLED).
  • Log everything the agent does :- you need an audit trail when it makes a bad call.

Treat the agent like a junior engineer with commit access: helpful, fast, and occasionally confidently wrong.

Where This Is Going

By the end of 2026, "the pipeline fixes itself" won't be a novelty, it'll be table stakes. We're heading toward pipelines that:

  • Auto-remediate infra drift (GitOps + AI)
  • Triage incidents before humans wake up (AIOps)
  • Tune their own resource usage and cost (FinOps agents)

The DevOps engineers who thrive won't be the ones fighting AI for their jobs, they'll be the ones designing the guardrails that let these agents run safely.

Your Turn 👇

Try the diagnose-only version this week, it's low-risk and genuinely useful. Then tell me in the comments:

  • What's the most annoying pipeline failure you'd hand off to an agent?
  • Would you trust an AI to open PRs against your main branch? Why or why not?

If this helped, follow the DevOpsLesson and visit https://devopslesson.com/

Happy shipping. 🚢

Top comments (0)