These are my personal thoughts based on what I've been experimenting with in my day-to-day work. I'm not claiming this is the perfect way — I'm sharing what works for me and I'm genuinely open to hearing what you think, what I'm missing, and how you approach this differently.
The Problem Nobody Talks About
Everyone is excited about AI agents. You give them a task, they go build it. Sounds great.
But here's what actually happens when you build something real — like a fullstack AI chatbot SaaS:
You launch an agent to build the chat UI. Another to handle message history. Another for authentication. Another for the AI response backend.
And then they start waiting on each other.
The frontend agent pauses because it doesn't know what the API response looks like. The auth agent blocks the chat agent. The AI backend agent makes assumptions about the input format that don't match what the frontend sends.
You end up with agents that are technically "parallel" but practically sequential. Half your time is spent fixing mismatches between what one agent produced and what another expected.
I've been thinking about this problem for a while. And I came up with a practice I call Contract-Based Design.
What is Contract-Based Design?
The idea is simple.
Before any agent writes a single line of code, one agent does one job only: understand the full requirement and define the contracts.
A contract is a small .md file that defines exactly:
- What goes in (input)
- What comes out (output)
- What the boundaries of this piece are
Once every piece has a contract, every agent has everything it needs to work completely independently — without waiting, without assuming, without breaking each other.
A Real Example: Building an AI Chatbot SaaS
Let's say the task is: build a fullstack AI chatbot SaaS with user auth, chat UI, message history, AI responses, and user settings.
Without contracts, this is a mess. Every piece touches every other piece. Agents block each other constantly.
With Contract-Based Design, here's what happens:
Phase 1 — The Contract Definition Phase
Before launching any implementation agent, I first instruct one agent to do only this:
"Understand the full requirement. Divide all tasks. For tasks that can be independent, define them clearly. For tasks that depend on others, define the exact input and output so they can still run in parallel."
That agent produces a contracts folder:
/contracts
auth.contract.md
chat-ui.contract.md
message-history.contract.md
ai-response.contract.md
user-settings.contract.md
Click to see example contract files
auth.contract.md
## Auth Contract
INPUT:
- token: string (JWT)
OUTPUT:
- userId: string
- role: "admin" | "user"
- error?: string
BOUNDARIES:
- Does not handle session storage
- Does not communicate with chat or AI modules
ai-response.contract.md
## AI Response Contract
INPUT:
- context: Message[] (last 10 messages)
- prompt: string
- settings: { model: string, temperature: number }
OUTPUT:
- response: ReadableStream
- error?: string
BOUNDARIES:
- Does not fetch message history
- Does not handle auth
- Streams response, does not buffer
message-history.contract.md
## Message History Contract
INPUT:
- userId: string
- limit: number (default: 10)
OUTPUT:
- messages: { role: "user" | "assistant", content: string, timestamp: ISO8601 }[]
- error?: string
BOUNDARIES:
- Does not call AI
- Does not handle auth
- Read-only, does not write messages
Phase 2 — Parallel Launch
Once the contracts exist, I launch all agents simultaneously:
| Agent | Task | Depends On |
|---|---|---|
| Agent 1 | Build Chat UI component |
chat-ui.contract.md only |
| Agent 2 | Build Message History API |
message-history.contract.md only |
| Agent 3 | Build Auth middleware |
auth.contract.md only |
| Agent 4 | Build AI Response backend |
ai-response.contract.md only |
| Agent 5 | Build User Settings page |
user-settings.contract.md only |
None of them wait for each other. None of them make assumptions. They each read their contract and build exactly what it says.
Agent 1 building the chat UI doesn't need Agent 4 to finish the AI backend — it already knows from the contract that the backend will return a ReadableStream. It builds against that shape.
Why This Works
The key insight is that you've separated thinking from doing.
Most people launch agents and let them figure out interfaces as they go. This creates hidden dependencies and mismatches you only discover when things break.
Contract-Based Design forces all interface decisions to be made before any implementation starts.
This is exactly how senior engineers design systems before delegating to a team. You don't tell five developers to go build five things and figure out how they connect later. You design the interfaces first, then everyone builds in parallel.
Contract-Based Design makes AI agents work the same way.
The Three Concepts I Use Together
Contract-Based Design doesn't live alone. I combine it with two other practices:
1. PRD.md Files
Before contracts, there's a product requirements document in markdown. This is the high-level "what are we building and why." The contract-definition agent reads the PRD and produces the contracts from it.
2. Spec-Based Design
Each agent gets a spec — not just a contract. The spec includes the contract plus implementation notes, tech stack constraints, and edge cases. The contract defines the interface. The spec defines the behavior.
3. Contract-Based Design
The contracts are the source of truth for all inter-agent communication. No agent makes assumptions. If it's not in the contract, it doesn't exist.
Together these three create a system where:
- The PRD tells agents what to build
- The spec tells agents how to build it
- The contract tells agents what to expect and produce
One More Thing: The Validation Step
After all agents finish, I run one final agent whose only job is:
"Check that every component's actual output matches its contract. Flag any drift."
This is the safety net. It catches mismatches before they hit production. And because the contracts are the source of truth, the validation is objective — either the output matches the contract or it doesn't.
What This Unlocks
| Without Contracts | With Contracts | |
|---|---|---|
| Execution | Sequential blocking | Truly parallel |
| Interfaces | Discovered during build | Agreed upfront |
| Debugging | Painful — where did it break? | Easy — contract shows exactly where |
| Scaling | Adding agents breaks things | Just add a new contract file |
You produce more. You compromise nothing.
Final Thought
AI agents are not slow because the models are slow.
They are slow because the system around them is not designed for parallelism.
Contract-Based Design is about building that system — so your agents can do what they're actually capable of: working fast, working independently, and producing real output without stepping on each other.
I've been using this in my day-to-day work and it has genuinely changed how I think about building with AI. But I want to be clear — this is just my current thinking. I'm still learning, still experimenting, and I'm sure there are better ways to do parts of this.
If you've tried something similar, or you think I'm wrong about something, or you have a better approach — I really want to hear it. Drop a comment. Let's figure this out together.
That's the whole point of sharing this. 🙂
sharing thoughts, not rules.
Top comments (0)