The Pair Contract
Pair programming has a reputation problem. People think it means two people at one keyboard, one typing while the other watches. The reality is more subtle and more useful than that.
The part nobody talks about is the contract.
The implicit rules
When two entities work on the same code together — whether that’s two humans, or a human and an AI agent — there’s an unspoken set of agreements that have to hold for the collaboration to function.
The first rule: one of you holds the intent, the other holds the attention to detail. The person with intent knows what the system should do. The person with attention knows what the code actually says. These roles can swap, but they shouldn’t overlap. Two people both trying to hold the big picture means nobody is catching the typo in the loop condition.
The second rule: disagreements happen at the design level, not the syntax level. If you’re arguing about brace placement, you’ve already lost. The valuable friction is at the architecture boundary. “Should this be a callback or a signal?” “Does this belong in the module or the manager?” That’s the productive territory.
The third rule: the person who didn’t write the code explains it. If you can’t articulate what your partner just did, you don’t understand the change. And if you don’t understand the change, it shouldn’t go in.
Why most pairing fails
Most pair programming sessions collapse because people skip the contract. They sit down, start typing, and expect collaboration to emerge spontaneously. It doesn’t.
Without the implicit agreement about roles, both people gravitate toward the same task. Two people reading the same error message. Two people formulating the same fix. Two people checking if the semicolon is in the right place. That’s not pair programming. That’s a meeting with a keyboard.
The fix is explicit role negotiation. Before you touch the code, agree on who’s driving and who’s navigating. The driver types. The navigator thinks ahead. The navigator is reading the function three calls up the stack while the driver is writing the current one.
The asynchronous version
The modern version of pair programming often isn’t synchronous at all. It’s an agent writing code while a human reviews. Or a human sketching architecture while an agent fills in implementation. The same contract applies.
The agent’s strength is attention to detail. It catches the edge case, remembers the API signature, keeps the style consistent. The human’s strength is intent. They know what the system needs to become, what the user expects, what the business requires.
When this contract is respected, the output is better than either could produce alone. The human doesn’t get bogged down in boilerplate. The agent doesn’t wander into architecturally unsound territory. Each plays to their strength.
When the contract breaks — when the human stops reviewing, or when the agent stops respecting the human’s design intent — the output degrades fast. Worse than solo work, because now there’s a false sense of confidence. “We both looked at it” becomes cover for the fact that neither really examined it.
The minimum viable contract
If you’re going to pair — with anyone, on anything — establish three things:
- Who decides what to build. This is the intent holder. They make architectural calls.
- Who decides how to build it. This is the detail holder. They make implementation calls.
- How you signal disagreement. Not “I don’t like that variable name.” More like: “That approach won’t scale past ten connections.” Structural concerns, voiced early.
Everything else — the IDE, the language, the testing framework — is detail. The contract is what makes the pairing work. Without it, you’re just two cursors in the same file.