Home/
Part XIII — Expert Mode: Systems, Agents, and Automation/38. Building a Code-Change Agent Safely
38. Building a Code-Change Agent Safely
Overview and links for this section of the guide.
On this page
High Stakes Coding
A coding agent is fundamentally different from a chatbot. It can:
- Delete your production database
- Introduce security vulnerabilities
- Push broken code to main
- Expose secrets in commits
- Create infinite loops that cost thousands
You cannot treat a coding agent like a helpful assistant. Every action must be validated, reviewed, and reversible.
The Safe Architecture
We use the Proposal Pattern—the agent never takes direct action. It proposes, humans approve.
┌─────────────────────────────────────────────────────────────────┐
│ SAFE CODE CHANGE PIPELINE │
├─────────────────────────────────────────────────────────────────┤
│ │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
│ │ ANALYST │──▶│ HUMAN │──▶│ CODER │──▶│ REVIEWER │ │
│ │ AGENT │ │ APPROVAL │ │ AGENT │ │ AGENT │ │
│ └──────────┘ └──────────┘ └──────────┘ └──────────┘ │
│ │ │ │ │ │
│ ▼ │ ▼ ▼ │
│ Creates Approves Generates Checks for │
│ PLAN or rejects DIFF bugs, security │
│ the plan │
│ │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
│ │ TEST │──▶│ HUMAN │──▶│ MERGE │ │
│ │ RUNNER │ │ APPROVAL │ │ │ │
│ └──────────┘ └──────────┘ └──────────┘ │
│ │ │ │
│ ▼ │ │
│ Runs tests Final review │
│ on changes before merge │
│ │
└─────────────────────────────────────────────────────────────────┘
Notice the TWO human checkpoints. This is non-negotiable for production code.
Core Principles
| Principle | Implementation |
|---|---|
| Never auto-apply | All changes require human approval |
| Always reversible | Every change creates a backup or git commit |
| Defense in depth | Multiple validation layers (review, lint, test, security) |
| Minimal scope | Agent only accesses files needed for the task |
| Auditable | Every decision is logged with reasoning |
Implementation Overview
// code-agent-pipeline.ts
export class SafeCodeAgent {
async processIssue(issue: Issue): Promise {
// Phase 1: Analyze and Plan (no code changes)
const analysis = await this.analystAgent.analyze(issue);
const plan = await this.analystAgent.createPlan(analysis);
// CHECKPOINT 1: Human approves the plan
const planApproval = await this.humanReview.requestApproval({
type: 'plan',
content: plan,
context: analysis
});
if (!planApproval.approved) {
return { status: 'rejected', reason: planApproval.feedback };
}
// Phase 2: Generate code changes
const diff = await this.coderAgent.generateDiff(plan);
// Phase 3: Automated review gates
const reviewResults = await Promise.all([
this.reviewerAgent.checkBugs(diff),
this.lintGate.check(diff),
this.securityGate.scan(diff),
this.testRunner.run(diff)
]);
const hasBlockingIssues = reviewResults.some(r => r.severity === 'blocking');
if (hasBlockingIssues) {
return { status: 'blocked', issues: reviewResults };
}
// Create PR for human review
const pr = await this.git.createPullRequest({
title: plan.title,
description: plan.description,
diff,
reviewResults
});
// CHECKPOINT 2: Human merges (handled by normal PR flow)
return pr;
}
}
Start More Restrictive Than You Think
Begin with agents that can only read code and propose plans. Add action capabilities gradually as you build trust and validation layers.
Where to go next
Explore next
38. Building a Code-Change Agent Safely sub-sections
5 pages