---
title: "Shipping production software with AI agents"
description: "Can AI agents write production code? Yes, if the system around them enforces quality mechanically. The agentic development workflow that ships production software."
date: 2026-07-18
updated: 2026-10-17
canonical: https://pabloalbaladejo.com/blog/shipping-production-software-with-ai-agents
---

# Shipping production software with AI agents

The question I get asked most often is some version of "can AI agents write production code?" The answer is yes, and the condition is the whole story. Agents can write production code **when the system around them enforces quality mechanically**. The model matters far less than the machine you put it inside. If you take one thing from this piece, take that: the interesting engineering is in the guardrails, not in the agent.

I can point at the proof. Kaiord, an open-source, local-first training platform, is built end to end by agents. Its landing page says so plainly: *"Every line — domain, adapters, editor, this page — written by AI agents."* It is a TypeScript monorepo with a domain core, format adapters, a CLI, an MCP server, and a React editor. It shipped version 10.0.0 to npm on 2026-07-18, the day I published this post. It has more than 700 merged pull requests behind it. I wrote almost none of that code by hand. What I do is approve, set constraints, and sometimes say no. The rest is a system.

The system has four pillars, and I will describe where it fails as well as where it works. A good prompt is not enough.

## 1. Specs before code

Non-trivial work starts with a written spec, not a diff. In Kaiord that is the `openspec/` flow: a proposal, a design and a task list land in `openspec/changes/<slug>/` before anyone touches an implementation file. Agents follow the tasks in a fixed hexagonal order (domain, then application, then ports, then adapters) and tick items off as they go.

This is not ceremony. Of all the failures I know, this one is the cheapest to prevent. An agent with a vague goal will invent an interpretation and build it, with confidence and often with good reasons. But two agents with the same vague goal will invent *two* interpretations and build both. Now you have a subtle inconsistency that no single diff review will catch. A spec is a shared contract. I can check the agents against it, and they can check each other. The drift I feared most early on was plausible code that disagrees with itself. Making the agent commit to a plan first designs most of that out.

## 2. Zero-tolerance CI is the real reviewer

Kaiord's quality policy is strict on purpose: zero ESLint warnings, zero TypeScript errors, zero test warnings, zero build warnings, and a 100% test pass rate. Coverage thresholds are 80% on core packages and 70% on the frontend. The policy is not a wish in a README. It is the CI gate, and the gate is a machine, not my patience.

This is the shift that makes agentic development workable at volume. I do not read every line of every diff. I could not, and pretending otherwise would be the real risk. Instead I read the spec and trust the gate to be the line-by-line reviewer. An agent cannot talk its way past a failing test. A tired human reviewer can be talked into "we will fix it later." The build is red or it is green.

One caveat, because this is where people get hurt: "green" has to mean the *whole* CI run, not the required-checks subset. Kaiord learned this from a real incident. A major dependency bump renamed some type unions and turned a non-required job, the SPA model catalog, red while every required check stayed green. If you gate only on the required subset, you merge a regression and call it clean. The rule that came out of it: treat any red job as red. When a bump makes a generated artifact stale, regenerate the artifact instead of merging around it. Agents are excellent at chasing a gate to green. That is exactly why the gate has to cover everything you care about.

## 3. Mechanical convention guards

Conventions survive because machines enforce them, not because anyone remembers them. This is the pillar people underestimate most.

Kaiord's test suite has two structural rules that are checked, not requested. `R-ItTitleShould` requires every test title to start with the word "should." `R-ItBodyAAA` requires every test body to carry `// Arrange`, `// Act`, `// Assert` markers, in order. Both are enforced three times: in the editor via ESLint, at commit via a pre-commit script, and again in CI. On top of that sits a set of `scripts/check-*.mjs` guards. One blocks toast and console calls from interpolating anything except static strings, to stop personal data leaking into logs. One forbids the state store from writing to the database directly. The cap of 100 lines per file and 40 lines per function is an ESLint rule in the same spirit. Small units keep diffs reviewable and stop agents burying a mistake in a 400-line function.

One failure justifies all of it. One of those guards checks the shape of a session-match identifier. It exists *because two agents diverged on that identifier's format* and produced a real bug. The convention lived in a document. The agents did not follow it, and the bug shipped far enough to hurt. The fix was not a sterner prompt. The fix was a script that fails the build when the shape is wrong. An agent will follow a rule it can see in a red error message and ignore one buried three links deep in a doc. So the operating principle is blunt: if a convention matters, it is a failing check, not a paragraph.

## 4. Isolation: worktrees and PR gates

Every change gets its own branch and its own git worktree, with no exceptions, down to a one-line fix. The pre-commit hook typechecks the whole monorepo before anything is committed. So a change that breaks a package three directories away never reaches a branch tip. And every change lands as a pull request.

Isolation is what makes the whole thing safe to run at speed. A bad agent run stays on its branch. It cannot corrupt the trunk while I am not looking. If something slips through, rollback is one revert and a push, and the pipeline redeploys itself. This plain plumbing is what lets me relax while agents move fast: any single mistake affects one branch, and the trunk is always releasable.

## What still needs me

None of this removes the human. It moves the human to where judgment lives.

**Approval gates.** On Kaiord, only I merge. The gate is not a keystroke. It is a decision. Machines decide whether the code is *correct*. I decide whether it should exist.

*Update, 2026-10-17:* an earlier version said the merge is "the one thing I never delegate". That is no longer true everywhere, so here is the rule I follow now. It depends on the repo. On Kaiord and my other repos, I press merge. On this personal site, an agent merges its own pull requests. It may do that only after a separate review agent approves and CI is green on the exact commit. After the merge, the agent watches the deploy until it finishes. New essays are the one exception: they also need my approval of the content.

**Taste.** Is this the right feature? Does the interaction feel right? Will the abstraction age well? Agents are very good at optimizing inside a defined box and bad at asking whether it is the right box. That question is mine.

**Constraints.** What must this system never do? Kaiord is local-first: certain data must never leave the device. That boundary is a value judgment before it is a check. The agents optimize inside the constraints, and I draw them. The lesson that keeps coming back is that agents are literal. They will satisfy the letter of a task and miss its intent, every time you leave the intent unstated. My job is to keep stating it.

## A starter checklist

If you want to run software this way, this is the shortest version of what makes it work:

1. **Write conventions as failing checks, not documentation.** If a rule only lives in prose, assume it will be broken. Turn it into a lint rule or a `check-*.mjs` script that turns the build red.
2. **Make CI the reviewer, and make it strict.** Zero warnings, real coverage thresholds, and a gate on the *entire* run, not on the convenient subset.
3. **Spec before code for anything non-trivial.** A short written contract prevents the confident, plausible drift that diff review will not catch.
4. **One branch and one worktree per change.** Limit the damage, so a bad run is a revert and not an incident.
5. **Keep files and functions small.** Small units keep diffs reviewable and keep agents from burying a mistake inside a 400-line function.
6. **Make the human gate a merge, not a formality.** Delegate correctness to the machine. Keep intent, taste, and the final yes on product code for yourself.

"Shipping production software with AI agents" is mostly a systems-design problem, not a prompting problem. The agents are capable. Whether they ship something you would put your name on depends on two things. The first is how much of your judgment you encoded into machines that check their work. The second is how honest you are about the parts you still have to do yourself.

## Related writing

- [Evaluating LLM outputs in production](https://pabloalbaladejo.com/blog/evaluating-llm-outputs-in-production) — the eval gate is one of the mechanical guards this system relies on.
- [Observability for LLM pipelines](https://pabloalbaladejo.com/blog/observability-for-llm-pipelines) — what production means once the agents' code is live.
- [GEO: how AI agents find you](https://pabloalbaladejo.com/blog/geo-how-ai-agents-find-you) — a full day of this workflow, documented mechanism by mechanism.
- [A tolerant OAuth server validates your broken client](https://pabloalbaladejo.com/blog/tolerant-oauth-server-validates-your-broken-client) — a mechanical guard for integrations: pin the spec, not the first partner you meet.
- [A 90% pass rate is not a gate](https://pabloalbaladejo.com/blog/a-pass-rate-is-not-a-gate) — what a mechanical guard needs before it counts as a gate: a threshold per criterion, not one average.
- [A gate is only as real as its run](https://pabloalbaladejo.com/blog/a-gate-is-only-as-real-as-its-run) — three Kaiord gates that looked real and were not, and the tiered merge rule that replaced "only I merge".
- [AI-DLC: the only gates that count are the ones code enforces](https://pabloalbaladejo.com/blog/ai-dlc-gates-only-count-when-code-enforces-them) — a mechanical guard Kaiord added in #1520: coverage floors may rise, never fall, checked against the base branch.

## FAQ

### Can AI agents write production code?

Yes, when the system around them enforces quality mechanically. Specs before code, a zero-tolerance CI gate, and machine-checked conventions do the enforcing. On Kaiord every line was written by agents and it ships to npm. Version 10.0.0 went out on 2026-07-18, the day I published this post.

### What's the hardest part of an agentic development workflow?

The guardrails, not the model. Agents drift without mechanical enforcement, so the work goes into turning every convention into a failing check, not into cleverer prompts. An agent follows a rule it can see in a red build. It ignores a rule buried in a doc.

### Do you read the code the agents write?

I read the spec and trust the gate. CI, with zero warnings, coverage thresholds and mechanical guards, is the line-by-line reviewer. I own intent and taste, not the diff. On Kaiord I also own the merge.

### What still needs a human?

Approval gates, taste (is this the right thing to build), and constraints (privacy boundaries, what not to build). Agents optimize inside the box. The human draws the box. On product code like Kaiord, the human also presses merge.

## Sources

- [Kaiord: CLAUDE.md (the agent contract: quality policy, spec flow, code style)](https://github.com/pablo-albaladejo/kaiord/blob/main/CLAUDE.md)
- [Kaiord: AGENTS.md (non-negotiables, mechanical guards, CI invariants)](https://github.com/pablo-albaladejo/kaiord/blob/main/AGENTS.md)
- [Kaiord: mechanical guard scripts (scripts/check-*.mjs)](https://github.com/pablo-albaladejo/kaiord/tree/main/scripts)
- [Kaiord: test-conventions spec (R-ItTitleShould, R-ItBodyAAA)](https://github.com/pablo-albaladejo/kaiord/blob/main/openspec/specs/test-conventions/spec.md)
- [kaiord.com: landing page built entirely by AI agents](https://kaiord.com)
- [@kaiord/core 10.0.0 on npm (published 2026-07-18)](https://www.npmjs.com/package/@kaiord/core)
- [Kaiord: source repository](https://github.com/pablo-albaladejo/kaiord)
