tmux for Claude Code
Course
Using tmux for Advanced Claude Code
Module 10 of 14

Contract-First Spawning

Eliminating dependency races with structured agent initialization

What you'll learn

Identify the dependency chain problem and explain why it causes integration failures
Design a contract chain for a layered architecture with explicit upstream/downstream handoffs
Write a contract-first spawning prompt and apply wave execution sequencing
Validate completed work against its contracts and diagnose common contract mistakes

The Dependency Race Problem

Silent divergence: agents assuming different schemas

When you spawn multiple agents simultaneously and ask them to build parts of a system that depend on each other, you are setting up a race condition — not in the technical concurrency sense, but in terms of assumptions. Without coordination, each agent will make independent decisions about the interfaces between its layer and the layers around it. Those decisions will almost certainly conflict.

Consider this scenario with no contracts:

DatabaseAgent decides: user_id stored as UUID (string)
BackendAgent assumes:  user_id is a numeric integer
FrontendAgent expects: userId as a camelCase string field

All three agents:
  ✓ Write code that compiles
  ✓ Pass their own unit tests
  ✓ Report "task complete" to the lead

Integration result: 💥 type errors at every layer boundary

Each agent was working correctly in isolation. The failure is not a bug in any agent's work — it is a coordination failure. The agents simply did not agree on the shape of the data that flows between them before they started building.

This is the problem that contract-first spawning solves. Instead of letting each agent make independent interface decisions and hoping they align, you define the interfaces explicitly before any implementation work begins, and you inject those definitions into each agent's context as a binding constraint.

The Contract-First Principle

"Contract-first spawning" is the term we use in this course for a pattern where upstream agents define their interfaces before downstream agents begin work. A contract, in this context, is a precise specification of the data that flows across a boundary between two agents' work. It might be a database schema, an API request/response shape, a function signature, or a file format. The key properties are:

  • It is defined before implementation starts — not discovered during integration
  • It is explicit and precise — not "handle payments" but a typed JSON specification
  • It is injected into every agent that needs it — not assumed to be known
  • It is the lead's responsibility to create and distribute — not left to individual agents

The full pattern runs in five steps:

  1. The lead analyzes the work and identifies all dependency boundaries
  2. The lead defines a contract for each boundary (schema, API spec, format)
  3. Contracts are included in the spawning prompt for each agent that needs them
  4. Agents implement against their received contracts rather than making assumptions
  5. Integration succeeds because everyone agreed up front

A Complete Contract Chain: Payment Feature

Database contract document: tables, fields, relationships, API surface

The clearest way to understand contract-first spawning is to trace it through a real example. Building a payment feature requires three layers — database, API, and frontend — with two contract boundaries between them. This is exactly the scenario where the pattern shines.

The dependency chain runs strictly in one direction:

Database → Backend → Frontend
(Backend cannot finalize its schema until Database defines it)
(Frontend cannot build its UI until Backend defines the API)

Wave 1: DatabaseAgent Defines the Schema Contract

Wave 1 — DatabaseAgent
Designs schema, writes migrations, then emits this contract:
{
  "tables": {
    "users": {
      "id": "UUID PRIMARY KEY DEFAULT gen_random_uuid()",
      "token_balance": "INT NOT NULL DEFAULT 0",
      "created_at": "TIMESTAMPTZ NOT NULL DEFAULT now()"
    },
    "purchases": {
      "id": "UUID PRIMARY KEY DEFAULT gen_random_uuid()",
      "user_id": "UUID NOT NULL REFERENCES users(id)",
      "amount": "INT NOT NULL",
      "type": "ENUM('purchase', 'refund') NOT NULL",
      "created_at": "TIMESTAMPTZ NOT NULL DEFAULT now()"
    }
  },
  "notes": "user_id is UUID everywhere. Use gen_random_uuid() not uuid_generate_v4()"
}

The contract is precise and includes the implementation notes that prevent a backend agent from making the classic uuid_generate_v4() mistake.

Wave 2: BackendAgent Receives Schema, Defines API Contract

Wave 2 — BackendAgent
Receives the database schema contract, implements API endpoints against it, then emits this contract:
# API Contract v1.0 — for FrontendAgent

POST /api/payment/purchase
  Request:  { package_id: string, quantity: int }
  Response: { success: bool, token_balance: int, message: string }
  Errors:   400 invalid_package | 402 insufficient_funds | 500 internal

GET /api/balance
  Response: { token_balance: int, last_updated: ISO8601 }

# All user_id values are UUID strings.
# All endpoints require Authorization: Bearer {jwt} header.
# Error response shape: { error: string, code: string }

BackendAgent worked directly from the database schema — it never had to guess whether user_id was a UUID or an integer, because the contract told it explicitly.

Wave 3: FrontendAgent Receives API Contract, Implements UI

Wave 3 — FrontendAgent
Receives the API contract, builds the billing UI with exact fetch calls matching the spec. No guessing about endpoints, request shapes, or error codes.

When all three agents complete, the integration works on the first attempt because every layer was built against the same explicit contracts rather than independent assumptions.

Wave Execution: Sequencing Dependent Agents

Contract-first wave execution: Database then Backend then Frontend

Contract-first spawning introduces the concept of wave execution — spawning agents in groups where each wave waits for the previous wave's contracts before beginning implementation. This is different from spawning all agents simultaneously and letting them coordinate in real time.

WAVE 1 (spawned immediately):
  DatabaseAgent
    └─ implements schema
    └─ sends schema contract to lead
    └─ transitions to idle

WAVE 2 (triggered when Wave 1 contract received):
  BackendAgent
    └─ receives: schema contract
    └─ implements API
    └─ sends API contract to lead
    └─ transitions to idle

WAVE 3 (triggered when Wave 2 contract received):
  FrontendAgent
    └─ receives: API contract
    └─ implements billing UI
    └─ transitions to idle

Wave execution looks sequential, and for strictly dependent layers it is. But it is not slow — DatabaseAgent's work typically takes 5–10 minutes, after which BackendAgent works for another 5–10 minutes, and FrontendAgent finishes in 5–8 minutes. Total wall time is 15–28 minutes for a feature that would take a single developer 2–3 hours to implement carefully.

For layers that are genuinely parallel — two backend services that don't share a database, for instance — you can spawn both in the same wave and let them work simultaneously.

The Contract-First Prompt Template

The lead's prompt to the team is where contracts are injected. Here is the template structure that ensures every agent receives what it needs:

Create an agent team for [project].

TEAM STRUCTURE:
1. DatabaseAgent: Design schema, write migrations, emit schema contract
2. BackendAgent: Implement API against DB contract, emit API contract
3. FrontendAgent: Build billing UI against API contract

KEY INSTRUCTION:
  - Do NOT start implementation until you have received your contract
  - When complete, send your contract to me IMMEDIATELY
  - Your contract is the source of truth for the next agent

CONTRACTS (injected as each stage completes):

Stage 1 Contract (for BackendAgent — inject after DatabaseAgent completes):
[DATABASE SCHEMA]
User: id (UUID), token_balance (INT), created_at (TIMESTAMPTZ)
Purchases: id (UUID), user_id (FK → users.id), amount (INT),
           type (ENUM: purchase|refund), created_at (TIMESTAMPTZ)

Stage 2 Contract (for FrontendAgent — inject after BackendAgent completes):
[API SPECIFICATION]
POST /api/payment/purchase
  Request: {package_id: string, quantity: int}
  Response: {success: bool, token_balance: int, message: string}
GET /api/balance
  Response: {token_balance: int, last_updated: ISO8601}

The "KEY INSTRUCTION" block is doing important work here. Without it, agents may begin implementation based on their prior knowledge of payment systems rather than waiting for the actual contract. The explicit instruction to wait prevents this.

When Contract-First Is Most Critical

Not every multi-agent task needs formal contracts. The pattern adds overhead — the lead spends time defining schemas and API specs that might be implicitly understood in simpler cases. Here is a prioritization guide:

Contract Priority Levels

Critical — always use contracts:

  • Cross-layer architecture changes (DB + API + Frontend)
  • New data models flowing through multiple services
  • Any work where type mismatches would cause silent failures

High — use contracts:

  • Complex integrations between systems with defined boundaries
  • Timing-sensitive data flows (webhooks, events, queues)
  • Any work that will be difficult to refactor after the fact

Medium — optional but helpful:

  • New features in an established architecture with documented patterns
  • Integration points that are already well-specified in existing code

Low — skip contracts:

  • Single-agent tasks with no peers
  • Purely independent work (code review, documentation, analysis)
  • Agents working in completely isolated parts of the codebase

Structured Plan Format

For complex projects, the lead can produce a formal structured plan before spawning any agents. This plan makes the dependency chain and contracts explicit in a machine-readable format that the orchestrator can use to automate wave sequencing:

{
  "objective": "Add payment processing",
  "team": [
    {
      "role": "DatabaseAgent",
      "responsibility": "Define schema, create migrations",
      "dependencies": [],
      "contract_deliverable": "Schema contract (tables, types, constraints)"
    },
    {
      "role": "BackendAgent",
      "responsibility": "Implement payment API endpoints",
      "dependencies": ["Database schema"],
      "contract_deliverable": "API specification (endpoints, types, errors)"
    },
    {
      "role": "FrontendAgent",
      "responsibility": "Build billing UI",
      "dependencies": ["API endpoints"],
      "contract_deliverable": "Working UI integrated with API"
    }
  ],
  "contracts": [
    {
      "stage": 1,
      "deliverable": "Database Schema",
      "recipients": ["BackendAgent"]
    },
    {
      "stage": 2,
      "deliverable": "API Specification",
      "recipients": ["FrontendAgent"]
    }
  ]
}

A custom /build skill can parse this format to extract the dependency graph, generates wave groups, and automatically injects each contract when the upstream agent marks its deliverable complete.

Contract Validation at Synthesis

After all agents complete, the lead's final responsibility is validating that the implementation matches the contracts. This is the check that catches any drift between what was agreed and what was built:

Lead performs integration validation:

1. Frontend API calls match Backend endpoints?
   - POST /api/payment/purchase ✓
   - GET /api/balance ✓
   - Error handling uses agreed codes ✓

2. Backend database operations match schema?
   - user_id referenced as UUID everywhere ✓
   - token_balance field name consistent ✓
   - Using gen_random_uuid() not uuid_generate_v4() ✓

3. Data formats consistent across all layers?
   - user_id is UUID string end-to-end ✓
   - Timestamps as ISO8601 strings ✓

4. End-to-end test: purchase flow completes without errors ✓

All contract checks passed. Integration successful.

This validation step is not optional. Even with contracts, agents sometimes make small divergences — a field name that shifts from token_balance to tokenBalance between layers, or an error code that one agent forgot to handle. The validation catches these before they reach testing or production.

Common Contract Mistakes

Most contract-first failures come from three patterns. Knowing them in advance makes them easy to avoid.

Mistake 1: Contracts Too Vague

Bad:  "The backend will handle payments"
Good: POST /api/payment/purchase
      Request:  { package_id: string, quantity: int }
      Response: { success: bool, token_balance: int }

A vague contract gives the downstream agent almost as much freedom to make assumptions as having no contract at all. Every field name, type, and endpoint path should be explicit.

Mistake 2: Defining Contracts Before Research

Bad:  Define API contracts before reading the existing codebase
Good: Research first → discover patterns and constraints
      → define contracts based on findings
      → spawn agents with informed contracts

A contract written without knowledge of the codebase will likely conflict with existing patterns — naming conventions, error handling styles, authentication mechanisms. Always research first, then define contracts from what you learn.

Mistake 3: Not Injecting the Contract

Bad:  "BackendAgent, implement the API. The database schema
       was defined by DatabaseAgent."
Good: "BackendAgent, implement the API against this schema:
       [full schema text included in the prompt]"

Telling an agent that a contract exists is not the same as giving it the contract. The contract must be included verbatim in the agent's prompt. Do not assume an agent can retrieve it from the task list or infer it from prior messages — include it explicitly every time.

Token Cost of Contract-First

Adding the contract phase to a session costs tokens, but the rework it prevents almost always costs more. A rough accounting for a typical three-layer feature:

  • Contract definition (lead): +5,000 tokens
  • Contract injection per agent: +1,000 tokens each (~3,000 total)
  • Validation pass (lead): +2,000 tokens
  • Total contract overhead: ~10,000 tokens

Compare this to the cost of a failed integration: the lead must diagnose the mismatch, potentially re-run one or more agents with corrected context, and re-validate. A single failed integration round typically costs 20,000–50,000 tokens in rework. Contract-first pays for itself the first time it prevents a failure.

The 10,000-token upfront investment in contracts eliminates the 30,000-token rework cost when integration breaks. This is always the right tradeoff for layered architecture work.

Knowledge Check
I can explain the dependency race problem and why simultaneous spawning without contracts causes integration failures
Given a three-layer architecture, I can design the contract chain, identify the wave groups, and write each contract with appropriate precision
I know the three common contract mistakes and how to avoid each one in my prompts
I can perform a post-execution contract validation and identify the checks that confirm integration success