Autonomous Software Factories: Planning Agents, Builders, and Reviewers

How Self-Driving Codebases Work: The Complete SDLC Cycle

Featured image

Image credit: InfoWorld

The Autonomous SDLC: A Complete Example

TL;DR β€” An autonomous SDLC runs planning β†’ building β†’ reviewing β†’ integrating β†’ monitoring entirely by AI agents. A developer submits a feature request (β€œAdd dark mode toggle”), the system routes through agents, and code ships automatically β€” including tests, documentation, and deployment. No human writes a single line of code. This is the pattern used by Gitpod’s software-factory.dev and Ona’s system.

Let’s walk through a complete autonomous SDLC workflow with a real example: building a β€œdark mode toggle” feature.


The Complete Flow: Feature to Production

Step 1: Feature Intake β†’ Planning Agent

Human input:

Feature Request: Add dark mode toggle to user settings

Description:
- User can toggle dark/light mode in settings
- Preference persists across sessions
- Default is system preference
- All pages immediately reflect the change

Acceptance Criteria:
- [ ] Toggle switch visible in settings
- [ ] Saves to user preferences
- [ ] Persists on page reload
- [ ] Works across all pages
- [ ] Follows accessibility guidelines

Planning Agent receives this and:

  1. Parses intent β€” Identifies: UI component + backend + persistence + accessibility
  2. Breaks into tasks:
{
  "feature_id": "DARK_MODE_001",
  "tasks": [
    {
      "id": "T1",
      "name": "Create theme context and provider",
      "subtasks": ["Define theme types", "Create React Context", "Add localStorage hook"],
      "depends_on": [],
      "assigned_to": "builder-agent-react"
    },
    {
      "id": "T2", 
      "name": "Update user settings table",
      "subtasks": ["Add theme_preference column", "Create migration", "Add constraints"],
      "depends_on": [],
      "assigned_to": "builder-agent-backend"
    },
    {
      "id": "T3",
      "name": "Create settings API endpoint",
      "subtasks": ["POST /api/user/settings", "Add authentication", "Validate input"],
      "depends_on": ["T2"],
      "assigned_to": "builder-agent-backend"
    },
    {
      "id": "T4",
      "name": "Build dark mode toggle component",
      "subtasks": ["Create component", "Wire to theme context", "Add accessibility attrs"],
      "depends_on": ["T1", "T3"],
      "assigned_to": "builder-agent-react"
    },
    {
      "id": "T5",
      "name": "Apply theme throughout app",
      "subtasks": ["Update global CSS", "Ensure contrast ratios", "Test on mobile"],
      "depends_on": ["T4"],
      "assigned_to": "builder-agent-react"
    }
  ],
  "priority": "medium",
  "estimated_effort": "6 hours",
  "complexity_score": 6.5
}
  1. Analyzes codebase context:
    • Existing theme system (Tailwind CSS)
    • Current authentication pattern
    • Database schema
    • API conventions
  2. Routes tasks in dependency order to builder agents

Step 2: Building β†’ Builder Agents

Builders receive their assignments and generate code in parallel:

Builder Agent T1: Frontend Theme Context

// contexts/ThemeContext.tsx (auto-generated)
import React, { createContext, useState, useEffect } from 'react';

type Theme = 'light' | 'dark' | 'system';

interface ThemeContextType {
  theme: Theme;
  setTheme: (theme: Theme) => void;
}

const ThemeContext = createContext<ThemeContextType | undefined>(undefined);

export const ThemeProvider: React.FC<{ children: React.ReactNode }> = ({ children }) => {
  const [theme, setTheme] = useState<Theme>('system');

  useEffect(() => {
    // Load from localStorage
    const saved = localStorage.getItem('theme') as Theme | null;
    if (saved) setTheme(saved);
    
    // Apply theme to DOM
    const root = document.documentElement;
    if (theme === 'system') {
      const isDark = window.matchMedia('(prefers-color-scheme: dark)').matches;
      root.classList.toggle('dark', isDark);
    } else {
      root.classList.toggle('dark', theme === 'dark');
    }
  }, [theme]);

  const handleSetTheme = (newTheme: Theme) => {
    setTheme(newTheme);
    localStorage.setItem('theme', newTheme);
  };

  return (
    <ThemeContext.Provider value={{ theme, setTheme: handleSetTheme }}>
      {children}
    </ThemeContext.Provider>
  );
};

export const useTheme = () => {
  const context = React.useContext(ThemeContext);
  if (!context) throw new Error('useTheme must be used inside ThemeProvider');
  return context;
};

// Generated test file
describe('ThemeProvider', () => {
  it('loads theme from localStorage', () => {
    localStorage.setItem('theme', 'dark');
    render(<ThemeProvider><div>Test</div></ThemeProvider>);
    expect(document.documentElement.classList.contains('dark')).toBe(true);
  });
  
  it('saves theme to localStorage on change', () => {
    const { rerender } = render(/* ... */);
    // Test assertions...
  });
});

Builder Agent T2: Database Migration

-- Generated migration: 2026-08-11_add_theme_preference.sql
ALTER TABLE users ADD COLUMN theme_preference VARCHAR(10) DEFAULT 'system' CHECK (theme_preference IN ('light', 'dark', 'system'));
CREATE INDEX idx_users_theme_preference ON users(theme_preference);

-- Rollback
-- ALTER TABLE users DROP COLUMN theme_preference;

Builder Agent T3: Backend API

// routes/user-settings.ts (auto-generated)
import express from 'express';
import { db } from '../db';
import { authenticateToken } from '../middleware/auth';

router.post('/api/user/settings', authenticateToken, async (req, res) => {
  const { theme_preference } = req.body;
  
  // Validation
  if (!['light', 'dark', 'system'].includes(theme_preference)) {
    return res.status(400).json({ error: 'Invalid theme' });
  }
  
  try {
    await db.query(
      'UPDATE users SET theme_preference = $1 WHERE id = $2',
      [theme_preference, req.user.id]
    );
    res.json({ success: true, theme: theme_preference });
  } catch (error) {
    res.status(500).json({ error: 'Failed to update settings' });
  }
});

// Generated tests
describe('POST /api/user/settings', () => {
  it('updates theme preference', async () => {
    const response = await request(app)
      .post('/api/user/settings')
      .set('Authorization', `Bearer ${token}`)
      .send({ theme_preference: 'dark' });
    
    expect(response.status).toBe(200);
    expect(response.body.theme).toBe('dark');
  });
});

Builders submit PRs β†’ Tasks move to review queue

Step 3: Review β†’ Reviewer Agent

Reviewer Agent receives all PRs and validates:

Checking T1 (Theme Context):
  βœ“ TypeScript types correct
  βœ“ React hooks used correctly
  βœ“ localStorage access is safe
  βœ“ Test coverage: 91% βœ“
  βœ“ Accessibility: ARIA labels present
  βœ“ Performance: No unnecessary re-renders
  β†’ APPROVED

Checking T2 (Database Migration):
  βœ“ SQL syntax valid
  βœ“ Indexes created for performance
  βœ“ Rollback script present
  βœ“ No breaking schema changes
  β†’ APPROVED

Checking T3 (API Endpoint):
  βœ“ Authentication enforced
  βœ“ Input validation present
  βœ“ Error handling comprehensive
  βœ“ Response format consistent
  βœ“ Test coverage: 87%
  βœ“ No SQL injection vulnerabilities
  β†’ APPROVED

Checking T4 (Toggle Component):
  ⚠ WARNING: Missing accessibility label
  Suggestion: Add aria-label="Toggle dark mode"
  
  Builder Agent accepts suggestion and updates
  β†’ Re-review: APPROVED

Checking T5 (Global CSS):
  βœ“ Contrast ratios checked (WCAG AA)
  βœ“ All components themed
  βœ“ Mobile responsive tested
  β†’ APPROVED

All PRs merged to main branch

Step 4: Integration β†’ Integrator Agent

Integrator runs comprehensive tests:

[1] Running full test suite
  Unit tests: 1,247 passed in 42s βœ“
  Integration tests: 156 passed in 31s βœ“
  E2E tests (critical paths): 43 passed in 18s βœ“
  
[2] Building artifacts
  Docker image built: v2.14.5-dark-mode-001
  Bundle size: 2.3 MB (+0.1 MB from dark mode) βœ“
  
[3] Deploying to staging
  Deployed to staging-us-east-1
  Healthcheck: All endpoints responding βœ“
  
[4] Smoke tests in staging
  Homepage loads: 234ms βœ“
  Settings page loads: 187ms βœ“
  Theme toggle works: βœ“
  Database migration applied: βœ“
  
[5] Deploying to production
  Canary deploy (1% traffic)
  Monitoring for 30 minutes...
  
  Error rate: 0.02% (normal) βœ“
  Response time: 187ms (baseline 185ms) βœ“
  CPU usage: 42% (baseline 40%) βœ“
  
  Escalating to 10% traffic
  Escalating to 50% traffic
  Full rollout: 100% traffic
  
[6] Feature marked COMPLETE
  Deployed at 2026-08-11 14:32:15 UTC
  Accessible to all users
  Rollback available (previous version tagged)

Step 5: Monitoring β†’ Monitoring Agent

Monitoring runs continuously:

MONITORING: dark-mode-feature (60 minutes)

βœ“ Error rate stable (0.01-0.02%)
βœ“ Response time stable (185-195ms)
βœ“ Zero uncaught exceptions related to theme
βœ“ Usage metrics:
  - 23% of users toggled to dark mode
  - 45% using system preference
  - 32% using light mode
βœ“ Zero accessibility violations reported
βœ“ Mobile usage: 87% success rate (matching desktop)

FEATURE STATUS: STABLE βœ“
All gates passed. Feature ready for long-term support.

The Agent Architecture Diagram

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ HUMAN: "Add dark mode toggle"                       β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                     β”‚
        β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
        β”‚  PLANNING AGENT           β”‚
        β”‚  - Parse feature          β”‚
        β”‚  - Break into tasks       β”‚
        β”‚  - Order dependencies     β”‚
        β”‚  - Route assignments      β”‚
        β””β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”˜
             β”‚       β”‚          β”‚
     β”Œβ”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”  β”Œβ”€β–Όβ”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
     β”‚ BUILDER  β”‚  β”‚ BUILDER β”‚ β”‚ BUILDER    β”‚
     β”‚ (React)  β”‚  β”‚(Backend)β”‚ β”‚(Database)  β”‚
     β”‚ T1, T4   β”‚  β”‚ T2, T3  β”‚ β”‚ T2         β”‚
     β””β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”˜  β””β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
             β”‚       β”‚          β”‚
             β””β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                     β”‚
        β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
        β”‚  REVIEWER AGENT           β”‚
        β”‚  - Syntax check           β”‚
        β”‚  - Security scan          β”‚
        β”‚  - Test coverage          β”‚
        β”‚  - Performance            β”‚
        β”‚  - Accessibility          β”‚
        β””β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
             β”‚
        β”Œβ”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
        β”‚  INTEGRATOR AGENT         β”‚
        β”‚  - Merge branches         β”‚
        β”‚  - Run full test suite    β”‚
        β”‚  - Deploy to staging      β”‚
        β”‚  - Deploy to production   β”‚
        β”‚  - Canary monitor         β”‚
        β””β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
             β”‚
        β”Œβ”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
        β”‚  MONITORING AGENT         β”‚
        β”‚  - Watch errors           β”‚
        β”‚  - Track performance      β”‚
        β”‚  - Monitor usage          β”‚
        β”‚  - Auto-rollback if issuesβ”‚
        β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Key Differences from Traditional SDLC

Traditional Autonomous
Human writes code AI writes code
Human reviews code AI reviews code
Manual testing Automated testing
Human QA approval Gate-based approval
Scheduled deployments Continuous deployment
Humans manage rollbacks Auto-rollback on issues
Days from feature request to shipping Hours from feature request to shipping

The Human Role in Autonomous SDLC

Humans now:

A developer’s week in an autonomous factory:

Monday: Plan 3 features, review agent implementations
Tuesday: Improve agent decision-making for edge cases
Wednesday: Monitor production metrics and customer feedback
Thursday: Teach agents new patterns from recent incident
Friday: Architect improvements to factory infrastructure

Why Autonomous Factories Matter

Productivity Impact

Traditional factory:

Autonomous factory:

Quality Impact

Traditional:

Autonomous:

Deployment Frequency

Traditional: Deploy every 1-4 weeks (batched releases) Autonomous: Deploy multiple times per day (continuous)

Result: bugs fixed in hours instead of weeks

Frequently Asked Questions

Q: How do agents actually communicate with each other?
A: Through task queues and structured output. Planning Agent outputs JSON tasks β†’ Builder Agent consumes tasks, generates code β†’ Reviewer Agent receives code+tests β†’ Integrator Agent merges and deploys. Each agent speaks the same JSON language. Implementation usually uses AWS SQS, RabbitMQ, or Kafka queues.

Q: What about failure scenarios β€” what if a builder agent gets stuck?
A: Multiple fallbacks: (1) Timeout β€” if builder takes >30 min, reassign task to different agent. (2) Validation failure β€” if output doesn’t meet schema, re-prompt with feedback. (3) Human escalation β€” if agent fails 3 times, notify human. (4) Rollback β€” if deployed code fails in production, auto-rollback. Systems are designed to fail gracefully.

Q: How much human oversight is actually needed?
A: At scale: 5-10% human involvement. Humans handle: requirements clarification (2%), feature approvals (3%), escalated failures (2%), production incidents (2%), strategic decisions (1%). Most daily work is autonomous. Humans become architects, not coders.

Q: Can this work for my programming language?
A: Most likely yes. Claude and GPT-4 support: Python, JavaScript/TypeScript, Go, Java, C++, Rust, C#, PHP, Ruby, Kotlin, and 20+ others. If your language has good documentation and examples online, agents can use it. Harder for niche languages (Cobol, Lisp) but still possible.

Q: How do agents actually decide what to build from a feature request?
A: Planning Agent uses: (1) Feature description, (2) Existing codebase structure, (3) Past similar features, (4) Acceptance criteria. It breaks features into tasks, then builders implement one task at a time. Example: β€œAdd dark mode” β†’ tasks = [Create context, Update UI, Add database field, Write tests].

Q: What’s the learning curve for developers in an autonomous system?
A: Low. Developers write better requirements (more specific, clearer acceptance criteria). They write more tests (agents need clear test cases to understand intent). They review agent-generated code (3-5 min per task, not hours). Many developers find it liberating β€” less grunt work, more review and architecture.

Q: How is this different from GitHub Copilot or ChatGPT?
A: Copilot is interactive (you ask, it generates snippets). Autonomous factories are systematic (autonomous agents coordinate without human prompting). Copilot generates code in context. Factories plan, build, review, test, deploy, and monitor β€” end-to-end automation. Copilot assists humans; factories replace specific human roles.


Next in the series: Real autonomous factories β€” how Gitpod, Ona, and others built their systems.