BoardSeat gives every GitLab merge request a board meeting. Five AI advisors argue from your real usage, tickets and sales, and every verdict ships with a bet you can check later

Site: boardseat.dev · Repo: gitlab.com/…/monte · Live Example App on GCP: monte-boardseat.cloud.run

Inspiration

As a solo founder, and I've always added too many features even before AI. Now with coding agents, I can create all the features I ever thought of!

But... that hurts the business. Every feature is something to maintain, support and explain, and most of them never get used. On a team, someone pushes back. As a solo founder, nobody does.

CI pipelines were built for teams pushing code into one repo. Now the ones pushing code are my agents. What I need is a board that thinks like a CEO, a CTO, a CFO, CS, and makes me work for every feature: show the evidence, name the bet, say what happens if it misses.

That way I keep a great product that people actually use, and pay for!

To build and demo it, I invented Tim, a solo founder who has my problem. Then I built Tim a real app, Monte, record-keeping software for Montessori schools. It has the parts a real product has: features, usage tracking, mock sales, mock support tickets and cancellations. All of it feeds the board, so the board argues from numbers, the way I'd actually run it.

Meet Tim

What it does

BoardSeat.dev is an AI board of directors that reviews every merge request against the business, not just the code.

Meet the Board

There are five seats, plus one agent on call:

  • Chair runs the meeting. It goes first, checks the evidence, calls the seats it needs and gives the verdict.
  • CEO asks whether the change will win, keep or upgrade a customer.
  • CTO asks what it will cost to maintain and how many features we're already carrying.
  • CFO asks what it costs per customer and whether the plan still makes a margin.
  • CS asks whether it answers real tickets, or whether a help article would fix it instead.
  • Chicken Little only shows up when you tag it. It lists everything that could go horribly wrong, each with an early warning sign and an exit.

How it works

A meeting works like this:

  1. Tim opens a merge request with the Feature template. It asks for evidence (tickets, usage), a bet (target and date), the cost and an exit if the bet misses. The template invites the board as reviewers.
  2. The Chair checks every claim against the files on main. No evidence means no meeting: the MR gets board::needs-evidence. Otherwise the Chair calls only the seats this change needs.
  3. Each called seat posts one position (Support, Concern or Block) and cites ticket IDs and files.
  4. The verdict goes on the record as a board:: label, and a decision file is committed with the code. If the change ships, the Chair files a GitLab task with the bet and a due date. When that date comes, the Chair checks the numbers itself and opens a keep, fix or remove MR.

Tim still decides. He can argue with a seat, override the board or merge anyway. The board just makes sure he does it with the facts in front of him.

The board never read Monte's database.

Every night a scheduled pipeline exports the live app's numbers into business/ on main (usage.md, feedback.yml, sales.md, customers.yml, costs.md), and those files are the only facts the board reads.

How I built it

Under the hood

The board runs on the GitLab Duo Agent Platform. Each seat is its own Duo flow with its own service account, prompt and files. The five seat flows start at once when the Feature template assigns them as reviewers; Chicken Little starts only when someone tags it.

They take turns through the MR thread: the Chair leaves a hidden routing marker naming the seats it called, and each seat waits for its turn with a small wait.sh script that polls the thread. Seats read facts from main and look at the MR branch only for the diff. Each seat is also a read-only Duo Chat agent, so you can ask a seat questions outside a meeting.

I created and updated every flow through GitLab's GraphQL API (aiCatalogFlowCreate, aiFlowTriggerUpdate), wrapped in pnpm board:publish, so the prompts live in the repo and change through MRs like everything else.

Monte is a Next.js app on GCP Cloud Run with Firestore. Schools get a guide, office admin and head-of-school view, and Monte's founder gets an HQ dashboard for usage, tickets, sales and pricing. track() records usage only inside the server code that did the work. A seeded simulator plays eight schools, so the numbers move even when nobody is visiting, and real visitor clicks count too. Pricing lives in business/pricing.yml, so a price change is itself an MR the board reviews.

CI/CD runs on GitLab. Every MR runs lint, typecheck, unit tests, the store contract tests against a Firestore emulator and a Docker build that boots the image. Merges to main deploy to Cloud Run through Workload Identity Federation, so CI holds no Google key. A board-verdict job fails Feature MRs until they carry a verdict label.

DevSecOps stages it touches

  • Plan: the Feature MR template asks for evidence, a bet, the cost and an exit before the board meets. The Chair files every bet as a GitLab task with a due date.
  • Create: the board reviews each merge request in the MR thread and commits a decision record with the code.
  • Verify: every MR runs lint, typecheck, unit tests, the Firestore contract tests, a Docker build that boots the image and checks the main pages, and the board-verdict check.
  • Package: CI builds and boot-tests the container image, and the deploy stores it in Google Artifact Registry.
  • Secure: SAST, secret detection and dependency scanning run on every MR and on main.
  • Release: a merge to main deploys to Cloud Run with no Google key in CI.
  • Monitor: a nightly pipeline exports the live app's usage, tickets and sales into business/ on main. When a bet comes due, the Chair measures it and opens a keep, fix or remove MR.
  • Govern: every verdict is a decision record in decisions/, with the seats' positions, the evidence and the bet, and CI fails a Feature MR's pipeline until the board has given a verdict.

It doesn't touch Configure: there's no infrastructure-as-code or environment configuration management beyond the deploy job.

BoardSeat.dev is the product site, built with Next.js and Tailwind, with the demo video and a full walkthrough of a real meeting.

What I built

Challenges I ran into

  • Agents can't call agents. My first design had the Chair @mention the seats. That doesn't work: only human actions trigger a flow, and the start_flow tool returned a permissions error. So every seat became its own flow, all triggered at once, and they coordinate through markers in the MR thread instead.
  • Making fake data believable. A board arguing from made-up numbers is pointless. That's why Monte is a working app with a simulator and a nightly export, not a slide with numbers on it.

Accomplishments that I am proud of

  • The board said no. On !11, a sticker chart with confetti, the CEO blocked it because nobody had asked for it, the CTO said the bet couldn't be measured, and CS blocked it with ticket FB-031: parents wanted less screen time. That's the pushback I've never had as a solo founder.
  • The bet loop closes. A feature ships with a dated bet, the nightly pipeline lands the numbers on main, and that pipeline triggers the Chair to check due bets and open a keep, fix or remove MR. Nobody has to remember to look.
  • Monte is a real app you can click through, and your clicks become data the board reads.

What I learned

Writing down the evidence and the bet before building changes what I build. Some ideas don't survive the template, before any agent runs.

Agents give better answers when you limit what they can see. Pointing the seats only at the business files, and making them cite ticket IDs, turned vague opinions into positions I could argue with.

On the platform side, I learned how Duo flows actually trigger, what a Developer can do through the API, and that an MR thread works well as a shared meeting room for agents that can't call each other.

Built With

Share this project:

Updates

Submission history