Spec-Driven Development
Spec-Driven Development β€Ί Module 4: Agent Orchestration, Verification & Maintenance
Module 4: Agent Orchestration, Verification & Maintenance

Chapter 13: Multi-Agent Execution Patterns: Implementors, Reviewers, and Adversaries

By Muhammad Riaz

The Single-Agent Limit

When engineering teams first transition from conversational chat sidebars to automated CLI coding agents (such as Claude Code, Cursor Agent, or custom scripts), they typically start with a Single-Agent Pattern: one AI agent reads the specification, writes the implementation code, generates the unit tests, and verifies its own work.

This approach hits a severe structural limitation known as Self-Verification Bias.

Large Language Models struggle to evaluate their own generated output objectively. If an LLM misinterprets a business invariant during the coding phase, it will make that exact same logical error when writing its unit tests. The test passes, the agent reports success, and a broken assumption slips straight past the local verification gate.

To build autonomous, self-healing execution pipelines in Spec-Driven Development, we must evolve from single-agent generation to Multi- Agent Orchestration.

By dividing tasks among specialized AI rolesβ€”operating with separated context boundaries, distinct system instructions, and adversarial mandatesβ€”we eliminate self-verification bias and catch architectural drift before it ever reaches a human code review.

The Three Core Agent Roles

A production-grade multi-agent execution pipeline relies on three distinct operational roles:

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                      MULTI-AGENT EXECUTION PIPELINE                         β”‚
β”‚                                                                             β”‚
β”‚  [ IMPLEMENTOR AGENT ] ──> Generates code strictly matching `tasks.md`       β”‚
β”‚                                   β”‚                                         β”‚
β”‚                                   β–Ό                                         β”‚
β”‚  [ ADVERSARIAL AGENT ] ──> Attempts to BREAK code with aggressive inputs   β”‚
β”‚                                   β”‚                                         β”‚
β”‚                                   β–Ό                                         β”‚
β”‚  [ REVIEWER AGENT ]    ──> Audits diff against `spec.md` & `constitution`   β”‚
β”‚                                   β”‚                                         β”‚
β”‚                                   β–Ό                                         β”‚
β”‚  [ HUMAN ARCHITECT ]   ──> Final inspection & Git pull request approval     β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

1. The Implementor Agent

  • Primary Objective: High-velocity execution of single atomic tasks from 03-tasks.md.

  • Context Boundary: Receives 01-spec.md, the File Impact Map from 02-plan.md, and the specific task definition. It is restricted from modifying files outside the write permissions list.

  • Instruction Strategy: Prompted to be concise, follow existing codebase patterns, and output minimal idiomatic code without adding unrequested features.

2. The Adversarial Agent (The Stress-Tester)

  • Primary Objective: Actively break the code written by the Implementor Agent before unit tests are finalized.

  • Context Boundary: Receives 01-spec.md, 02-plan.md, and the code generated by the Implementor. It does not read the Implementor's conversational thought process.

  • Instruction Strategy: Prompted with a cynical, security-minded persona. It inspects the code specifically for missing validation checks, unhandled null values, race conditions, boundary overflow errors, and unhandled edge paths.

3. The Reviewer / Auditor Agent

  • Primary Objective: Ensure full compliance with the project's Constitution and technical constraints before human code review.

  • Context Boundary: Reads the generated git diff, 01-spec.md, and the repository's constitution.md.

  • Instruction Strategy: Acts as a strict static analysis gatekeeper. It checks for unapproved third-party dependencies, style violations, forbidden paths, and missing inline documentation.

Real-World Multi-Agent Orchestration in Action

Let us walk through a real-world execution sequence for adding a high-concurrency balance transfer feature to a fintech microservice.

Phase 1: Implementor Generation

The Implementor Agent receives Task 2.1 from 03-tasks.md:

"Implement transferCredits(fromUserId, toUserId, amount) in src/services/wallet.service.ts ."

The Implementor generates a standard async function using standard SQL updates:

// Generated by Implementor Agent
async function transferCredits(fromUserId: string, toUserId: string, amount: number) {
await db.user.update({ where: { id: fromUserId }, data: { balance: { decrement: amount } } });
await db.user.update({ where: { id: toUserId }, data: { balance: { increment: amount } } });
}

Phase 2: Adversarial Attack

The Adversarial Agent inspects the Implementor's diff against 01-spec.md and generates a stress-test suite

(tests/adversarial/wallet.spec.ts):

// Generated by Adversarial Agent to break Implementor Code
test("Adversarial: Negative transfer amount should not issue credits", async () => {
// Exploit: Passing a negative amount flips decrement to increment
await expect(transferCredits("user_A", "user_B", -500)).rejects.toThrow();
});

test("Adversarial: Concurrent transfer during insufficient balance", async () => {
// Exploit: Two simultaneous transfers of $100 on a $100 balance cause negative balance
const [res1, res2] = await Promise.allSettled([
  transferCredits("user_A", "user_B", 100),
  transferCredits("user_A", "user_C", 100)
]);
const userA = await db.user.findUnique({ where: { id: "user_A" } });
expect(userA.balance).toBeGreaterThanOrEqual(0);
});

Phase 3: Automated Correction Loop

The test runner executes the Adversarial Agent's test suite. Both tests FAIL.

The test failure output and stack traces are automatically routed back to the Implementor Agent with the directive:

"Your implementation failed 2 adversarial edge-case tests. Fix src/services/wallet.service.ts so that all adversarial tests pass without modifying the test assertions."

The Implementor Agent rewrites the function, wrapping the updates inside a database transaction (prisma.$transaction) with an explicit input check (amount > 0) and an atomic balance guard (WHERE balance >= amount).

Phase 4: Reviewer Verification

The Reviewer Agent runs a final check against constitution.md:

  • All mutations use Prisma transactions.

  • Zero new dependencies introduced.

  • Unit and adversarial tests pass with 100% path coverage.

Only after passing all three agent passes does the pipeline trigger a Human Review Gate, presenting the human developer with a clean, hardened Pull Request.

Key Multi-Agent Execution Patterns

When designing multi-agent workflows for your engineering team, choose the pattern that matches the complexity and risk profile of the task:

Pattern Name Agent Roles Included Best Used For Risk / Cost Profile
Pairing Pattern Implementor + Reviewer Everyday feature development, UI components, API endpoints Low Cost / Fast Execution
Adversarial Triad Implementor + Adversarial + Reviewer High-risk business logic, financial transactions, auth workflows Medium Cost / High Security
Parallel Ensemble 2 Implementors (competing) + 1 Reviewer Complex algorithmic optimization or refactoring High Cost / Maximum Solution Quality

Practical Exercises: Setting Up Multi-Agent Workflows

  1. Conduct an Adversarial Review Manually: Take an AI-generated service file from a recent feature. Prompt a separate AI chat session with the Master Adversarial Prompt:

"You are an adversarial security auditor. Find 3 ways to trigger a runtime crash, race condition, or invalid state transition in this code."

  1. Build an Adversarial System Prompt: Save a reusable system prompt file (.specify/prompts/adversarial.md) in your project repository that forces the AI agent to focus strictly on boundary failures, concurrency traps, and input validation exploits.

  2. Trace a Correction Loop: Observe how many turns it takes an Implementor Agent to fix a failing adversarial test suite compared to trying to debug the code yourself.

Next Steps

Multi-agent execution patterns ensure that code generated locally is robust, secure, and compliant. However, code must ultimately pass through continuous integration and deployment pipelines before reaching production.

In Chapter 14, we will explore Automated Verification: Test-Driven Acceptance Gates β€”learning how to wire SDD specs directly into CI/CD pipelines, construct automated contract testing suites, and block non-compliant AI output automatically.