← All writing

AI Agents That Guard Your Deploy Pipeline

Deployments fail because of things that were already knowable — stale dependencies, wrong config, missed migrations. AI agents can run your readiness checks, interpret the results, and block a release before a human has to remember what to look for.


Most deployment failures I have debugged were not caused by broken code. They were caused by context that a human forgot to check.

A dependency that quietly stopped supporting the current Laravel version. A queue driver set to sync in a staging config that got copied to production. A migration committed two sprints ago and never run. The code passed every test. The pipeline was green. The failure happened because nobody asked the right questions before the deploy went out.

AI agents are good at asking the right questions — if you wire them into the right tools.

The gap between green CI and safe deploy

A typical CI pipeline runs tests, linting, and maybe static analysis. If those pass, the deploy proceeds. That is necessary but not sufficient.

Tests verify correctness. Does the code do the right thing? That is covered.

Readiness is a different question. Is the environment prepared for the code to do the right thing? That is usually not covered.

A test suite will not tell you that:

  • APP_DEBUG is still true
  • The mailer is set to log
  • A critical package has been abandoned by its author
  • A pending migration will cause a missing-table error

Most teams run readiness checks manually or not at all. The ones who automate them usually write shell scripts that check a few .env values and call it done. But readiness checks need judgment, not just pattern matching.

A sync queue driver is fine in a test environment and dangerous in production. An abandoned package is acceptable if you have forked it and unacceptable if you have not. A missing migration is a blocker for a feature deploy and irrelevant for a hotfix.

That judgment layer is where AI agents fit.

What an agent-guarded pipeline looks like

The idea is not to replace your CI with an AI. It is to add a stage after tests pass where an agent runs structured tools, interprets the combined results, and decides whether the deploy should proceed.

1. Tests        → phpunit / pest
2. Lint         → pint --test / phpstan
3. Build        → production build
4. Agent gate   → AI agent runs readiness checks
5. Deploy       → only if stage 4 passes

Stage 4 is where the agent runs tools like Deploy Guard and Package Doctor, reads their output, and makes a go/no-go recommendation with specific reasons.

Wiring the tools

The agent needs two things: commands to run and rules for interpreting results.

Deployment readiness

Deploy Guard checks environment configuration:

php artisan deploy:guard --env=production --ci --fail-on=warning

It produces a structured report — pass, warning, fail, or skipped for each check — with exit codes the agent can act on. Non-zero means something needs attention.

Dependency health

Package Doctor audits every Composer package:

php artisan package:doctor --no-dev --ci

It scores each production dependency on abandonment, security advisories, Laravel compatibility, release recency, and constraint conflicts. Exit code 2 means at least one critical package was found.

Migration status

Standard Laravel:

php artisan migrate:status

Why the combination matters

An agent that runs all three commands now has a picture that no individual tool provides: the environment is misconfigured and a dependency is abandoned and there is a pending migration. Individually, each might be acceptable. Together, they represent a deploy that should not go out.

Teaching the agent what matters

Running the commands is the easy part. The value of the agent is in interpreting results with context.

A system prompt for a deploy-gate agent:

You are a deployment readiness reviewer for a Laravel application.

Run these commands in order:
1. php artisan deploy:guard --env=production --json
2. php artisan package:doctor --no-dev --json
3. php artisan migrate:status

BLOCK the deploy if:
- Deploy Guard reports any "fail" status
- Package Doctor finds a package with status "Critical"
- migrate:status shows pending migrations

WARN but allow the deploy if:
- Deploy Guard reports warnings only
- Package Doctor finds "Risky" packages but none "Critical"
- All migrations are up to date

For each issue, explain:
- What the problem is
- Why it matters for this deploy
- What action the team should take

Output a final verdict: PASS, WARN, or BLOCK.

That prompt is not sophisticated. It is a checklist with judgment attached. The agent follows the checklist, but when it encounters ambiguity — a Risky package the team has already forked, a warning that only applies to certain deployment targets — it can reason about context in a way that a bash if statement cannot.

What the agent produces vs what a script produces

Consider a deploy where all three commands return issues.

What a shell script gives you

Three non-zero exit codes. The pipeline stops. The developer gets no context about which problem matters most or what to do about it.

What the agent gives you

Verdict: BLOCK

Three issues prevent this deploy:

1. Queue driver is "sync" in production.
   Jobs will execute inside the HTTP request cycle. Any slow
   job will cause request timeouts. Set QUEUE_CONNECTION to
   redis, sqs, or database before deploying.

2. vendor/legacy-auth is abandoned (score: 22/100).
   No release in 18 months. Marked abandoned on Packagist.
   This is a production dependency handling authentication.
   Evaluate the suggested replacement or fork the package.

3. One pending migration: create_audit_logs_table.
   Committed August 14. If this deploy depends on the
   audit_logs table, the feature will fail silently. Run the
   migration or confirm the feature is behind a flag.

Advisory: File-based cache in production is functional but will
not survive container restarts. Consider switching to Redis.
This is not blocking.

That is the difference between a red light and a diagnosis.

Structured output for the pipeline

The agent should return JSON with a verdict field so the pipeline can act on it programmatically:

{
  "verdict": "BLOCK",
  "issues": [
    {
      "source": "deploy-guard",
      "check": "queue_driver",
      "severity": "fail",
      "message": "Queue driver is set to sync in production",
      "action": "Set QUEUE_CONNECTION to redis, sqs, or database"
    },
    {
      "source": "package-doctor",
      "check": "vendor/legacy-auth",
      "severity": "critical",
      "message": "Package abandoned, score 22/100",
      "action": "Fork or replace before upgrading"
    }
  ],
  "advisories": [
    {
      "source": "deploy-guard",
      "check": "cache_driver",
      "severity": "warning",
      "message": "File-based cache will not survive container restarts"
    }
  ]
}

The pipeline reads the verdict. The human reads the explanation. If the agent hallucinates a check name or invents a status, the structured format makes it obvious.

Guardrails on the agent itself

An agent with access to your deploy pipeline needs constraints. The same principles from agentic coding apply here, but stricter — because this runs unattended.

Read-only tools only. The agent runs commands that inspect state. It does not run composer update, php artisan migrate, or anything that modifies the project. Deploy Guard and Package Doctor are both read-only by design. The agent reports; a human acts.

No deploy authority. The agent can block a deploy by returning a non-zero exit code. It cannot approve a blocked deploy. A manual override step in the pipeline is the only way to proceed past a BLOCK verdict. The agent is a gate, not a gatekeeper.

Allow-lists for known exceptions. The agent can be wrong about context it does not have — flagging a Risky package the team has already evaluated. The fix is the same as any alert system: maintain an allow-list.

// config/deploy-guard.php
'allow' => [
    'sync_queue_in_production',  // Intentional for this worker service
],

Where this breaks down

AI agents add a layer of interpretation that scripts cannot provide. They also add a layer of non-determinism that scripts do not have.

The same set of tool outputs may produce slightly different phrasing across runs. The verdict should be consistent — it is based on clear rules — but the explanation may vary. For teams that need exact reproducibility in audit logs, the raw tool output (Deploy Guard JSON, Package Doctor JSON) is the source of truth. The agent’s interpretation is supplementary.

The practical version

This is not autonomous deployment. The agent does not decide when to deploy, what to deploy, or how to deploy. It does not write fixes for the problems it finds.

It is a reviewer that runs the checks a careful developer would run if they had time, reads the results the way a senior engineer would read them, and writes up the findings so the team can make an informed decision.

The deploy still belongs to the humans. The agent just makes sure they are not flying blind.