Inspiration
We code with AI agents now, and so does everyone else at this hackathon. Parag uses Claude Code and Carter uses Codex. The first time we split a project between them, we hit a bug git couldn't see: one agent's backend returned userId, the other agent's frontend read user_id. Both files merged cleanly. The app just showed undefined.
Git merges code. Nothing merges intent. Each agent has its own context window and has no idea what the other one decided. Add more people and it gets worse fast: with $n$ agents, the number of pairs that can drift apart is
$$\binom{n}{2} = \frac{n(n-1)}{2}$$
Four teammates means six separate ways to disagree. We wanted one source of truth that every agent checks against, so coordination grows with $n$, not $n^2$.
What it does
theChair is a shared ledger of API contracts with a team chat on top.
- Main chat. The team plans together with an AI. When you agree on a shape ("login returns userId and token"), the AI drafts it as a contract card, and a human clicks Approve.
- Before the code is written. Each agent connects through an MCP server with three tools:
get_contracts,preflightandpropose_contract_change. For Claude Code, a PreToolUse hook goes further. It extracts the API shape from the proposed edit itself and blocks the write if it breaks a contract, with the exact field and the fix. - After the push. For agents that can't be gated, a GitHub webhook extracts shapes from the changed files and diffs them against the ledger. Any conflict appears in the main chat as a card with the file, the line, a plain-English explanation and a suggested fix.
- One-click fixes. Approving a fix or a contract change commits the new contract and rewrites
AGENTS.md, so every agent starts its next session from the updated truth.
How we built it
- Dashboard and API: Next.js, with Supabase (Postgres plus Realtime) as the ledger, so chat messages and conflict cards show up live on both screens.
- Main chat:
gpt-oss-120bon Groq, with apropose_contracttool for turning conversation into structured contracts. All model calls go through one adapter, so switching to Gemini or a local Ollama model is a one-line env change. - Shape extraction: Gemini 3.8 Flash with a strict JSON schema, cached by commit SHA. A deterministic extractor for Express handlers and
fetchcalls runs as the fallback when Gemini is slow or down. - Diff engine: Pure TypeScript, no AI. It normalizes names (
userId≈user_id≈UserID) and paths (/users/:id≈/users/${id}), and only blocks on exact contract mismatches. Everything fuzzy is a warning. - Agent integration: A stdio MCP server for Claude Code and Codex, a Claude Code PreToolUse hook, and a GitHub push webhook.
We split the repo by ownership from the first hour and froze a shared interface (shared/types.ts) before writing anything else. Parag owned the engine, server, MCP server and hook. Carter owned the dashboard, webhook, extractor and demo app. [Did you run theChair on itself during the build? If so, one or two sentences here about a real conflict it caught between your two agents.]
Challenges we ran into
- We can't read the agents' minds. Our first idea was AIs that watch each other's chats. Claude Code and Codex don't expose their conversations, so we switched to checking what agents do (the edits and pushes they make) against what the team agreed.
- Not every agent can be stopped. Claude Code supports hooks that run before every edit, so we can block it deterministically. Codex can't be gated the same way, so we catch its mistakes at push time instead. Two agents, two enforcement points, one ledger.
- LLMs aren't referees. An AI deciding whether code is "compatible" gives different answers on different runs. We kept the AI for the jobs it's good at (reading messy code, explaining conflicts, drafting contracts) and made the verdict itself deterministic and testable.
- Free-tier limits. Gemini's free Flash quota was too small for a chat we'd hammer all weekend, so the chat runs on Groq and Gemini only handles extraction, behind the SHA cache.
- [The worst bug or integration problem you actually hit overnight.]
Accomplishments that we're proud of
- The hook blocks a contract-breaking edit inside Claude Code's own terminal, before the bad code ever exists.
- The webhook catches Codex's mismatch, with the file and line number, before anyone merges.
- [A real number if you have one, e.g. how many conflicts it caught during your own build.]
What we learned
- Agents read instruction files like
AGENTS.mdat the start of a session, not on every turn. Keeping agents in sync takes a live channel (MCP), not just a file in the repo. - Advice isn't enforcement. An agent told to call
preflightoften won't. The parts that hold up are the hook and the webhook, which run whether the agent cooperates or not. - Agreeing on interfaces up front makes parallel work possible, for people and for AIs.
What's next for theChair
- Contracts beyond HTTP: database schemas, shared types and event payloads.
- Gating for more agents as their tools add hook support.
- A fully local mode (Ollama plus a self-hosted ledger) for teams whose code can't leave the building.
Built With
- claude-code
- codex
- css
- gemini
- github
- github-actions
- github-webhooks
- groq
- hmac
- llama
- mcp
- model-context-protocol
- next.js
- node.js
- ollama
- pglite
- postgresql
- react
- sharp
- supabase
- tsx
- typescript
- vercel
- zod
Log in or sign up for Devpost to join the conversation.