When AI writes the code, who enforces the standards?

Boris Chabeda
Systems Engineer, Andela Talent
Sep 18, 2026
8 min
When AI writes the code, who enforces the standards?

The promise of agentic software engineering is alluring: feed a task to an agent like Cursor or Claude Code and watch a complete "production-ready” pull request materialize in seconds.

For simple tasks like generating a standalone utility function or scaffolding a CRUD route, this works brilliantly. Because isolated LLM code generation yielded instant wins, the logical conclusion would be: if an agent can write a function, an agentic loop can engineer the entire repository.

If you take an autonomous agent and drop it into an already complex codebase where global cohesion is a requirement, without altering the surrounding infrastructure, it is a disaster waiting to happen.

To harness AI safely, engineering teams position deterministic guardrails inside the repository harness long before enabling agentic tools.

The illusion of autonomous delivery

When you turn autonomous agents loose on complex codebases without structural boundaries, productivity initially spikes then plummets. This slump happens because of a fundamental conflict in priorities:

  • The Agent’s objectives: Local optimization. Make the current test pass and close the ticket using the shortest token path possible
  • The system's objectives: Global cohesion. Maintain compatibility, zero trust security boundaries, resource pooling and architectural cohesion over a multi tier boundary.

Unchecked agents accelerate technical debt because they lack the awareness of global constraints. To pass a local unit test an agent will happily instantiate duplicate client connections, bypass shared middleware or mutate global state.

To prevent agents from introducing architectural antipatterns teams must establish machine readable boundaries before delegating tasks.

Consider a standard schema contract embedded in a repository’s CI pipeline:

# api/schemas/v2/subscriptions.yaml
# Caption: The baseline API schema contract acting as deterministic Guardrail #1.
components:
schemas:
ErrorResponse:
type: object
required: [error]
properties:
error:
type: object
required: [code, message]
properties:
code: { type: integer, example: 403 }
message: { type: string, example: "Forbidden" }

At first glance, this looks like routine API documentation. In an agent-driven workflow, this schema acts as an active, machine-readable boundary designed to intercept contract drift automatically.

To complement schema validation, teams must also enforce structural code boundaries using static analysis:

// rules/no-inline-auth-instantiation.js
// An AST static analysis rule acting as deterministic Guardrail.
module.exports = {
meta: {
type: "problem",
docs: {
description: "Forbid inline AuthValidator instantiation inside handlers"
},
messages: {
architecturalViolation: "Architectural Violation: AuthValidator must be injected via Global Middleware, not instantiated in request handlers."
}
},
create(context) {
return {
NewExpression(node) {
if (node.callee.name === 'AuthValidator') {
context.report({
node,
messageId: "architecturalViolation"
});
}
}
};
}

This abstract syntax tree (AST) linter rule sits in the build pipeline. It doesn't write code, but it defines the non-negotiable structural parameters of the application architecture.

To transform AI agents from volatile code churners into dependable software delivery engines, we must reconcile agentic speed with architectural stability.

High-reliability software delivery treats the AI agent as an untrusted high-velocity engine operating inside a deterministic human-designed harness.

In this model, human engineers stop spending hours reviewing standard syntax line by line. Instead, engineering efforts shift to designing explicit specifications, fine-tuning system boundaries and configuring deterministic feedback loops. The quality of an AI agent's output is directly bounded by the harness built to constrain it.

The harness in action

To see how this architecture operates under real-world conditions, consider a routine task:

Upgrading a critical /v2/billing/subscriptions endpoint in a microservice to enforce fine-grained Role-Based Access Control (RBAC).

An autonomous agent was assigned the task with a straightforward instruction: “Enforce the admin:write scope in subscription upgrades.”

In under 45 seconds, the agent opened a pull request. It touched six files, wrote 140 lines of code, and reported that 12 of its generated unit tests were a success. 

Under the hood, however, the agent has executed a classic localized failure mode. Struggling to mock the service’s dependency injection tree. It bypasses the global middleware entirely and instantiates a rogue  new Authenticator() directly inside the request handler. 

To make its local assertions pass, it also flattened the endpoint’s standardised error payload swapping the required nested structure for a flat (“detail”: “Unauthorised”).

// src/controllers/subscriptions.ts
// The rogue code generated by the agent to pass local unit tests.
import { Request, Response } from 'express';

export async function updateSubscription(req: Request, res: Response) {
const auth = new AuthValidator();
if (!auth.checkScope(req, 'admin:write')) {
// Flattened schema payload (Violates Guardrail #1)
return res.status(403).json({ detail: "Unauthorized" });
}
}

This code was locally functional but globally destructive. 

In production, it would have silently broken downstream mobile SDKs expecting the nested schema while leaking database connections by re-initializing the auth client pool in every HTTP request.

When guardrails were embedded in the pipeline prior to execution, the system intercepted the flaw immediately:

  1. The API Contract Gate Fired: The automated schema validator ran in CI, comparing the agent's modified response against subscriptions.yaml. It failed the build due to the missing error.code payload structure.
  2. The AST Static Linter Fired: The custom linter rule flagged the illegal new AuthValidator() call, failing the build on architectural grounds.
# CI Test Execution Output Log
# Caption: Deterministic CI failure logs fed back into the agent loop.
[FAIL] Contract Violation: /v2/billing/subscriptions
- Missing required property: 'error' in response payload.
[FAIL] AST Architectural Rule Violation: src/controllers/subscriptions.ts:4
- AuthValidator must be injected via Global Middleware, not instantiated in request handlers.

A reviewer didn't spend 45 minutes debugging 140 lines of plausible syntax to catch these subtle defects. The deterministic system identified the architectural breaches in 4 seconds.

The engineer simply piped the exact CI error log back to the agent:

“Fix schema compliance and route auth through middleware.” 10 seconds later, the agent delivered a fully compliant production-ready PR.

Operating playbook

Safely integrating AI agents into an active software delivery pipeline requires three operational adjustments:

Define boundaries before specifying tasks

Never prompt an agent to write code in a domain lacking strict type contracts, static analysis rules or dynamic test assertions. If the system cannot automatically catch a failure mode, it remains susceptible to failure when an agent commits it.

Version control repository rules

Store repository conventions, architectural guidelines and module boundaries directly alongside the codebase so the agent consumes them natively.

<!-- .cursorrules / SYSTEM_PROMPT.md -->
<!-- Repo-level rule file constraining agent execution pathways. -->
# Architecture Constraints
- NEVER instantiate `AuthValidator` directly. Always consume `req.user` attached by global auth middleware.
- ALL error responses MUST strictly match the definitions in `/api/schemas`.
- Do not add external dependencies without updating `package.json` and running the package manager to regenerate the lockfile.

Shorten the deterministic loop

Force the agent to execute AST linters type checkers and unit tears locally inside its own execution loop before submitting a pull request. The agent should resolve failures against automated guardrails during execution rather than during human code review.

Code generation is largely a solved problem, system boundary design is the emerging engineering bottleneck. High performing teams do not succeed with AI by handing control of the workflow over to the autonomous agents. They succeed by building a deterministic harness that makes bad AI code impossible to merge.

Boris Chabeda
Systems Engineer, Andela Talent
No items found.
No items found.
No items found.

Recent articles