Bridge: designing a command deck that agents report into

When coding agents write most of the code, the founder's bottleneck becomes decisions. How Bridge is designed around a typed generative-UI contract, an MCP check-in protocol and tiered approvals, and what is actually built so far.

Status, plainly: Bridge is an early prototype. The chat shell described below runs on sample data with a rule-based stand-in for the agent. The MCP server, action gateway, passkey approvals, audit log and cost ingestion are designed in detail but not built. We label each piece as we go.

The problem

When Claude Code, Codex and similar tools do most of the implementation, typing stops being the constraint. The founder becomes the bottleneck for decisions, and the state of the build is scattered across plan documents, agent sessions, issue trackers and cloud consoles. The design goal we wrote down is blunt: nobody should have to read five markdown files to know what exists.

Bridge is meant to be the thing those markdown files were trying to be. Agents read it before they start and write to it when they stop. The founder asks questions in chat and sees answers drawn on screen. Anything that changes the world waits for an approval whose strength matches the risk.

Architecture at a glance

Bridge architecture, built and plannedThe founder talks to the comms console. Today a mock agent returns typed replies that the viewscreen renders. Planned: an LLM agent with a spend cap, tiered approvals feeding an action gateway with scoped short-lived credentials, a Bridge MCP server that coding agents report into, Postgres with row-level security, ingest from GitHub and cost sources, and an append-only audit log.Built · sample dataDesigned · next phasesFounderbrowser · passkeyComms consolechat · chips/api/chatmock agentViewscreenwidget rendererAgentReply contractmessages · view.widgets[] · approvalsame contractBridge agentsmall model · hard $ capApproval tiers0 read · 1 yes · 2 passkeyCoding agentsClaude Code · CodexAction gatewayscoped, short-lived accessBridge MCP serverread · start_run · report …Project servicespause · deploy · rotatePostgres + RLSorg → projectAppend-only auditevery turn & approvalIngestGitHub app · cloud & AI spend · Pulse telemetry
Solid boxes run today on sample data. Dashed boxes are designed in the spec and not yet built. Tap to zoom.

What runs today: a typed generative-UI shell

The shell is a Next.js 15 App Router app on React 19 and TypeScript, deliberately with almost no other dependencies. The page keeps a message list and a current view, and posts each chat turn to a single route handler, /api/chat. That route calls the agent and returns an AgentReply:

type AgentReply = {
  messages: string[];     // what Bridge says in chat
  view?: View;            // what it draws on the viewscreen
  approval?: Approval;    // a card that must be answered
}
type View   = { title: string; filters?: string[]; widgets: Widget[] }
type Widget = stats | table | bars | placeholder   // a closed union

The important decision is the closed widget union in src/lib/types.ts. The agent can't emit arbitrary HTML or invent a page; it can only describe a view as a list of known widget kinds (stat tiles with optional cap meters, toned tables, bar charts). New visuals are added as new widget kinds, never as new pages. That keeps the interface safe to drive from a model, easy to test, and lets the stand-in agent and the future model share one contract.

Today the agent is mockAgent.ts: intent matching over sample data for tasks (with project aliases, P0–P3 priorities and key:value label filters), costs, overviews, ideas and action verbs. Verbs map onto approval tiers, and the console renders an approval card. Approving in the prototype only records that nothing was executed. The passkey button is a placeholder for WebAuthn.

The protocol: agents as first-class reporters

The design doc says it best: without the agent protocol, Bridge is just a very good dashboard. The plan is a Bridge MCP server that coding-agent sessions connect to with a per-project token, exposing seven tools:

Agent run lifecycle over MCPA coding agent reads project state, starts a run, sends heartbeats, reports what moved and finishes the run. A run without a heartbeat for two hours is flagged stale.bridge.readproject state as Markdown/JSONbridge.start_runagent · task → run_idbridge.heartbeatstale after 2h of silencebridge.reportcomponents moved · tasks closedbridge.finish_runoutcome recordedrepeat
The planned Bridge MCP protocol. bridge.measure and bridge.decide sit alongside it. Tap to zoom.

Two rules make the data trustworthy rather than self-reported:

  • State is measured, not typed. A component can only be marked as existing when its paths point at real files in the repo. bridge.measure recounts source and test files per component, so "done" is checkable.
  • The code wins. Repo docs govern behaviour, Bridge governs status and shape, and if an export disagrees with the code, the code is right. Exports given to agents are framed as data, not instructions, so they can't be used to smuggle commands into a session.

Fallbacks are planned for agents that can't speak MCP: a BRIDGE.md export, a GitHub app that logs runs from pull requests and re-measures on push, and a small CLI.

Approvals and the action gateway (designed)

Actions are tiered. Tier 0 is reads and needs nothing. Tier 1 is reversible (pause, resume, scale) and needs a "yes" in chat. Tier 2 touches money, production or deletion (deploys, key rotation, deletes) and needs a "yes" plus a fresh passkey tap. Agents never hold raw credentials: every action goes through a typed gateway that checks the tier, waits for approval, and then uses narrowly scoped, short-lived access for that one action. A single command revokes every agent permission. Every request, chat turn and approval goes to an append-only log stored apart from the app itself.

Costs under one label system (designed)

Bridge plans to put cloud bills, AI API spend and revenue on one ledger under the same labels used for tasks and agents, so "what did area:ai cost this month?" is a chat question. One idea we like is shadow cost for flat-rate AI subscriptions: estimate the per-project cost from session token counts at list price, sent by a small local relay that transmits numbers only, never code or conversation.

Where it came from

Before the Next.js shell, Bridge existed as a single-file HTML prototype used during Lifekeep's development. It had an auto-laid-out C4 system map (context, container and component levels via dagre), a "Vision vs Today" toggle that hides planned components, a workflow player that animates a pulse along real edges of the map, a per-user cost model mirroring a spreadsheet (including prompt-cache and batch pricing), and a Markdown exporter that emits the whole state with a Mermaid diagram. Those pieces are being ported into the shell as widget kinds.

Stack

LayerBuiltPlanned
UINext.js 15, React 19, TypeScript, CSS tokensPWA and push, C4 map and mission widgets
AgentRule-based stand-in behind /api/chatSmall Claude model with prompt caching and a hard spend cap
DataStatic sample modulePostgres with row-level security (org → project), Drizzle
Agents in—Bridge MCP server, GitHub app, CLI fallback
Auth—Passkeys (WebAuthn), roles: owner, operator, viewer

What's next

The first real milestone is "the loop": database tables for the object model, an importer for the prototype's data, and the MCP server, so a real agent session can read Bridge, report back, and have the change show up on screen. Bridge is also planned as the front door to Forge OS, sharing its vocabulary of projects, release boundaries and gates. See how the products fit together.

See Bridge All posts