A walkthrough of the ingest pipeline, the AI extraction and orchestration layer, the decision systems, and the portal architecture — from first field input to final logged decision.
True Build OS runs a working interior design studio end-to-end: how information comes in from the field, how it becomes structured records, how work gets routed, and how decisions get made and logged.
distinct portals / surfaces, multiple identity models
background jobs call Claude for extraction, classification, suggestion
WhatsApp · Telegram · email · voice · web/QR · contracts
entity types embedded into pgvector for semantic + temporal recall
Every record, issue, task, decision, cost and approval hangs off one Project. There is a single place to ask "what is the state of this job?" — no cross-system reconciliation.
Mutations emit verbs onto an append-only event spine. The spine is the trigger surface: suggestions, notifications and embeddings all react to events rather than being wired into business logic.
Claude is not a chat feature bolted on the side. It sits inside ~15 background jobs doing extraction, classification and routing — with structured tool-use, logging and graceful fallback.
The bet: in a studio, work is information-driven (a transcript becomes tasks) rather than process-driven (step 1 must finish before step 2). So the system is an event-and-extraction engine, deliberately not a BPMN workflow tool.
How messy, real-world input from a building site becomes clean, structured, queryable records — usually without anyone filling in a form.
A chat is tied to a project via /init MZK001 — then every message routes itself.
Webhooks verify and return fast; heavy work runs in retried Solid Queue jobs.
Every record keeps its input_source and a link back to the exact message.
DocumentGenerationJob takes an unstructured transcript or email and returns a single structured object that the app commits in one transaction.
{
record_type: "site_visit_report",
summary: "…",
decisions_structured: [ {statement, decided_by,
source_quote} ],
open_questions: [ {question, raised_by} ],
new_action_items: [ {description, assignee,
due_date, task_type} ],
action_item_updates: [ {id, status, next_step} ],
action_item_closures: [ {id, resolution} ],
change_requests: [ {description, cost_impact} ]
}
Falls back to raw-JSON parsing if tool-use is unavailable. Every call is logged to AiUsageLog with tokens + cost.
The hard part of AI editing isn't generating text — it's telling the model which part to change without it quietly rewriting everything else. The studio's answer borrows from how people already mark up documents.
Walkthrough of Level 3 with the client. The contractor confirmed the marble will arrive next week; tiling to follow once the substrate is signed off.
Client approved the brushed-brass ironmongery. Electrical position on the island to move 300 mm east before second fix.
The contractorStone & Co confirmed the marble will arrive next weekon the 19th; tiling to follow once the substrate is signed off.
↳ consistency: "contractor" → "Stone & Co" also updated in Decisions and Action ItemsOnce everything is a structured fact on a shared event spine, the system can route work, suggest the next move, and capture decisions with an audit trail.
Six different entity types — action items, issues, approvals, decisions, open questions, attention alerts — all share a Ball-in-Court concern: a polymorphic pointer to whoever currently owns the next move, plus a snooze.
Most tools give each object type its own backlog. Here the operational question — what is waiting on me, ranked — is answered in one place regardless of object type.
One polymorphic ClientApproval serves three different approvable things — an FF&E item, a variation order, or a design record. The client never logs in: the secure token is the authentication.
FfeItem · VariationOrder · ProjectRecord — one model, three masters
draft → snapshot + token → email link → client approves / requests-changes → side-effect + event → confirmation back to requester (and Telegram, if that's where it began)
Seven entity types embed their text into pgvector on write. "Ask Arqis" runs one semantic query spanning all of them, assembles a context window, and has Claude answer with the project's own history.
I'll be candid on the next slide about which of these is genuinely differentiated and which is just 2024 table-stakes.
Events · Records · Issues · Action Items · Decisions · Open Questions · Contract Chunks
single query → 6 entity types → 6k-token context → Claude Haiku answer, logged
decisions_at(t) · events_at(t) · current_superseding(d) — state as-of any moment, not just "now"
Human approvals are treated as labelled data. They do two jobs: few-shot exemplars at generation time, and fuel for an offline meta-loop that proposes prompt rewrites for a human to accept. Both stay human-gated by design.
All five are live and in daily use — every portal has at least one active user right now. They sit at different stages of continuous development, but none is a prototype.
Staff. Queue, projects, records, FF&E grid, library, comms.
Approvals, brief, project story, assistant chat.
Assigned issues, NCRs, photos, certs.
Scoped project access, items, expenses.
Expense triage workflow only.
Sign in with a password. What each person can see and do is scoped to their role — a consultant or accountant can't reach beyond their own remit.
No password ever. They get a one-time email link that expires in 15 minutes — nothing to set up, nothing to forget.
The link is the key. Client approvals, defect sign-offs and on-site QR photo capture need no login — each secure link opens exactly one thing.
Rails 7.1 · Ruby 3.3
single monolith, one deploy
PostgreSQL 17 + pgvector
relational + vectors, one DB
Solid Queue · Solid Cable
Postgres-backed, no Redis
Hotwire (Turbo + Stimulus)
server-rendered, no SPA
Anthropic Claude — Haiku 4.5 (fast triage), Sonnet 4.6 (long-form generation)
OpenAI text-embedding-3-small · 1536-dim · HNSW
Postmark (in + out) · OpenClaw/wacli (WhatsApp) · Telegram · Zoho CRM sync
Docker · Heroku (prod) + Coolify (staging) · Sentry · Backblaze B2
Forge isn't a third-party integration bolted on the side. It's an AI agent that runs locally and lives inside the same ecosystem — sharing one machine surface, the OpenClaw bridge, with the studio's own channels.
Forge is an AI agent that lives alongside the studio rather than calling in from outside. It wears three hats — all over the very same OpenClaw API the studio's own WhatsApp and Telegram channels run on.
Watches the channels, drafts and creates records, issues and approvals, and runs tasks against True Build OS — a teammate operating directly on project state.
Pre-classifies inbound WhatsApp and Telegram, resolves which project a message belongs to, and decides intent before anything is written down.
Engineering support on the codebase itself — much of this system — plus day-to-day help. The same agent, a broader remit.
Forge is a genuine external AI agent with live read/write access to the studio — which makes the trust boundary the interesting engineering, not the connection itself.
dashboard · projects · action items · issues · approvals · expenses · vendors · staff
action items · issues (+ photos) · records · notes · client approvals · expenses
Beyond the integration, Forge provides ongoing engineering support and operational help directly — a working collaboration, not just an API client.
We spent two months building polished portals. The most-used — and frankly most enjoyable — way to put data into the system has turned out to be none of them. It's messaging.
Answers cite sources alongside, but claims aren't verified back against the retrieved text. No re-ranking, no hybrid keyword+semantic.
Objects can link (blocks, supersedes, remediates) but there's no automatic propagation — it's manual today.
Snooze defers; staleness is detected by scan. There's no time-based auto-escalation or SLA timer.
People are matched by substring — "Sam" can collide with "Samira". No glossary / canonical entity resolution yet.
Budget roll-ups can briefly diverge if a mutation fails mid-transaction. No reconciliation job yet.
Tuning the auto-execution threshold · an evaluation harness for the AI jobs · whether the event spine should become the one universal log.
That's True Build OS as it stands today. I'd value your read on it — especially ways to push it further, and different angles on the problems and the solutions.