A social media platform staffed by agents instead of features. A director and eight specialists hold the community, the triage, the analytics, the plan, the copy, the art, the video, and the outreach, and every one of them works on read-only credentials. Exactly one write path exists and it runs through your approval queue. Roughly 113k lines, a third of it tests, 312 commits in seven weeks, one person. Unreleased, closed source, no domain yet.
Year2026StackProduct · Agents · Orchestration · Security · Design system
WireframeShipped
Drag the seam · wireframe ↔ shippeddesigned and built by one person
FIG.Measured Render
The UI, measured. The shipped screen, drawn to its own griddesigned and built by one person
A measured render: the same screen you ship, drawn as a technical drawing. Every number is a constraint someone has to hold. That is why a simple screen is so hard to build.
A whole social media team, running as software
Most tools in this category sell you a box to type in and a calendar to drop it on. The work that actually eats the week is the part nobody automated: reading the mentions, deciding what deserves a reply, planning a month, writing in a voice, briefing the art, chasing the outreach.So Choir is not a feature list. It is a staffed team. A Director agent and eight specialists hold those jobs, they hand work to each other, and a person keeps the last word on anything that leaves the building. Hire the team. Keep the veto.It is unreleased. Closed source, decided rather than pending, and no public domain yet. Everything below is built and running.
1, A staff page, not a settings pane
The roster reads like the team page of an agency, because that is the mental model the product is asking for. Community, triage, analytics, planner, copywriter, art director, video, outreach. Each one has a job, a scope, and a face, and the Director is the one that routes work between them and reports back.That framing is not decoration. It decides what a person has to hold in their head. You do not configure eleven automations, you tell a team what you want this month, and the team argues it out among themselves before anything reaches you. The landing page counts the whole thing out in four numbers, and the fourth one is the promise:01 director · 08 specialists · 03 approval modes · 00 unsanctioned sendsThe page signs off in the same register:// built by agents. reviewed by humans. in that order.
2, Exactly one write path
Every specialist holds read-only credentials over four surfaces, and there is exactly one way for anything to get out. The four are the Brand Bible, the calendar, the inbox, and analytics. Agents read all of them freely and write to none of them. The single write path runs through the approval queue, and it is the only door in the building.
Exactly one write path exists, and it runs through your approval queue. That is an architecture, not a promise.
The difference matters because a promise is a sentence in a marketing page and an architecture is a thing that fails a build. The write path is covered by tests that assert the negative case: given a specialist, given a live connection, given a draft it wrote itself, nothing leaves. A capability that cannot be demonstrated to be absent is not absent.FIG. 02 · The queue. One door, and a person on the handle.
3, Three modes, and the floor none of them unlocks
Autonomy is a dial with three positions: approve every action, approve the plan, or accept edits after the fact. That covers the honest range of how much a brand trusts a new hire in week one against month six, and it is set by the person, not inferred from behaviour.Underneath the dial there is a floor. Spam signals and complaint signals are checked before any autonomy level applies, which means the most permissive mode is still standing on the same guard as the strictest one. No setting anywhere in the product unlocks past that check. A dial that can be turned far enough to cause harm is not a dial, it is a trap with a label on it.
4, A brand voice with version history
Agents do not edit the Brand Bible. They propose diffs to it, and a person merges. The copywriter learns that the brand says customers and not users, the community specialist learns which complaints get an apology and which get a link, and both of those arrive as a proposed change with a before and an after, sitting in a gate.Memory that writes itself is memory nobody can audit. This one has a merge gate, so the voice has a history: who changed it, when, and what the line said the day before. Your brand voice has version history, not vibes.FIG. 03 · Compose. The draft is the agent's work. The signature is not.
5, The agent surface is the product surface
Sixteen typed tools are exposed over the open protocol agents already speak, so the product is usable by an agent that was not built by me. Channels, calendar, drafts, scheduling, inbox, conversations, previews, capabilities, analytics. The same catalog runs two ways: as a local process on your own machine, and as a hosted endpoint sitting behind a full authorization server with dynamic client registration and a consent screen, so a third-party agent can be granted access without anyone pasting a key into a chat window.One rule shapes the whole catalog. The workspace is ambient, never a tool argument. An agent cannot name a workspace, therefore an agent cannot name someone else's, and the entire class of "it addressed the wrong account" bugs stops being possible rather than being tested for.FIG. 04 · The assistant. It gets the same sixteen tools an outside agent gets, and the same gates.
6, The tool I did not build
There is deliberately no tool for sending a direct message, and the catalog documents why. Platform review for that permission is not cleared. A tool that is listed, called, and then fails for every real user does not just fail once. It teaches the agent that this catalog lies, and after that it stops trusting the fifteen tools that work. Better a short honest catalog than a long one with a hole in it.Two more gates sit in the same file. An agent cannot approve its own draft, which is the difference between a queue and a formality. And scheduling rejects any time in the past, because a schedule that accepts yesterday is a publish button wearing a disguise. Nothing gets to reach the world by pretending it already had.
7, Tenancy the database enforces, credentials it hands over late
Separation between workspaces is enforced by the database itself, under a role that cannot bypass it, not by a filter somebody has to remember to add. Row-level policies decide what a query can see. The application connects as a non-superuser precisely so that the policies are not advisory. One forgotten clause in one query is the classic way this goes wrong, and the fix is to put the rule underneath the queries rather than inside each of them.Credentials live in an envelope-encrypted vault and are revealed just in time at publish, then let go. The publish pipeline itself is three phases, claim, dispatch, and settle, with a per-account delivery ledger that makes a retry exactly-once for a given connection instead of hopefully-once. A reaper sweeps dispatches that were interrupted mid-flight, because the one thing worse than a post that failed is the same post twice.Around all of it, adversarial hygiene runs on a schedule. A prompt-injection evaluation harness runs nightly in the build, red-team cases cover poisoned output coming back from a platform, and quarantine and cost-guard processors sit in the path. The write path holds when the input is honest. The tests are there for when it is not.
8, The design system I threw away, and the arithmetic that replaced it
The first system drew elevation with shadows and structure with borders, and I could prove it was broken. The page field was one off-white and a card sitting on it was another, five sRGB code values apart, in the most compressed stretch of the transfer curve. That card only ever read as a card because a shadow was drawn underneath it. On a cheap panel the step disappeared entirely. That is not a taste problem, it is a quantisation defect, and a taste argument cannot fix it.So the fix is arithmetic. The replacement system is called Lattice and it runs on two of them: a tonal lattice of seven calibrated lightness stops one arithmetic step apart, and a spatial lattice on a 4px grid. Every surface in the product is a position on the tonal ladder rather than a colour somebody picked, no structural step is ever thinner than 8 code values, and the floor is derived from what cheap panels can actually resolve rather than from what looks fine on mine.The thesis is one sentence: contrast rises monotonically toward the data. Chrome sits one stop below the page field, panels sit one stop above it, so scanning the screen means riding a gradient that points at the work. That gradient is the elevation system, which is why the system can afford its own law.
Flat. Zero shadows, zero gradients, no glass, no serif, no circles, and no outline on a card.
Three commitments come out of it. The number is the hero: every numeral is monospaced, tabular and slashed-zero, and the largest type on any page is a digit rather than a heading, because prose is not the job. A line is a gridline, never a box: rules run edge to edge so the eye can measure across a column, and they never close into a rectangle, so there are no outlined cards. And colour is state, never finish: the field is near-achromatic, one accent and three status hues carry the chroma, and resting states spend none of it. A budget of six accent clusters per screen, countable.I did not arrive at it by taste either. Five design directions were built out and judged by three fixed perspectives, an operator, a craft critic, and an accessibility engineer. One won on architecture and absorbed the best of the others. Migrating to it caught six defects the old system had been hiding, all measured rather than eyeballed, including a switch knob sitting at 1.22 to 1 against its own track, now 5.54, and a z-index scale that was defined and then ignored until a popover rendered underneath a menu.Readers of this site will notice the argument is the same one I make here in a different accent, with one honest divergence: this portfolio is editorial and Lattice bans the word outright. A war room is not a magazine.FIG. 05Four console surfaces01 / 04
The roster
A director and eight specialists, read as a staff page rather than a settings pane.seven stops · zero shadows
Four tabs, four captures. Chrome one stop below the page field, panels one stop above it, gridlines instead of boxes, and colour spent only on state.
FIG. 06 · The week, planned. Nothing on this grid publishes without a signature.
9, A canvas where the caps are code
Fourteen node kinds, laid out automatically, covering the shape of a real automation rather than a demo of one. Comment, direct message and mention triggers. Keyword matches, frequency caps, approval gates, delays, time and tag conditions. Reply, message, notify and tag actions, and a node that simply hands the job to an agent.The comment-to-message automation is the one everybody ships badly, so it carries a real consent handshake: the person has to ask before anything lands in their inbox, the window is twenty-four hours, and the frequency caps are enforced in code, not in a prompt. A cap written into an instruction is a suggestion to a model. A cap written into the runtime is a cap.
10, What is true today, said out loud
Fifteen channel kinds live in a capability registry, read at the call site, never hardcoded. One end of that range allows 280 characters and the other allows 63,206, and the composer, the validator and the preview all ask the registry rather than carrying a copy of the answer. Adding a channel is a registry entry.Two of those platforms have real adapters wired to a real network today. The rest are simulated, and the status page says so, in a legend with three states: real and wired, real but simulated, gated. Keeping that legend truthful is what makes the page worth reading, because it is the bridge between what is built and what is claimed.The rest of the shape, for scale: roughly 113k lines with about a third of it tests across 125 test files, 155 endpoints over 33 controllers, 39 migrations, 16 agent tools, 15 channel kinds, 14 node kinds, 312 commits in seven weeks, one person. There is also a relay for anyone who would rather not send their traffic through me: a small daemon on your own machine answers the model calls with your key or your local model over an outbound socket, while the tools still execute server-side under the same gates. Your model, my guardrails.
What it demonstrates
Layer
What I did
Product
A staffed-team model instead of a feature list, a director and eight specialists with real jobs, three approval modes over a floor that none of them unlocks, and a tool catalog with a documented honesty gate
Trust
Read-only credentials over four surfaces, exactly one write path through an approval queue, no self-approval, no past-dated scheduling, and a status legend that says which channels are real
UX / Design
A flat system derived numerically: seven calibrated tonal stops, contrast rising toward the data, gridlines instead of boxes, colour spent only on state, and a roster read as a staff page rather than a settings pane
Engineering
Tenancy enforced by the database under a non-superuser role, an envelope-encrypted vault revealed just in time, claim to dispatch to settle with an exactly-once delivery ledger and a reaper, and a nightly prompt-injection harness in the build
Interoperability
Sixteen typed tools over the open protocol agents already speak, local and hosted, behind a full authorization server with dynamic client registration, plus a relay that answers model calls from the user's own machine
The seam
The sentence on the landing page, the gate in the tool catalog, and the test that proves the gate are one decision held in three places by one person
Role: Product, design, and engineering, end to end. Timeline: 2026 · Unreleased. Three weeks of build, a Menyo project, closed source.A team is not a prompt. It is nine jobs, four surfaces read, and one door that only a person opens.