NaramAlhasani

I design, architect and build software products.

2 product slots open for Q4

Things I’ve built

10 systems, 7 with live sites

  1. 01.1

    MATTER

    Construction project platform. Running project teams on big projects right now: real-time chat, RFIs, submittals and bids in one place, always showing who owes the next move.

    In use on live projects

    Fig.A project platform for design-build teams, in use on big projects today, made for the people on site with a phone or an iPad.

    Architecture

    1. AClients

      • Web appNext.js 15 · React 19UI

        UI · Next.js 15 · React 19

        The app people use on site and in the office, built mobile-first for phones and iPads. Types are generated from the Java DTOs, so the front end and back end can’t drift.

        Talks to

        • → Public API (HTTPS · JWT)
        • → Live sockets (live)
      • Respond by linkone-time token pagesUI

        UI · one-time token pages

        Pages that outside architects, subs and reviewers open from an emailed link to answer an RFI or a submittal, or to submit a bid. No account needed.

        Talks to

        • → Public API (token)
      • ClaudeMCP clientEXTERNAL

        EXTERNAL · MCP client

        Claude Desktop or any MCP client, signed in as a real user through OAuth. It only gets what that person could do in the app.

        Talks to

        • → MCP endpoint (MCP)
        • → OAuth server (OAuth)
    2. BGateway

      • Public APISpring Boot · WebFluxSERVICE

        SERVICE · Spring Boot · WebFlux

        The only door in. It checks the JWT, resolves the user, their company and the client IP once, and forwards each request with trusted identity headers.

        Talks to

        • ← Web app (HTTPS · JWT)
        • ← Respond by link (token)
        • → Projects (REST)
        • → RFIs (REST)
        • → AI service (proxy)
      • Live socketsWebSocketsREALTIME

        REALTIME · WebSockets

        Held by the gateway: chat, notifications, presence and which conversation each tab is reading. Drawn in full below.

        Talks to

        • ← Web app (live)
        • ← Redis 7 (pub/sub)
      • MCP endpointJSON-RPCAI

        AI · JSON-RPC

        The MCP transport, also in the gateway. Claude’s tool calls arrive here and run as the signed-in user.

        Talks to

        • ← Claude (MCP)
        • → Tool registry (as the user)
      • AI serviceNode · FastifyAI

        AI · Node · Fastify

        Runs the assistant and the agents’ turns: streams the model, loads the tool list, applies each company’s model policy, evaluates agent hooks once per turn, and transcribes voice notes.

        Talks to

        • ← Public API (proxy)
        • → Tool registry (list · call)
        • → Claude · OpenRouter (stream)
        • ← Agents (turns)
    3. CPlatform

      • Projectsdashboard · directorySERVICE

        SERVICE · dashboard · directory

        The centre of the model. Everything else belongs to a project and its team, and the dashboard is built around what the job needs today.

        Talks to

        • ← Public API (REST)
        • ← Procore (import)
      • RFIsball in courtSERVICE

        SERVICE · ball in court

        Requests for information, with drafts. Status rules move the ball: open sits with the assignee’s company, answered or returned goes back to the asker, closed clears it.

        Talks to

        • ← Public API (REST)
        • ← Tool registry
        • → Notifications (ball moved)
        • → PostgreSQL 16 (SQL)
      • Submittalsrevisions · ball in courtSERVICE

        SERVICE · revisions · ball in court

        Submittals go round in revisions, with grant-based access, private drafts and a ball held by named people, until one is approved.

      • Biddingpackages · levelingSERVICE

        SERVICE · packages · leveling

        Bid packages per trade, bids with a schedule of values and alternates, leveling, and the award.

        Talks to

        • → Financials (award → contract)
      • Drawingssplit · diff · presenceSERVICE

        SERVICE · split · diff · presence

        Splits a plan-set PDF into one sheet per page, renders a pixel diff between revisions, holds markups and pins, and shows who else is on the sheet.

        Talks to

        • → Object storage (sheets · overlays)
      • Chatreal timeSERVICE

        SERVICE · real time

        Project, group and direct conversations with mentions and attachments. Drawn in full below.

        Talks to

        • → Redis 7 (publish)
      • Financialscontracts · SOV · pay appsSERVICE

        SERVICE · contracts · SOV · pay apps

        Contracts with schedules of values, change events and change orders, and pay applications on the AIA G702/G703 forms. Contract sums are derived, never stored.

        Talks to

        • ← Bidding (award → contract)
      • Agentscommands · skills · hooksAI

        AI · commands · skills · hooks

        Each company’s AI agents: a built-in set of construction commands, its own skills, hooks evaluated on every turn with an audit trail, and delegation to named agents only.

        Talks to

        • → AI service (turns)
      • Notificationsin-app · emailSERVICE

        SERVICE · in-app · email

        Tells the right people when something moves, like a ball changing hands, in the app and by email.

        Talks to

        • ← RFIs (ball moved)
        • → Redis 7 (publish)
      • Tool registry199 MCP toolsAI

        AI · 199 MCP tools

        Every action an AI may take, declared on the service method itself with a schema derived from its DTO, one error path, and the caller’s permissions checked on every call.

        Talks to

        • ← MCP endpoint (as the user)
        • ← AI service (list · call)
        • → RFIs
      • Documentslibrary · PDFSERVICE

        SERVICE · library · PDF

        One library for files and generated documents at company and project level, each with a share list, rendered to PDF on the server.

        Talks to

        • ← Workflows (renders)
        • → Autodesk APS (folders · files)
      • OAuth serverOAuth 2.1SERVICE

        SERVICE · OAuth 2.1

        Lets MCP clients such as Claude Desktop sign in as a user. Redirect addresses are checked strictly so the consent step can’t be abused.

        Talks to

        • ← Claude (OAuth)
      • Sales & CRMleads · estimatingSERVICE

        SERVICE · leads · estimating

        Leads with statuses each company sets, client accounts, contacts, follow-ups, the estimating schedule, and won/lost analysis.

        Talks to

        • ← Missive (webhooks)
      • Workflowstriggers · cronJOB

        JOB · triggers · cron

        Workflow definitions wired step to step, checked so each output fits the next input, and run on triggers or a schedule.

        Talks to

        • → Documents (renders)
      • Catalogue ingestionfrom past documentsAI

        AI · from past documents

        Reads a company’s past project documents and proposes budget and qualification catalogue entries for a person to accept.

    4. DData

      • PostgreSQL 16Liquibase migrationsSTORE

        STORE · Liquibase migrations

        The system of record for every module, with versioned schema migrations.

        Talks to

        • ← RFIs (SQL)
      • Redis 7cache · pub/subSTORE

        STORE · cache · pub/sub

        Caching, plus the pub/sub channels that carry chat, notification, presence and viewing events between instances.

        Talks to

        • ← Notifications (publish)
        • ← Chat (publish)
        • → Live sockets (pub/sub)
      • Object storageS3-compatibleSTORE

        STORE · S3-compatible

        Files: drawing sheets and thumbnails, diff overlays, photos and documents, served through short-lived signed links.

        Talks to

        • ← Drawings (sheets · overlays)
    5. EOutside

      • Procoreone-way importEXTERNAL

        EXTERNAL · one-way import

        Projects are imported from Procore over OAuth. Nothing is written back.

        Talks to

        • → Projects (import)
      • MissivewebhooksEXTERNAL

        EXTERNAL · webhooks

        The shared inbox. Its webhooks bring email activity into sales.

        Talks to

        • → Sales & CRM (webhooks)
      • Claude · OpenRoutermodelsEXTERNAL

        EXTERNAL · models

        The models behind the assistant and the agents, chosen per company within the platform’s policy.

        Talks to

        • ← AI service (stream)
      • Autodesk APSOAuth · filesEXTERNAL

        EXTERNAL · OAuth · files

        Autodesk Platform Services: linked projects, folders and files.

        Talks to

        • ← Documents (folders · files)

    Connections

    1. Web app → Public API · HTTPS · JWT
    2. Respond by link → Public API · token
    3. Web app → Live sockets · live
    4. Claude → MCP endpoint · MCP
    5. Claude → OAuth server · OAuth
    6. Public API → Projects · REST
    7. Public API → RFIs · REST
    8. Public API → AI service · proxy
    9. MCP endpoint → Tool registry · as the user
    10. AI service → Tool registry · list · call
    11. AI service → Claude · OpenRouter · stream
    12. Agents → AI service · turns
    13. Tool registry → RFIs
    14. RFIs → Notifications · ball moved
    15. Bidding → Financials · award → contract
    16. Notifications ⇢ Redis 7 · publish
    17. Chat ⇢ Redis 7 · publish
    18. Redis 7 ⇢ Live sockets · pub/sub
    19. RFIs → PostgreSQL 16 · SQL
    20. Drawings → Object storage · sheets · overlays
    21. Workflows → Documents · renders
    22. Documents → Autodesk APS · folders · files
    23. Procore ⇢ Projects · import
    24. Missive ⇢ Sales & CRM · webhooks

    Inside: real-time chat and presence

    Every server can hold someone’s open tab, so nothing is sent tab to tab. Events go through Redis once, each server pushes them to the tabs it holds, and the app keeps track of what each tab is actually looking at.

    1. ATabs

      • Open tabsone socket eachUI

        UI · one socket each

        Every open tab is its own WebSocket session. It reports which conversation it is showing and whether the person is active or idle.

        Talks to

        • → Socket handler (WebSocket)
        • ← Fan-out (push)
      • Drawing vieweravatarsUI

        UI · avatars

        Shows who else is on the same sheet right now.

        Talks to

        • → Presence relay (open · keep-alive)
    2. BGateway

      • Socket handlerper-session stateREALTIME

        REALTIME · per-session state

        Tracks viewing per session, not per user: when a tab closes it re-resolves from the person’s remaining tabs, so a closed tab never leaves a stale “still reading”.

        Talks to

        • ← Open tabs (WebSocket)
        • → Viewing state (viewing)
      • Fan-outchannel subscribersREALTIME

        REALTIME · channel subscribers

        Subscribes to the chat, notification and system channels and pushes each event to the sessions this server holds.

        Talks to

        • ← Chat events
        • ← Notifications
        • → Open tabs (push)
      • Presence relayJWT handshakeREALTIME

        REALTIME · JWT handshake

        Relays “I’m on this sheet” to the platform. The user comes from the authenticated handshake, never the message, and every keep-alive re-proves access.

        Talks to

        • ← Drawing viewer (open · keep-alive)
        • → Drawing presence (relay)
    3. CChannels

      • Chat eventsRedis pub/subQUEUE

        QUEUE · Redis pub/sub

        Chat events, published once for every server to hear.

        Talks to

        • ← Chat service (publish once)
        • → Fan-out
      • NotificationsRedis pub/subQUEUE

        QUEUE · Redis pub/sub

        Notification events on their way to open tabs.

        Talks to

        • → Fan-out
        • ← Chat notifications (publish)
        • ← Ball in court (ball moved)
      • Viewing stateRedis pub/subQUEUE

        QUEUE · Redis pub/sub

        Which conversation each person is reading, shared between servers.

        Talks to

        • ← Socket handler (viewing)
        • → Viewing registry (subscribe)
      • PresenceRedis pub/subQUEUE

        QUEUE · Redis pub/sub

        Who is on which sheet, and last-seen updates.

        Talks to

        • ← Drawing presence (roster)
    4. DPlatform

      • Viewing registryin memorySERVICE

        SERVICE · in memory

        Per-server and deliberately not persisted: after a restart it refills from the next broadcasts.

        Talks to

        • ← Viewing state (subscribe)
        • ← Chat notifications (reading?)
      • Chat servicemessages · mentionsSERVICE

        SERVICE · messages · mentions

        Stores the message, works out the recipients and publishes the event once.

        Talks to

        • → Chat events (publish once)
        • → Chat notifications
      • Chat notificationsskips readersSERVICE

        SERVICE · skips readers

        Notifies everyone except the sender and anyone already reading the conversation, respecting each person’s settings; mentions also go by email.

        Talks to

        • ← Chat service
        • → Viewing registry (reading?)
        • → Notifications (publish)
      • Drawing presencepermission-checkedSERVICE

        SERVICE · permission-checked

        Owns the access check and the roster of who is on each sheet.

        Talks to

        • ← Presence relay (relay)
        • → Presence (roster)
      • Ball in courtRFIs · submittalsSERVICE

        SERVICE · RFIs · submittals

        Status rules decide who holds the ball. Only an official answer moves it; a change of holder notifies the new one.

        Talks to

        • → Notifications (ball moved)

    Connections

    1. Open tabs → Socket handler · WebSocket
    2. Socket handler ⇢ Viewing state · viewing
    3. Viewing state ⇢ Viewing registry · subscribe
    4. Chat service ⇢ Chat events · publish once
    5. Chat events ⇢ Fan-out
    6. Notifications ⇢ Fan-out
    7. Fan-out ⇢ Open tabs · push
    8. Chat service → Chat notifications
    9. Chat notifications → Viewing registry · reading?
    10. Chat notifications ⇢ Notifications · publish
    11. Ball in court ⇢ Notifications · ball moved
    12. Drawing viewer → Presence relay · open · keep-alive
    13. Presence relay → Drawing presence · relay
    14. Drawing presence ⇢ Presence · roster

    Two flows

    An RFI changes hands

    Step through it and the parts it runs through light up above.

    By count

    actions Claude can take in it
    199

    Notes

    1. N.1Nobody updates ball-in-court by hand. It follows the RFI: while it’s open it sits with the company that has to answer, once it’s answered it goes back to whoever asked, and closing it clears it.
    2. N.2Only an official answer moves the ball. A quick clarifying reply joins the thread and leaves the ball where it is.
    3. N.3The assistant sees exactly what you can see and nothing more. It works through the same actions you have.
    4. N.4Awarding a bid carries its schedule of values onto a payable contract, in a separate step that can never undo the award if it fails.
    runsraisesanswered byrevised asemploysstaffed bycollectsOrganizationGC, sub or clientProjectthe jobRFIball in courtResponsemay supersede oneMembera person, a roleSubmittalapproved as noted …Revisionrevise & resubmit
    Fig.Swipe across to see all of it. MATTER’s core data model.
    MATTER website
  2. 01.2

    OutreachSphere

    Sales CRM. Turns a cold lead list into deals: it fills in missing contacts, runs email and LinkedIn sequences, and sorts replies so only real leads reach a person.

    Live · Formwork and its clients

    Fig.Cold outreach for Formwork and its clients, from a raw lead list to a deal in the CRM.

    Architecture

    1. APeople

      • Campaign managersNext.js 15 · React 19UI

        UI · Next.js 15 · React 19

        Formwork’s team: lead lists, campaigns, sequences and the CRM, across every client, each client’s data kept apart.

        Talks to

        • → Lead lists (CSV)
      • SDR deskcalls · follow-upsUI

        UI · calls · follow-ups

        Where reps work the follow-up queue, approve drafted replies and log calls.

        Talks to

        • → Reply approvals (approve)
      • Client portalper clientUI

        UI · per client

        Each client sees their own campaigns, leads, pipeline and campaign health.

        Talks to

        • → CRM (their pipeline)
      • ClaudeMCP clientEXTERNAL

        EXTERNAL · MCP client

        Claude, connected with a personal token, working the same data through MCP.

        Talks to

        • → MCP server (MCP · token)
    2. BApp

      • Lead listsCSV · domain dedupeSERVICE

        SERVICE · CSV · domain dedupe

        Uploaded lists, cleaned and matched to companies by web domain. Uploading never marks anyone as contacted.

        Talks to

        • ← Campaign managers (CSV)
        • → Enrichment (gaps)
        • → Sequences (filtered)
      • Enrichmentwaterfall per fieldSERVICE

        SERVICE · waterfall per field

        Fills each missing field (email, phone, title, location) by trying providers in priority order, with rate limits and caching.

        Talks to

        • ← Lead lists (gaps)
        • ← Enrichment drain (queued)
        • → Data providers (in turn)
      • Sequencesemail · LinkedInSERVICE

        SERVICE · email · LinkedIn

        A sequence filters a live list into the leads it will contact, then hands them to the sender for its channel.

        Talks to

        • ← Lead lists (filtered)
        • → Smartlead (push)
        • → Valley
      • Webhook intakeevents · repliesSERVICE

        SERVICE · events · replies

        Receives the senders’ events. Only these can mark a contact as reached, which keeps the numbers honest.

        Talks to

        • ← Smartlead (webhooks)
        • ← Valley (webhooks)
        • ← Nylas (webhooks)
        • → Reply triage (replies)
      • MCP server100 tools by roleAI

        AI · 100 tools by role

        Tools grouped by area and composed per role: an admin sees all of them, other roles only their own. Tokens are stored hashed.

        Talks to

        • ← Claude (MCP · token)
      • CRMcompanies · contactsSERVICE

        SERVICE · companies · contacts

        Warm contacts and their companies, with status, temperature, notes and a relationship score from 0 to 100.

        Talks to

        • ← Reply approvals (promote)
        • → Opportunities (deal)
        • ← Client portal (their pipeline)
        • → PostgreSQL
      • Opportunitiesproposal → won / lostSERVICE

        SERVICE · proposal → won / lost

        Deals, from proposal to won or lost.

        Talks to

        • ← CRM (deal)
      • Reply approvalsdrafted answersSERVICE

        SERVICE · drafted answers

        Real leads queue here with a reply drafted. A person approves it before it goes.

        Talks to

        • ← Reply triage (real leads)
        • ← Reply pre-drafts (drafts)
        • ← SDR desk (approve)
        • → Smartlead (reply)
        • → CRM (promote)
      • Reply triagerules → ClaudeAI

        AI · rules → Claude

        Cheap rules catch bounces, unsubscribes and warmup mail first. Claude sorts the rest into six kinds, and says unsure rather than guess.

        Talks to

        • ← Webhook intake (replies)
        • → Claude · OpenAI (classify)
        • → Slack (alert)
        • → Reply approvals (real leads)
      • Research & prepClaude · FirecrawlAI

        AI · Claude · Firecrawl

        Researches a contact or their company and preps a sales meeting, and answers questions about the CRM.

        Talks to

        • → Vector store
    3. CJobs

      • Enrichment draincronJOB

        JOB · cron

        Works through queued enrichment in the background.

        Talks to

        • → Enrichment (queued)
      • Reply pre-draftscronJOB

        JOB · cron

        Drafts answers ahead of time for confident real leads, so the queue is ready when someone opens it.

        Talks to

        • → Reply approvals (drafts)
      • Sender synccronJOB

        JOB · cron

        Pulls campaign stats from Smartlead and sends replies scheduled for later.

        Talks to

        • → Smartlead
    4. DData

      • PostgreSQLPrismaSTORE

        STORE · Prisma

        Every client’s leads, lists, campaigns and CRM, scoped by client.

        Talks to

        • ← CRM
      • Vector storePostgres · embeddingsSTORE

        STORE · Postgres · embeddings

        A separate database of contact embeddings for semantic search in the assistant.

        Talks to

        • ← Research & prep
    5. EOutside

      • Data providersProxycurl · Findymail …EXTERNAL

        EXTERNAL · Proxycurl · Findymail …

        Proxycurl, Findymail, Apollo and Hunter, among others, tried in turn for each missing field.

        Talks to

        • ← Enrichment (in turn)
      • SmartleademailEXTERNAL

        EXTERNAL · email

        Sends the email sequences, and sends approved replies on the same thread.

        Talks to

        • ← Sequences (push)
        • → Webhook intake (webhooks)
        • ← Reply approvals (reply)
        • ← Sender sync
      • ValleyLinkedInEXTERNAL

        EXTERNAL · LinkedIn

        Runs the LinkedIn sequences.

        Talks to

        • ← Sequences
        • → Webhook intake (webhooks)
      • NylasmailboxesEXTERNAL

        EXTERNAL · mailboxes

        Connected mailboxes, for replies that arrive outside a sequence.

        Talks to

        • → Webhook intake (webhooks)
      • Claude · OpenAImodelsEXTERNAL

        EXTERNAL · models

        Claude for triage, drafting and research; OpenAI for embeddings.

        Talks to

        • ← Reply triage (classify)
      • Slacktriage alertsEXTERNAL

        EXTERNAL · triage alerts

        Triage posts real leads to the team’s channels.

        Talks to

        • ← Reply triage (alert)

    Connections

    1. Campaign managers → Lead lists · CSV
    2. Lead lists → Enrichment · gaps
    3. Enrichment drain ⇢ Enrichment · queued
    4. Enrichment → Data providers · in turn
    5. Lead lists → Sequences · filtered
    6. Sequences → Smartlead · push
    7. Sequences → Valley
    8. Smartlead ⇢ Webhook intake · webhooks
    9. Valley ⇢ Webhook intake · webhooks
    10. Nylas ⇢ Webhook intake · webhooks
    11. Webhook intake → Reply triage · replies
    12. Reply triage → Claude · OpenAI · classify
    13. Reply triage ⇢ Slack · alert
    14. Reply triage → Reply approvals · real leads
    15. Reply pre-drafts ⇢ Reply approvals · drafts
    16. SDR desk → Reply approvals · approve
    17. Reply approvals → Smartlead · reply
    18. Reply approvals → CRM · promote
    19. CRM → Opportunities · deal
    20. Client portal → CRM · their pipeline
    21. Claude → MCP server · MCP · token
    22. Sender sync ⇢ Smartlead
    23. Research & prep → Vector store
    24. CRM → PostgreSQL

    Inside: reply triage

    Most replies to cold email are noise. Triage stores every reply first, lets cheap rules catch the obvious, has Claude sort the rest, and only ever lets a person send, with the CRM updated before the one step that can’t be undone.

    1. AArrive

      • Smartleadreply webhooksEXTERNAL

        EXTERNAL · reply webhooks

        Replies to the email sequences, including ones from a colleague of the person emailed.

        Talks to

        • → Webhook event
      • Nylasmailbox webhooksEXTERNAL

        EXTERNAL · mailbox webhooks

        Replies that land in connected mailboxes.

        Talks to

        • → Webhook event
      • Webhook eventstored firstSTORE

        STORE · stored first

        Every reply is saved before it is classified, so nothing is lost and anything can be reclassified later.

        Talks to

        • ← Smartlead
        • ← Nylas
        • → Field extraction
    2. BSort

      • Field extractionevery known aliasSERVICE

        SERVICE · every known alias

        Smartlead has used several names for each field over time; extraction tries all of them.

        Talks to

        • ← Webhook event
        • → Rules
      • Ruleswarmup · bounces · vendorsSERVICE

        SERVICE · warmup · bounces · vendors

        Catch warmup mail, auto-replies, unsubscribes and bounces without a model call. Vendor domains an admin pins are a hard rule.

        Talks to

        • ← Field extraction
        • → Classifier (undecided)
      • ClassifierClaude Haiku · six kindsAI

        AI · Claude Haiku · six kinds

        Sorts what the rules can’t decide into a real lead, unsure, vendor mail, automated, spam or warmup noise, with a confidence and a one-line reason. A bid invitation from a platform counts as real money.

        Talks to

        • ← Rules (undecided)
        • → Confidence floor
      • Confidence floorlow → unsureSERVICE

        SERVICE · low → unsure

        A low-confidence answer becomes unsure, so a person sees it.

        Talks to

        • ← Classifier
        • → Hot channel (lead · unsure)
        • → Vendor channel (vendor)
        • → Firehose
        • → Review queue (real leads)
      • Kill switcheverything to peopleSERVICE

        SERVICE · everything to people

        One setting sends every reply to the hot channel for a person to read.

        Talks to

        • → Hot channel (override)
    3. CRoute

      • Hot channelreal leads · unsureEXTERNAL

        EXTERNAL · real leads · unsure

        Slack, for replies a person should see now.

        Talks to

        • ← Confidence floor (lead · unsure)
        • ← Kill switch (override)
      • Vendor channelSlackEXTERNAL

        EXTERNAL · Slack

        Vendor mail, kept apart.

        Talks to

        • ← Confidence floor (vendor)
      • Firehoseevery replyEXTERNAL

        EXTERNAL · every reply

        Every classification, whatever the category, as an audit trail.

        Talks to

        • ← Confidence floor
      • Review queueone per replySERVICE

        SERVICE · one per reply

        Real leads queue for a drafted answer; creating the entry twice for the same reply is impossible.

        Talks to

        • ← Confidence floor (real leads)
        • → Draft + suggestions
    4. DAnswer

      • Pre-draftscronJOB

        JOB · cron

        Drafts ahead of time for confident real leads; everything else drafts when someone opens it.

        Talks to

        • → Draft + suggestions
      • Draft + suggestionsreply · tags · temperatureAI

        AI · reply · tags · temperature

        One call writes the reply and suggests tags (only from the client’s existing ones, never invented), a CRM status and a temperature from cold to burning.

        Talks to

        • ← Review queue
        • ← Pre-drafts
        • → Approve
      • ApproveCRM first, send lastUI

        UI · CRM first, send last

        The reversible work (status, temperature, tags) is applied first; the send, which can’t be undone, comes last.

        Talks to

        • ← Draft + suggestions
        • → Thread resolver
      • Thread resolvercolleague repliesSERVICE

        SERVICE · colleague replies

        Finds the right thread even when the person replying was never in the campaign, using the id the original webhook carried.

        Talks to

        • ← Approve
        • → Send or schedule
      • Send or scheduleSmartlead inboxSERVICE

        SERVICE · Smartlead inbox

        Sends now or at a set time on the same thread, logs it, and marks the contact as replied.

        Talks to

        • ← Thread resolver

    Connections

    1. Smartlead ⇢ Webhook event
    2. Nylas ⇢ Webhook event
    3. Webhook event → Field extraction
    4. Field extraction → Rules
    5. Rules → Classifier · undecided
    6. Classifier → Confidence floor
    7. Confidence floor → Hot channel · lead · unsure
    8. Confidence floor → Vendor channel · vendor
    9. Confidence floor ⇢ Firehose
    10. Kill switch → Hot channel · override
    11. Confidence floor → Review queue · real leads
    12. Review queue → Draft + suggestions
    13. Pre-drafts ⇢ Draft + suggestions
    14. Draft + suggestions → Approve
    15. Approve → Thread resolver
    16. Thread resolver → Send or schedule

    Two flows

    A lead list becomes a pipeline

    Step through it and the parts it runs through light up above.

    By count

    channels: email and LinkedIn
    2
    kinds of reply, sorted
    6
    actions Claude can take in it
    100

    Notes

    1. N.1Nobody counts as contacted until the email has actually gone out, so the numbers a client sees are real.
    2. N.2An invitation to bid sent by a bid platform is automated, but it’s still real money. The sorter is told that, and when it isn’t sure it says so and a person looks.
    3. N.3Clients get their own portal with their campaigns, leads and pipeline.
    OutreachSphere website
  3. 01.3

    SIGIL

    Sound-design instrument. A synth with six ways to make sound that plays in a browser tab or inside your DAW. Hunt breeds new patches from the ones you keep, so you find sounds by ear.

    Invite-only for now · demos public

    Fig.A sound-design instrument: six engines, in a browser tab or inside your DAW.

    Architecture

    1. APlay

      • Browser tabNext.js 16 · ReactUI

        UI · Next.js 16 · React

        The instrument in a browser. The public build keeps everything in the browser, with no accounts and nothing stored on a server.

        Talks to

        • → React UI
        • → Server routes (gate)
      • MIDI · keyboardWebMIDI · computer keysUI

        UI · WebMIDI · computer keys

        Play from a controller or the computer keyboard, in a chosen key and scale. Every browser API is optional; missing ones fail quietly.

        Talks to

        • → React UI (notes)
      • Your DAWVST3 · standaloneEXTERNAL

        EXTERNAL · VST3 · standalone

        Ableton or any VST3 host, on Apple Silicon, loading the plugin build.

        Talks to

        • ← Bounce · record (drag WAV)
        • ← JUCE plugin (VST3)
      • ClaudeMCP clientEXTERNAL

        EXTERNAL · MCP client

        Claude can list engines and presets, make and change patches, and write chord progressions.

        Talks to

        • → MCP endpoint (MCP)
    2. BInterface

      • Bounce · recordWAV · drag outSERVICE

        SERVICE · WAV · drag out

        Renders a sound offline to WAV, or records it, then lets you drag the file onto a DAW track (in Chrome) or download it.

        Talks to

        • ← React UI
        • → Your DAW (drag WAV)
      • React UIone UI for bothUI

        UI · one UI for both

        The same interface in the browser and inside the plugin: engines, macros, the XY pad, presets and Hunt.

        Talks to

        • ← Browser tab
        • ← MIDI · keyboard (notes)
        • ← Hunt (six takes)
        • → AudioWorklet (params · notes)
        • → Bounce · record
        • → JUCE plugin (bundled)
      • Huntmutate · breed · tasteSERVICE

        SERVICE · mutate · breed · taste

        Six variations at a time, judged by ear. Keeping some nudges the next generation toward them, within limits, and the nudge fades unless you keep choosing it.

        Talks to

        • ← Presets (seeds)
        • → Names & glyphs (name · mark)
        • → React UI (six takes)
      • Names & glyphsfrom parametersSERVICE

        SERVICE · from parameters

        A patch’s name and mark are computed from its parameters, so the same sound gets the same name everywhere, with nothing stored.

        Talks to

        • ← Hunt (name · mark)
      • MCP endpoint13 tools · JSON-RPCAI

        AI · 13 tools · JSON-RPC

        A plain HTTP POST endpoint. The protocol layer knows nothing about music; every tool body is a tested function.

        Talks to

        • ← Claude (MCP)
        • → Six engines (patches)
    3. CSound

      • Presets84 across the banksSTORE

        STORE · 84 across the banks

        Starting points for every engine, plus a percussion bank.

        Talks to

        • → Hunt (seeds)
      • DSP coreTypeScript · referenceSERVICE

        SERVICE · TypeScript · reference

        The synthesis itself, in plain TypeScript: no browser APIs and no allocation in the render loops.

        Talks to

        • ← AudioWorklet (renders)
        • → Six engines
        • → Parity check (goldens)
      • Six enginesanalog · FM · physical …SERVICE

        SERVICE · analog · FM · physical …

        Analog, FM, physical modelling, granular, wavetable and sampler voices, under one voice manager.

        Talks to

        • ← DSP core
        • → FX & character
        • ← MCP endpoint (patches)
      • FX & charactertwo chainsSERVICE

        SERVICE · two chains

        An effects chain and a character chain, available on every engine.

        Talks to

        • ← Six engines
    4. DHosts

      • AudioWorkletseparate realmREALTIME

        REALTIME · separate realm

        Runs the DSP on the browser’s audio thread. It is bundled on its own and only hears what the page posts to it.

        Talks to

        • ← React UI (params · notes)
        • → DSP core (renders)
      • C++ enginehand portSERVICE

        SERVICE · hand port

        The same DSP in C++, kept in step with the TypeScript.

        Talks to

        • ← JUCE plugin (process)
        • → Parity check (compared)
      • JUCE pluginWebView UI insideSERVICE

        SERVICE · WebView UI inside

        Wraps the C++ engine as a VST3 and serves the React UI from inside the binary. Parameters are only ever appended, so saved automation never moves.

        Talks to

        • ← React UI (bundled)
        • → C++ engine (process)
        • → Your DAW (VST3)
    5. EBuild

      • Server routespasscode gate · sign-upsSERVICE

        SERVICE · passcode gate · sign-ups

        The private build sits behind a passcode; the public one has none. One setting decides, not a fork.

        Talks to

        • ← Browser tab (gate)
        • → PostgreSQL (SQL)
      • PostgreSQLsign-upsSTORE

        STORE · sign-ups

        Email sign-ups from the landing page.

        Talks to

        • ← Server routes (SQL)
      • Parity check197 golden rendersJOB

        JOB · 197 golden renders

        Renders fresh goldens from the TypeScript and measures the C++ against them on every build.

        Talks to

        • ← DSP core (goldens)
        • ← C++ engine (compared)

    Connections

    1. Browser tab → React UI
    2. MIDI · keyboard → React UI · notes
    3. Presets → Hunt · seeds
    4. Hunt → Names & glyphs · name · mark
    5. Hunt → React UI · six takes
    6. React UI → AudioWorklet · params · notes
    7. AudioWorklet → DSP core · renders
    8. DSP core → Six engines
    9. Six engines → FX & character
    10. React UI → Bounce · record
    11. Bounce · record → Your DAW · drag WAV
    12. React UI → JUCE plugin · bundled
    13. JUCE plugin → C++ engine · process
    14. JUCE plugin → Your DAW · VST3
    15. DSP core → Parity check · goldens
    16. C++ engine → Parity check · compared
    17. Claude → MCP endpoint · MCP
    18. MCP endpoint → Six engines · patches
    19. Browser tab → Server routes · gate
    20. Server routes → PostgreSQL · SQL

    Inside: the engines and Hunt

    Each engine is a description plus a voice; the interface, the plugin parameters and Hunt are all built from the description. Hunt breeds sounds from a single seed, so a whole session can be replayed from one number.

    1. ADescribe

      • Engine registryone line per engineSERVICE

        SERVICE · one line per engine

        Adding an engine is one line here plus its module. No app code changes.

        Talks to

        • → Descriptors
      • Descriptorsparams · ranges · groupsSTORE

        STORE · params · ranges · groups

        Every parameter with its range, default, curve and group. Linear and exponential parameters are normalised differently so a step means the same thing to the ear.

        Talks to

        • ← Engine registry
        • → Built interface (builds)
        • → Voice manager (params)
      • Built interfacefrom descriptorsUI

        UI · from descriptors

        The controls draw themselves from the descriptor.

        Talks to

        • ← Descriptors (builds)
    2. BVoices

      • Voice managerpolyphonySERVICE

        SERVICE · polyphony

        Owns polyphony so engines never think about it. Every voice is allocated up front, so playing a note allocates nothing.

        Talks to

        • ← Descriptors (params)
        • → Analog (voices)
        • ← Smoothing
        • → Granular
      • Analogantialiased saw · ladderSERVICE

        SERVICE · antialiased saw · ladder

        Subtractive voice with an antialiased sawtooth, so the top end sounds clean rather than harsh, into a ladder filter.

        Talks to

        • ← Voice manager (voices)
      • FMvelocity → brightnessSERVICE

        SERVICE · velocity → brightness

        Frequency modulation where playing harder opens the timbre, like a real tine, and nothing you do can push a preset past the brightness it was voiced at.

      • Physicalmembrane · wood · metal · glassSERVICE

        SERVICE · membrane · wood · metal · glass

        A bank of resonant modes shaped like a drum head, a wooden bar, a bell or glass. Bowed excitation is bounded so it can never build up forever.

        Talks to

        • → Effects chain (mix)
      • Granularshared buffersSERVICE

        SERVICE · shared buffers

        Grain clouds panned across the field, sharing one buffer across voices instead of megabytes per note, with tapered windows so grains never click.

        Talks to

        • ← Voice manager
      • Wavetablesine → metallicSERVICE

        SERVICE · sine → metallic

        Tables that run from pure to complex: sine, triangle, soft organic, square, saw, two vocal formants and metallic.

      • Sampleryour samplesSERVICE

        SERVICE · your samples

        Every voice plays one shared sample; swapping a 30 MB recording is a single reference swap between audio blocks.

    3. CSignal

      • Smoothingevery parameterSERVICE

        SERVICE · every parameter

        Every parameter passes through a smoother. Unsmoothed changes cause zipper noise, the most common reason a digital synth sounds cheap.

        Talks to

        • → Voice manager
      • Effects chainchorus · delay · reverbSERVICE

        SERVICE · chorus · delay · reverb

        Where the signal becomes stereo. Each unit is skipped when its mix is silent.

        Talks to

        • ← Physical (mix)
        • → Character chain
      • Character chainbounded ±1.2SERVICE

        SERVICE · bounded ±1.2

        Effects that make a listener ask what that was, allocation-free and guarded against denormals, and bounded so nothing can push the output past ±1.2.

        Talks to

        • ← Effects chain
    4. DHunt

      • Seedone numberSERVICE

        SERVICE · one number

        A deterministic generator: the same seed gives the same hunt on every machine, so a session can be shared as a single number.

        Talks to

        • → Mutate
      • Mutatesix distinct takesSERVICE

        SERVICE · six distinct takes

        Walks the current patch to six variations, retrying until they sound distinct from each other.

        Talks to

        • ← Seed
        • ← Breed
        • → Lineage (what changed)
      • Breedtwo kept parentsSERVICE

        SERVICE · two kept parents

        Crosses two patches you kept, with a little jitter.

        Talks to

        • → Mutate
        • ← Taste (bias)
      • Tastebounded · blended · fadingSERVICE

        SERVICE · bounded · blended · fading

        Turns what you keep into a direction for the next generation: capped so it can’t pin a parameter, blended so one odd keep doesn’t define you, and fading unless you keep choosing it.

        Talks to

        • → Breed (bias)
      • Lineage“brighter”, “looser”SERVICE

        SERVICE · “brighter”, “looser”

        Names the one or two things that changed in a player’s words, and keeps the trail of moves that found a sound.

        Talks to

        • ← Mutate (what changed)
        • → Name & glyph
      • Name & glyphfrom parametersSERVICE

        SERVICE · from parameters

        Computed from the parameter values, so the same sound always has the same name and mark.

        Talks to

        • ← Lineage

    Connections

    1. Engine registry → Descriptors
    2. Descriptors → Built interface · builds
    3. Descriptors → Voice manager · params
    4. Voice manager → Analog · voices
    5. Smoothing → Voice manager
    6. Voice manager → Granular
    7. Physical → Effects chain · mix
    8. Effects chain → Character chain
    9. Seed → Mutate
    10. Breed → Mutate
    11. Taste → Breed · bias
    12. Mutate → Lineage · what changed
    13. Lineage → Name & glyph

    Two flows

    Finding a sound

    Step through it and the parts it runs through light up above.

    By count

    engines
    6
    presets
    84
    actions Claude can take in it
    13

    Notes

    1. N.1A patch’s name and glyph come from how it sounds. The same sound is called the same thing on every machine, and a heavy dark patch can’t come out called Bright Tide.
    2. N.2Hunt shows no knobs. You choose by ear, and each patch keeps the moves that found it, written the way a player would say them.
    3. N.3The plugin and the browser make the same sound, so a patch you find in a tab sounds identical in your DAW.
    SIGIL website
  4. 01.4

    Orbit

    AI testing platform. Point it at a GitHub repo and it tests the app for you: riskiest journeys first, in a real browser, with what broke explained in plain English.

    Live · in development

    Fig.An AI tester for small teams that ship fast: connect a repo and it tests the app the way a person would.

    Architecture

    1. AClients

      • DashboardNext.js · live mapUI

        UI · Next.js · live map

        Projects, the system map, plans, runs with replays and failure analysis, and a chat panel.

        Talks to

        • → API routes (HTTPS)
        • ← Live stream (live)
      • GitHubOAuth · App · webhooksEXTERNAL

        EXTERNAL · OAuth · App · webhooks

        Sign-in, repo access through an installed App, webhooks on changes, and checks and comments back on pull requests.

        Talks to

        • → API routes (webhooks)
        • ← Reporter (PR check)
      • ClaudeMCP clientEXTERNAL

        EXTERNAL · MCP client

        Trigger runs, read the system map, plans and results, and search failures from Claude.

        Talks to

        • → MCP server (MCP)
    2. BAPI

      • API routesNextAuth · RESTSERVICE

        SERVICE · NextAuth · REST

        Workspaces, projects, plans and runs, plus the webhook receivers for GitHub, Linear, Slack and billing.

        Talks to

        • ← Dashboard (HTTPS)
        • ← GitHub (webhooks)
        • → indexing (enqueue)
      • Live streamSSE · pub/subREALTIME

        REALTIME · SSE · pub/sub

        Streams indexing progress, run events and browser screenshots to the dashboard as they happen.

        Talks to

        • ← Executor (screenshots)
        • → Dashboard (live)
      • Orchestratorbudgets · contextSERVICE

        SERVICE · budgets · context

        Coordinates the agents through a run: token budgets per agent, and context picked by similarity rather than sent whole.

        Talks to

        • → execution (run)
        • ← scheduler (schedule)
        • ← MCP server (trigger)
      • MCP server7 toolsAI

        AI · 7 tools

        Run, map, plan, results, health, failure search and a code audit, over MCP.

        Talks to

        • ← Claude (MCP)
        • → Orchestrator (trigger)
    3. CQueues

      • indexingBullMQQUEUE

        QUEUE · BullMQ

        Jobs to clone and index a repo.

        Talks to

        • ← API routes (enqueue)
        • → Analyst (worker)
      • executionBullMQQUEUE

        QUEUE · BullMQ

        Jobs to run test cases in a browser.

        Talks to

        • ← Orchestrator (run)
        • → Executor (worker)
      • reportingBullMQQUEUE

        QUEUE · BullMQ

        Jobs to analyse results and send reports.

        Talks to

        • ← Executor (results)
        • → Reporter (worker)
      • schedulerBullMQQUEUE

        QUEUE · BullMQ

        Recurring runs on a schedule.

        Talks to

        • → Orchestrator (schedule)
    4. DAgents

      • Analystsystem mapAI

        AI · system map

        Turns a repo into a system map: framework, routes, components and their links.

        Talks to

        • ← indexing (worker)
        • → Indexer
        • → Planner (system map)
      • Plannerjourneys · casesAI

        AI · journeys · cases

        Rebuilds user journeys from the map, finds coverage gaps and writes test cases. Plans are cached.

        Talks to

        • ← Analyst (system map)
        • → Prioritiser
        • → Claude · GPT (plan)
      • Executorruns · evidenceAI

        AI · runs · evidence

        Drives a real browser step by step, classifies each failure, and captures screenshots, video and DOM snapshots.

        Talks to

        • ← execution (worker)
        • → Playwright · Stagehand (CDP)
        • → Self-healer
        • → Object storage (evidence)
        • → Live stream (screenshots)
        • → reporting (results)
      • Reporterplain EnglishAI

        AI · plain English

        Explains failures, spots patterns across runs, and files them where the team works.

        Talks to

        • ← reporting (worker)
        • → GitHub (PR check)
        • → Linear · Slack
      • Indexertree-sitter · regex fallbackSERVICE

        SERVICE · tree-sitter · regex fallback

        Parses source with tree-sitter, falls back to patterns when it can’t, detects the framework, and indexes incrementally.

        Talks to

        • ← Analyst
        • → PostgreSQL (map · embeddings)
      • Prioritiser40 · 35 · 25SERVICE

        SERVICE · 40 · 35 · 25

        Scores each case on criticality (40%), risk (35%) and coverage gap (25%), and boosts journeys like sign-in and checkout.

        Talks to

        • ← Planner
      • Self-healerselector memorySERVICE

        SERVICE · selector memory

        Finds a moved element by stored fix, text, label or role before asking a model, and saves what worked.

        Talks to

        • ← Executor
        • → PostgreSQL (saved fixes)
    5. EData

      • PostgreSQLpgvectorSTORE

        STORE · pgvector

        Projects, maps, plans, runs and healed selectors, with embeddings for retrieval.

        Talks to

        • ← Indexer (map · embeddings)
        • ← Self-healer (saved fixes)
      • Redisqueues · pub/subSTORE

        STORE · queues · pub/sub

        Backs the job queues, rate limits and live events.

      • Object storageS3 / R2STORE

        STORE · S3 / R2

        Screenshots, videos and DOM snapshots from every run.

        Talks to

        • ← Executor (evidence)
    6. FOutside

      • Claude · GPTrouted by taskEXTERNAL

        EXTERNAL · routed by task

        Different models for mapping, planning, running and reporting, chosen per task.

        Talks to

        • ← Planner (plan)
      • Playwright · Stagehandremote CDPEXTERNAL

        EXTERNAL · remote CDP

        A real headless browser over CDP, or a cloud browser when configured.

        Talks to

        • ← Executor (CDP)
      • Linear · Slackissues · alertsEXTERNAL

        EXTERNAL · issues · alerts

        Where failures become issues and alerts.

        Talks to

        • ← Reporter

    Connections

    1. Dashboard → API routes · HTTPS
    2. GitHub ⇢ API routes · webhooks
    3. API routes ⇢ indexing · enqueue
    4. indexing ⇢ Analyst · worker
    5. Analyst → Indexer
    6. Indexer → PostgreSQL · map · embeddings
    7. Analyst → Planner · system map
    8. Planner → Prioritiser
    9. Planner → Claude · GPT · plan
    10. Orchestrator ⇢ execution · run
    11. scheduler ⇢ Orchestrator · schedule
    12. execution ⇢ Executor · worker
    13. Executor → Playwright · Stagehand · CDP
    14. Executor → Self-healer
    15. Self-healer → PostgreSQL · saved fixes
    16. Executor → Object storage · evidence
    17. Executor ⇢ Live stream · screenshots
    18. Live stream ⇢ Dashboard · live
    19. Executor ⇢ reporting · results
    20. reporting ⇢ Reporter · worker
    21. Reporter → GitHub · PR check
    22. Reporter → Linear · Slack
    23. Claude → MCP server · MCP
    24. MCP server → Orchestrator · trigger

    Inside: the executor and self-healing

    Real apps change under their tests. The executor checks it’s allowed to run, orders tests by what they depend on, and when a button has moved it climbs a ladder of cheap fixes before it ever asks a model, then remembers the answer.

    1. ABefore

      • Environment checknever productionSERVICE

        SERVICE · never production

        Refuses production environments outright, checks the target is reachable, and decrypts the test credentials.

        Talks to

        • → Dependency order
      • Dependency orderparallel groupsSERVICE

        SERVICE · parallel groups

        Sorts tests by their prerequisites into groups that run in parallel, one group after another, breaking any cycles first.

        Talks to

        • ← Environment check
        • → Auth reuse
        • → API tests (contracts)
      • Auth reuseskip repeat loginsSERVICE

        SERVICE · skip repeat logins

        Once signed in, later tests skip their opening login steps. Tests of the login itself always start fresh.

        Talks to

        • ← Dependency order
        • → Step executor
      • API testsplain HTTPSERVICE

        SERVICE · plain HTTP

        Contract tests run without a browser or a model loop, falling back to the browser when they need the UI.

        Talks to

        • ← Dependency order (contracts)
    2. BRun

      • Step executorone step at a timeAI

        AI · one step at a time

        Acts on the page step by step and classifies any failure: missing element, not clickable, timeout, wrong assertion, wrong page.

        Talks to

        • ← Auth reuse
        • ← Provider guard (abort)
        • → Browser (act)
        • → Stored fix (broken selector)
        • → Flaky registry (retries)
        • → Baselines (on pass)
        • → Evidence
      • BrowserPlaywright · StagehandEXTERNAL

        EXTERNAL · Playwright · Stagehand

        A real browser over CDP, with Stagehand’s element and prompt caching when it is used.

        Talks to

        • ← Step executor (act)
      • Provider guardstop, don’t pile upSERVICE

        SERVICE · stop, don’t pile up

        If the AI provider fails on billing, auth or quota, the run stops rather than recording a false failure for every remaining test.

        Talks to

        • → Step executor (abort)
    3. CHeal

      • Stored fixapproved firstSERVICE

        SERVICE · approved first

        A fix that worked before for this selector, approved ones first, then others above 0.85 confidence.

        Talks to

        • ← Step executor (broken selector)
        • → Visible text (miss)
      • Visible textheuristicSERVICE

        SERVICE · heuristic

        Finds the element by the words on it.

        Talks to

        • ← Stored fix (miss)
        • → Label (miss)
      • Labelaria-labelSERVICE

        SERVICE · aria-label

        Finds it by its accessible label.

        Talks to

        • ← Visible text (miss)
        • → Role (miss)
      • Rolerole-basedSERVICE

        SERVICE · role-based

        Finds it by what it is: a button, a link, a field.

        Talks to

        • ← Label (miss)
        • → Model (miss)
      • Modelselector sub-agentAI

        AI · selector sub-agent

        Last resort: a model reads the page’s interactive elements and the selectors that failed, and proposes a new one.

        Talks to

        • ← Role (miss)
        • → Selector memory (saved)
    4. DAfter

      • Selector memorysaved fixesSTORE

        STORE · saved fixes

        Every heal is stored with its strategy and confidence, so the next run starts from it.

        Talks to

        • ← Model (saved)
      • Flaky registryquarantineSERVICE

        SERVICE · quarantine

        A test that fails then passes with no code change is flaky, not broken; after five such flips with under half its recent runs passing, it is quarantined.

        Talks to

        • ← Step executor (retries)
      • Baselinesscreens · API shapesSTORE

        STORE · screens · API shapes

        After a passing run, screenshots and API response shapes are kept to compare the next run against.

        Talks to

        • ← Step executor (on pass)
      • Evidencescreens · video · DOMSTORE

        STORE · screens · video · DOM

        Everything a person needs to see what happened, kept per step.

        Talks to

        • ← Step executor

    Connections

    1. Environment check → Dependency order
    2. Dependency order → Auth reuse
    3. Dependency order → API tests · contracts
    4. Auth reuse → Step executor
    5. Provider guard → Step executor · abort
    6. Step executor → Browser · act
    7. Step executor → Stored fix · broken selector
    8. Stored fix → Visible text · miss
    9. Visible text → Label · miss
    10. Label → Role · miss
    11. Role → Model · miss
    12. Model → Selector memory · saved
    13. Step executor → Flaky registry · retries
    14. Step executor → Baselines · on pass
    15. Step executor → Evidence

    Two flows

    Testing your app

    Step through it and the parts it runs through light up above.

    By count

    agents: analyst, planner, executor, reporter
    4
    actions Claude can take in it
    7

    Notes

    1. N.1When a button moves, Orbit tries the cheap ways to find it first: its text, its label, its role. It only asks a model as a last resort, and it remembers the answer.
    2. N.2It can break things on purpose, like a dropped request or a slow server, to see how the app copes.
    Orbit website
  5. 01.5

    Thronos

    Agent operations platform. A team of AI agents that works on a schedule. They read a company’s systems, draft the work and bring every decision to a person to approve.

    Live · private

    Fig.A team of AI agents that does a company’s routine work on a schedule, remembers what it learns, and brings every decision to a person.

    Architecture

    1. AWeb

      • StageThree.js roomUI

        UI · Three.js room

        The home screen: each agent a node with live presence, lines where one hands work to another, an artifact shelf and a chat dock.

        Talks to

        • ← Live socket (live)
      • Decisionsj · k · a · rUI

        UI · j · k · a · r

        One queue for every pending approval, gate and proposal, triaged from the keyboard, with a log of what was settled today.

        Talks to

        • → Engine API (approve · reject)
      • LibraryartifactsUI

        UI · artifacts

        Every typed artifact an agent has produced, addressable by key.

      • Live socketsocket.ioREALTIME

        REALTIME · socket.io

        One shared connection per app; the Stage, chat and live thought streams all listen on it.

        Talks to

        • ← Redis (pub/sub)
        • → Stage (live)
      • Slackfast-path chatEXTERNAL

        EXTERNAL · fast-path chat

        Talk to the agents from Slack, answered by the cheaper runtime.

        Talks to

        • → Kernel (chat)
    2. BEngine

      • Engine APInode:httpSERVICE

        SERVICE · node:http

        The engine’s HTTP API, on Node’s own http module rather than a framework.

        Talks to

        • ← Decisions (approve · reject)
        • → Governance
      • SignalsGitHub · Linear · healthJOB

        JOB · GitHub · Linear · health

        Gatherers that collect what changed (code, tickets, business numbers, tool health, memory) before each tick.

        Talks to

        • → Heartbeat (what changed)
      • HeartbeatBullMQ · 12 lanesJOB

        JOB · BullMQ · 12 lanes

        Health hourly, the inbox every two hours, reviews each morning, weekly analysis, nightly research. Lanes that share resources never overlap, and a circuit breaker pauses an agent that keeps failing.

        Talks to

        • ← Team templates (seeds)
        • ← Signals (what changed)
        • → Orchestrator (tick)
        • → Kernel (cheap lanes)
        • → Autoresearch (nightly)
      • OrchestratorOpus · Agent SDKAI

        AI · Opus · Agent SDK

        The top-level agent. It reads the signals, opens and claims a task, and delegates to the specialists.

        Talks to

        • ← Heartbeat (tick)
        • → 14 sub-agents (delegates)
        • → Task loop (claims)
      • 14 sub-agentsHaiku · Sonnet · OpusAI

        AI · Haiku · Sonnet · Opus

        Sentinel, Analyst, Scribe, Custodian, Oracle, Architect, Strategist and the rest, each with its own model, tools, budget and yes-or-no checks.

        Talks to

        • ← Orchestrator (delegates)
        • → Agent runner
        • → Governance (proposals)
        • ← Autoresearch (prompts)
        • ← Self-healing (revisions)
        • → Anthropic · OpenRouter
      • KernelOpenRouter · cappedAI

        AI · OpenRouter · capped

        A second, cheaper runtime for the frequent lanes, with a hard budget per tick, a turn limit, and only the MCP servers that lane needs.

        Talks to

        • ← Heartbeat (cheap lanes)
        • → MCP registry (subset)
        • ← Slack (chat)
      • Team templatesfiveSERVICE

        SERVICE · five

        Seeds a team, its schedule and its autonomy defaults in one action.

        Talks to

        • → Heartbeat (seeds)
      • Governanceapprovals · autonomySERVICE

        SERVICE · approvals · autonomy

        Approval records and the autonomy mode (supervised, assisted or full) that decides what is approved automatically. New agents are capped at 20 per workspace and three a day.

        Talks to

        • ← Engine API
        • ← 14 sub-agents (proposals)
      • Agent runnerone run, start to endSERVICE

        SERVICE · one run, start to end

        Checks the budget, loads the agent’s past experience, filters its tools, runs it with a live thought stream, retries on failure, then writes the run to memory.

        Talks to

        • ← 14 sub-agents
        • → MCP registry (tools)
        • → Event mesh (output)
        • → Mnemos (write · recall)
        • → Costs (checks)
      • Task loopclaim · settleSERVICE

        SERVICE · claim · settle

        The work record. The engine claims a task before delegating and settles whatever is still open when a run ends, so the record is right even if an agent forgets.

        Talks to

        • ← Orchestrator (claims)
      • Event meshagent → agentREALTIME

        REALTIME · agent → agent

        Each run’s output is classified and published, so a Sentinel alert lands in the Orchestrator’s triage and an Architect deploy sets off a Sentinel check.

        Talks to

        • ← Agent runner (output)
        • → Redis (publish)
      • MCP registry~60 built-in toolsAI

        AI · ~60 built-in tools

        Assembles each agent’s tools from the healthy servers, minus the tools that agent is blocked from.

        Talks to

        • ← Agent runner (tools)
        • ← Kernel (subset)
        • → Dev tools (MCP)
        • → Company systems (MCP)
        • ← Integration hub (compiled)
      • Autoresearch03:00 nightlyJOB

        JOB · 03:00 nightly

        Simulates five outputs, grades them on yes-or-no checks, mutates the prompt, simulates five more, and promotes only at five percent better. Every experiment is logged.

        Talks to

        • ← Heartbeat (nightly)
        • → 14 sub-agents (prompts)
      • Self-healingbinary evalsJOB

        JOB · binary evals

        Scores every run and drafts a prompt revision when quality drops. A revision may change at most a fifth of the prompt, and after three failed revisions in a row a person is asked.

        Talks to

        • → 14 sub-agents (revisions)
      • Coststick · day · monthSERVICE

        SERVICE · tick · day · month

        Token budgets per agent per tick, per day and per month, under a global cap.

        Talks to

        • ← Agent runner (checks)
      • Integration hubspec → MCPSERVICE

        SERVICE · spec → MCP

        Compiles a REST or GraphQL connector from its spec into an in-process MCP server at install time.

        Talks to

        • → MCP registry (compiled)
        • ← Any API (spec)
    3. CMemory

      • Mnemosmemory serviceSERVICE

        SERVICE · memory service

        The memory, as its own service: written after every run, consolidated on a schedule, searched before the next. Drawn in full below.

        Talks to

        • ← Agent runner (write · recall)
        • → Neo4j
        • → PostgreSQL (vectors)
    4. DData

      • PostgreSQLPrisma · pgvectorSTORE

        STORE · Prisma · pgvector

        Agents, runs, tasks, approvals, budgets and experiments, plus the memory’s embeddings.

        Talks to

        • ← Mnemos (vectors)
      • Neo4jknowledge graphSTORE

        STORE · knowledge graph

        The graph of what the agents have learned.

        Talks to

        • ← Mnemos
      • RedisBullMQ · pub/subSTORE

        STORE · BullMQ · pub/sub

        The heartbeat’s queues and the event channels.

        Talks to

        • ← Event mesh (publish)
        • → Live socket (pub/sub)
    5. EReach

      • Anthropic · OpenRoutermodelsEXTERNAL

        EXTERNAL · models

        Claude through the Agent SDK; other models through OpenRouter.

        Talks to

        • ← 14 sub-agents
      • Dev toolsin-process MCPEXTERNAL

        EXTERNAL · in-process MCP

        GitHub, Linear and Railway: code, tickets and deploys.

        Talks to

        • ← MCP registry (MCP)
      • Company systemsHTTP MCPEXTERNAL

        EXTERNAL · HTTP MCP

        C0, ContentSphere and OutreachSphere, read through their own MCP servers.

        Talks to

        • ← MCP registry (MCP)
      • Any APIREST · GraphQLEXTERNAL

        EXTERNAL · REST · GraphQL

        Any API added through the hub.

        Talks to

        • → Integration hub (spec)

    Connections

    1. Decisions → Engine API · approve · reject
    2. Engine API → Governance
    3. Team templates → Heartbeat · seeds
    4. Signals → Heartbeat · what changed
    5. Heartbeat ⇢ Orchestrator · tick
    6. Heartbeat ⇢ Kernel · cheap lanes
    7. Heartbeat ⇢ Autoresearch · nightly
    8. Orchestrator → 14 sub-agents · delegates
    9. Orchestrator → Task loop · claims
    10. 14 sub-agents → Agent runner
    11. Agent runner → MCP registry · tools
    12. Agent runner ⇢ Event mesh · output
    13. Agent runner → Mnemos · write · recall
    14. Agent runner → Costs · checks
    15. Kernel → MCP registry · subset
    16. Slack → Kernel · chat
    17. 14 sub-agents → Governance · proposals
    18. Autoresearch ⇢ 14 sub-agents · prompts
    19. Self-healing ⇢ 14 sub-agents · revisions
    20. MCP registry → Dev tools · MCP
    21. MCP registry → Company systems · MCP
    22. Integration hub → MCP registry · compiled
    23. Any API → Integration hub · spec
    24. Mnemos → Neo4j
    25. Mnemos → PostgreSQL · vectors
    26. Event mesh ⇢ Redis · publish
    27. Redis ⇢ Live socket · pub/sub
    28. Live socket ⇢ Stage · live
    29. 14 sub-agents → Anthropic · OpenRouter

    Inside: the memory

    Memory isn’t a log. Everything an agent produces is read for what it’s about, merged with what is already known, consolidated every six hours, faded when unused, and searched by meaning, keyword and connection when it’s needed again.

    1. AIn

      • Run outputsuccessful runsSERVICE

        SERVICE · successful runs

        What an agent produced, sent to memory after the run.

        Talks to

        • → Extract
      • Experienceevery runSERVICE

        SERVICE · every run

        A record of each run, failures included, so an agent can learn from what it has done.

        Talks to

        • → Knowledge graph (Experience node)
      • Documentsfiles · URLs · YouTubeSERVICE

        SERVICE · files · URLs · YouTube

        Outside material ingested on request.

        Talks to

        • → Extract
      • From toolsMCP ingestAI

        AI · MCP ingest

        Anything an agent chooses to remember through its memory tools.

        Talks to

        • → Extract
      • Scenariosworld modelsSERVICE

        SERVICE · world models

        A seed document becomes a model: actors with interests, tensions between them, dynamics and assumptions.

        Talks to

        • → Knowledge graph (world model)
    2. BWrite

      • Extractontology-awareAI

        AI · ontology-aware

        Pulls out entities and relationships using the known types and their properties. Runs on a local model when one is available, Haiku otherwise.

        Talks to

        • ← Run output
        • ← Documents
        • ← From tools
        • → Deduplicate
      • Deduplicatespelling · meaningSERVICE

        SERVICE · spelling · meaning

        Matches each entity to one already known: by fuzzy name (bigram similarity of 0.75 or more), then by meaning.

        Talks to

        • ← Extract
        • → Score
      • Scoreconfidence · half-lifeSERVICE

        SERVICE · confidence · half-life

        Confidence comes from the source; lifespan from the type: 7 days for a signal, 90 for a client, 365 for a principle. Use keeps a memory fresh.

        Talks to

        • ← Deduplicate
        • → Store
      • Storemerge · never dropSERVICE

        SERVICE · merge · never drop

        Writes nodes idempotently with bounded concurrency. If extraction fails, the raw text is kept as an observation rather than lost.

        Talks to

        • ← Score
        • → Embed
        • → Knowledge graph (MERGE)
      • Embed1536 dimensionsAI

        AI · 1536 dimensions

        Embeds each node for search. In production a failed embedding is an error, never a placeholder that would quietly poison recall.

        Talks to

        • ← Store
        • → Connect
        • → Embeddings
      • Connectauto-linkSERVICE

        SERVICE · auto-link

        Links new nodes to related ones already in the graph.

        Talks to

        • ← Embed
        • → Knowledge graph (edges)
    3. CStores

      • Knowledge graphL0 raw · L1 distilledSTORE

        STORE · L0 raw · L1 distilled

        Nineteen core kinds of memory in Neo4j (new kinds can appear), from signals and bugs to decisions and principles, each fact able to say when it became true and when it stopped.

        Talks to

        • ← Experience (Experience node)
        • ← Scenarios (world model)
        • ← Store (MERGE)
        • ← Connect (edges)
        • ← Compression (L0 → L1)
        • ← Reflection (insights)
        • ← Summaries
        • ← Past experience (experiences)
      • EmbeddingspgvectorSTORE

        STORE · pgvector

        The vectors behind semantic search, cleaned up when a node is archived so it can’t haunt results.

        Talks to

        • ← Embed
        • ← Decay (archive)
        • ← Hybrid search (dense)
    4. DKeep

      • Compressionevery 6 hJOB

        JOB · every 6 h

        Clusters similar memories, checks the cluster really is similar (cosine 0.65 or more), and replaces it with one distilled L1 memory. High-value memories are never compressed.

        Talks to

        • → Knowledge graph (L0 → L1)
      • Reflectionafter compressionJOB

        JOB · after compression

        Reads 12 to 60 recent observations, decisions and experiences together and writes up to eight new insights or patterns.

        Talks to

        • → Knowledge graph (insights)
      • SummariesrollingJOB

        JOB · rolling

        Keeps a short summary on each node from its properties and its recent connections.

        Talks to

        • → Knowledge graph
      • DecaydailyJOB

        JOB · daily

        Recomputes each memory’s freshness from its half-life and last use; below 0.05 it is archived. A node with no timestamp is left alone, never archived on a guess.

        Talks to

        • → Embeddings (archive)
    5. ERecall

      • Past experiencebefore each runSERVICE

        SERVICE · before each run

        The agent’s own past runs, ranked by overlap with the task at hand, added to its prompt so it builds a view from what it has actually done.

        Talks to

        • → Knowledge graph (experiences)
      • HyDEhypothetical answerAI

        AI · hypothetical answer

        For abstract questions, drafts a likely answer and searches with that instead. Direct lookups skip it.

        Talks to

        • → Hybrid search
      • Hybrid searchdense + keyword · RRFSERVICE

        SERVICE · dense + keyword · RRF

        Runs semantic and keyword search and fuses the two rankings.

        Talks to

        • ← HyDE
        • → Embeddings (dense)
        • → Graph walk
      • Graph walk2 hopsSERVICE

        SERVICE · 2 hops

        Expands each hit two steps through the graph, so related context comes along.

        Talks to

        • ← Hybrid search
        • → Filters
      • Filterstime · type · truthSERVICE

        SERVICE · time · type · truth

        Drops archived and invalidated facts, and can answer as of a past date.

        Talks to

        • ← Graph walk
        • → Rerank
      • Rerankagainst the questionAI

        AI · against the question

        A model reorders the shortlist against the original question, not the expanded one.

        Talks to

        • ← Filters

    Connections

    1. Run output → Extract
    2. Documents → Extract
    3. From tools → Extract
    4. Experience → Knowledge graph · Experience node
    5. Scenarios → Knowledge graph · world model
    6. Extract → Deduplicate
    7. Deduplicate → Score
    8. Score → Store
    9. Store → Embed
    10. Embed → Connect
    11. Store → Knowledge graph · MERGE
    12. Embed → Embeddings
    13. Connect → Knowledge graph · edges
    14. Compression ⇢ Knowledge graph · L0 → L1
    15. Reflection ⇢ Knowledge graph · insights
    16. Summaries ⇢ Knowledge graph
    17. Decay ⇢ Embeddings · archive
    18. Past experience → Knowledge graph · experiences
    19. HyDE → Hybrid search
    20. Hybrid search → Embeddings · dense
    21. Hybrid search → Graph walk
    22. Graph walk → Filters
    23. Filters → Rerank

    Two flows

    How an agent remembers

    Step through it and the parts it runs through light up above.

    By count

    agent roles
    15
    heartbeat lanes
    12
    built-in tools
    ~60
    kinds of memory, each with its own lifespan
    19
    team templates
    5
    autonomy modes
    3

    Notes

    1. N.1Every kind of memory has its own lifespan. A signal fades in a week, a client in three months, a principle in a year, and anything that keeps getting used stays fresh.
    2. N.2Memory can answer “what did we believe in March?” Facts carry when they became true and when they stopped, and recall can ask about a past date.
    3. N.3If a model can’t make sense of something, it is still kept as a raw note. Nothing an agent learns is silently dropped.
    4. N.4The agents react to each other. A Sentinel alert lands in the Orchestrator’s triage, and an Architect deploy sets off a Sentinel check.
    Thronos website
  6. 01.6

    Contractor Toolkit

    Open-source Claude Code plugins. Free Claude Code plugins for contractors. Tell Claude about your company once, and it drafts estimates, bid packages, RFIs and daily logs in your brand.

    Live · open source

    Fig.Free Claude Code plugins for contractors: tell Claude about your company once, and it writes the paperwork in your brand.

    Architecture

    1. AInstall

      • Your forkgit repoEXTERNAL

        EXTERNAL · git repo

        Fork the repo, configure it once, and push it to a private repo. Teammates clone it and get the company’s skills with no setup.

        Talks to

        • → Claude Code (marketplace add)
      • Claude Codeplugin marketplaceEXTERNAL

        EXTERNAL · plugin marketplace

        The marketplace file registers six plugins; each installs on its own.

        Talks to

        • ← Your fork (marketplace add)
        • → /initialize (installs)
      • claude.ai · Coworkskill zipsEXTERNAL

        EXTERNAL · skill zips

        The same skills as standalone packages, for the web app.

        Talks to

        • ← Skill packages (upload)
    2. BSetup

      • /initializeten sectionsUI

        UI · ten sections

        A conversational interview, one section at a time. Each answer is written into the template tokens of every skill that uses it; re-run one section and only its tokens change.

        Talks to

        • ← Claude Code (installs)
        • → Company config (writes)
      • Company configlocal MarkdownSTORE

        STORE · local Markdown

        The company’s answers, kept in local config. Capabilities are read at run time rather than substituted.

        Talks to

        • ← /initialize (writes)
        • → contractor-brand (tokens)
        • → contractor-estimating (defaults)
      • contractor-brandcolors · fonts · voiceSERVICE

        SERVICE · colors · fonts · voice

        Keeps every document on-brand: colors, type, logos and how the company sounds.

        Talks to

        • ← Company config (tokens)
        • → contractor-docs (brand)
    3. CSkills

      • contractor-estimating13 skillsSERVICE

        SERVICE · 13 skills

        The preconstruction pipeline: ROM, plan takeoff, conceptual budget, scope check, sub bid packages, bid leveling, formal bid, contract and subcontract.

        Talks to

        • ← Company config (defaults)
        • → estimate-reviewer (review)
        • → scope-writer (scope)
        • → sub-packager (packages)
        • → contractor-docs (render)
      • contractor-extras13 skillsSERVICE

        SERVICE · 13 skills

        Everyday paperwork: proposals, RFIs and RFI logs, submittals, daily logs, look-aheads, change orders, punch lists, incident reports.

        Talks to

        • → contractor-docs
      • contractor-subs4 skillsSERVICE

        SERVICE · 4 skills

        For subcontractors: quotes, change order requests, T&M tickets and pay applications.

      • contractor-docsdocument engineSERVICE

        SERVICE · document engine

        Renders everything as HTML or DOCX in the company’s brand.

        Talks to

        • ← contractor-brand (brand)
        • ← contractor-estimating (render)
        • ← contractor-extras
        • → Documents (Write)
      • estimate-revieweragentAI

        AI · agent

        Checks an estimate before documents are generated.

        Talks to

        • ← contractor-estimating (review)
      • scope-writeragentAI

        AI · agent

        Writes project-specific scope by CSI division.

        Talks to

        • ← contractor-estimating (scope)
      • sub-packageragentAI

        AI · agent

        Builds one self-contained bid invitation per trade.

        Talks to

        • ← contractor-estimating (packages)
      • Token guardPostToolUse hookJOB

        JOB · PostToolUse hook

        Runs after every file Claude writes. A finished HTML document that still has an unfilled {{TOKEN}} is blocked.

        Talks to

        • → Documents (guards)
    4. DOutput

      • DocumentsHTML · DOCXEXTERNAL

        EXTERNAL · HTML · DOCX

        Estimates, bids, contracts, logs and the rest, ready to send.

        Talks to

        • ← contractor-docs (Write)
        • ← Token guard (guards)
      • Release validationPython checksJOB

        JOB · Python checks

        Checks manifests, inventory, resource paths and template tokens. Unconfigured templates fail; there is no switch to skip it.

        Talks to

        • → Skill packages (gate)
      • Skill packagesdist buildJOB

        JOB · dist build

        Builds the standalone zips, after validation passes and a person reviews them.

        Talks to

        • ← Release validation (gate)
        • → claude.ai · Cowork (upload)

    Connections

    1. Your fork → Claude Code · marketplace add
    2. Claude Code → /initialize · installs
    3. /initialize → Company config · writes
    4. Company config → contractor-brand · tokens
    5. Company config → contractor-estimating · defaults
    6. contractor-estimating → estimate-reviewer · review
    7. contractor-estimating → scope-writer · scope
    8. contractor-estimating → sub-packager · packages
    9. contractor-brand → contractor-docs · brand
    10. contractor-estimating → contractor-docs · render
    11. contractor-extras → contractor-docs
    12. contractor-docs → Documents · Write
    13. Token guard ⇢ Documents · guards
    14. Release validation → Skill packages · gate
    15. Skill packages → claude.ai · Cowork · upload

    Inside: the setup wizard and its safety gate

    Setup rewrites a company’s own files, so it is run like a change to production: planned, shown as an exact diff, approved, backed up, applied, and checked byte for byte, with nothing ever reported as done that wasn’t.

    1. AInterview

      • Ten sectionsone at a timeUI

        UI · one at a time

        Company, services, brand colors, type, logos, voice, contact, ideal client, capabilities and estimating defaults, each with a default you can accept.

        Talks to

        • → Staged answers
      • Section re-runonly its tokensUI

        UI · only its tokens

        Re-run one section and only that section’s values change.

        Talks to

        • → Staged answers
    2. BPlan

      • Staged answersoutside live filesSERVICE

        SERVICE · outside live files

        Answers and full proposed files are staged away from the real ones and validated first.

        Talks to

        • ← Ten sections
        • ← Section re-run
        • → Change plan
      • Change planbefore hashes · contextsSTORE

        STORE · before hashes · contexts

        Every file, its hash before, the exact text and context of each replacement, and the fields that change. No global find-and-replace.

        Talks to

        • ← Staged answers
        • → Diff + approval
      • Diff + approvalbound to the planUI

        UI · bound to the plan

        The exact diff is shown, and approval is tied to that plan; change the plan and it needs approving again.

        Talks to

        • ← Change plan
        • → Snapshot (approved)
    3. CApply

      • Snapshotbackups firstJOB

        JOB · backups first

        Backs up every target and verifies the backups before anything is touched.

        Talks to

        • ← Diff + approval (approved)
        • → Recheck
      • Recheckstale hash voids itSERVICE

        SERVICE · stale hash voids it

        Checks each file still matches its hash from the plan. If it changed since approval, the approval no longer counts.

        Talks to

        • ← Snapshot
        • → Exact edits
      • Exact editsper file, per contextSERVICE

        SERVICE · per file, per context

        Applies only the approved edits.

        Talks to

        • ← Recheck
        • → Readback
      • Readbackafter hashes · fieldsSERVICE

        SERVICE · after hashes · fields

        Reopens every changed file and compares it to the approved result, byte for byte and field by field.

        Talks to

        • ← Exact edits
        • → Receipt (pass)
        • → Needs a person (fail)
    4. DOutcome

      • Needs a personnever a false successSERVICE

        SERVICE · never a false success

        Any failure, interruption or missing backup stops here, with the backups kept.

        Talks to

        • ← Readback (fail)
        • → Resume
      • Resumebefore · after · conflictSERVICE

        SERVICE · before · after · conflict

        On restart each file is classed from its actual bytes; finished edits are never repeated, and nothing is rolled back over someone else’s changes.

        Talks to

        • ← Needs a person
      • Receiptmeasured, not claimedSTORE

        STORE · measured, not claimed

        Reports only what was measured: sections, changed files, checkpoint and any tokens still unfilled.

        Talks to

        • ← Readback (pass)

    Connections

    1. Ten sections → Staged answers
    2. Section re-run → Staged answers
    3. Staged answers → Change plan
    4. Change plan → Diff + approval
    5. Diff + approval → Snapshot · approved
    6. Snapshot → Recheck
    7. Recheck → Exact edits
    8. Exact edits → Readback
    9. Readback → Receipt · pass
    10. Readback → Needs a person · fail
    11. Needs a person → Resume

    Two flows

    An idea becomes a formal bid

    Step through it and the parts it runs through light up above.

    By count

    plugins
    6
    skills
    38
    agents
    3
    setup sections
    10

    Notes

    1. N.1Setup is a ten-minute interview: name, colors, logos, how you talk, who your clients are. Every document after that uses it.
    2. N.2Every skill is plain Markdown. You can open one and change how it works.
    3. N.3Push your configured copy to a private repo and your whole team gets your company’s skills with no setup.
    4. N.4A finished document can’t be saved with a blank {{TOKEN}} left in it.
    Contractor Toolkit website
  7. 01.7

    ContentSphere

    Content system. Each client’s newsletters, LinkedIn posts and web copy, planned from their brand and drafted from prompts written for them. The client approves every piece.

    Live · internal

    Fig.A content studio for Formwork’s clients: newsletters, LinkedIn posts and web copy, planned from each brand and approved by the client.

    Architecture

    1. APeople

      • Writers · adminsNext.js 15UI

        UI · Next.js 15

        Formwork’s content team: brand, plans, pieces, approvals and the calendar, one client at a time.

        Talks to

        • → Content pieces (edit)
      • Client portalper clientUI

        UI · per client

        Clients read their pieces, comment and approve.

        Talks to

        • → Review (approve)
      • ClaudeMCP clientEXTERNAL

        EXTERNAL · MCP client

        Claude, connected with a scoped key, working the same content through MCP.

        Talks to

        • → MCP server (MCP · key)
    2. BApp

      • Brand strategyversionedSERVICE

        SERVICE · versioned

        Each client’s positioning, pillars and voice, with every version kept.

        Talks to

        • → Personas
        • → Content plans (informs)
      • Personasaudiences · frameworksSERVICE

        SERVICE · audiences · frameworks

        Who the client is talking to, and the messaging frameworks for each audience.

        Talks to

        • ← Brand strategy
      • Transcriptsclient callsSERVICE

        SERVICE · client calls

        Calls with the client, kept as source material for topics.

        Talks to

        • → Content plans (topics)
      • Content plansmonthlySERVICE

        SERVICE · monthly

        The month’s topics per channel, drawn from the strategy and the calls.

        Talks to

        • ← Brand strategy (informs)
        • ← Transcripts (topics)
        • → Content pieces (pieces)
        • → C0 (deliverables)
      • MCP server112 tools · scoped keysAI

        AI · 112 tools · scoped keys

        A fresh server per request, with only the tool groups the key’s scopes allow. Keys are stored hashed.

        Talks to

        • ← Claude (MCP · key)
        • ← Six specialists (own tools)
      • Prompt matrixclient × content typeSERVICE

        SERVICE · client × content type

        The instructions for every pairing of client and kind of content.

        Talks to

        • → Generation (instructions)
      • Generationdraft · rewriteAI

        AI · draft · rewrite

        Drafts and rewrites pieces from the matrix, with the client’s context.

        Talks to

        • ← Prompt matrix (instructions)
        • → Content pieces (drafts)
        • → Claude · OpenAI (generate)
      • Content piecesdrafts · versionsSERVICE

        SERVICE · drafts · versions

        One piece per channel, with versioned drafts, comments and a status.

        Talks to

        • ← Content plans (pieces)
        • ← Generation (drafts)
        • ← Writers · admins (edit)
        • → Review
        • → PostgreSQL (SQL)
      • Reviewteam → clientSERVICE

        SERVICE · team → client

        Internal review, then the client’s. A piece can’t enter review without real draft copy.

        Talks to

        • ← Content pieces
        • ← Client portal (approve)
        • → Calendar (approved)
        • → Slack (notify)
      • CalendarscheduledSERVICE

        SERVICE · scheduled

        Approved pieces, on the dates they go out.

        Talks to

        • ← Review (approved)
    3. CAgents

      • OrchestratorClaude Agent SDKAI

        AI · Claude Agent SDK

        The in-app agent. It hands work to the right specialist.

        Talks to

        • → Six specialists (delegates)
        • → Claude · OpenAI
      • Six specialistsstrategy → campaignsAI

        AI · strategy → campaigns

        Specialists from strategy and writing to prompts and campaigns, each limited to the tools its job needs, plus one tool to hand work to another.

        Talks to

        • ← Orchestrator (delegates)
        • → MCP server (own tools)
    4. DData

      • PostgreSQLPrismaSTORE

        STORE · Prisma

        Clients, strategy, plans, pieces, versions and comments.

        Talks to

        • ← Content pieces (SQL)
    5. EOutside

      • Claude · OpenAImodelsEXTERNAL

        EXTERNAL · models

        The models behind drafting and the agents.

        Talks to

        • ← Generation (generate)
        • ← Orchestrator
      • C0deliverables APIEXTERNAL

        EXTERNAL · deliverables API

        Formwork’s operations system, where each piece is also a tracked deliverable.

        Talks to

        • ← Content plans (deliverables)
      • SlacknotificationsEXTERNAL

        EXTERNAL · notifications

        Tells the team when work needs them.

        Talks to

        • ← Review (notify)

    Connections

    1. Brand strategy → Personas
    2. Brand strategy → Content plans · informs
    3. Transcripts → Content plans · topics
    4. Content plans → Content pieces · pieces
    5. Prompt matrix → Generation · instructions
    6. Generation → Content pieces · drafts
    7. Generation → Claude · OpenAI · generate
    8. Writers · admins → Content pieces · edit
    9. Content pieces → Review
    10. Client portal → Review · approve
    11. Review → Calendar · approved
    12. Review ⇢ Slack · notify
    13. Content plans → C0 · deliverables
    14. Claude → MCP server · MCP · key
    15. Orchestrator → Six specialists · delegates
    16. Six specialists → MCP server · own tools
    17. Orchestrator → Claude · OpenAI
    18. Content pieces → PostgreSQL · SQL

    Inside: specialist agents and the prompt matrix

    The in-app agent isn’t one model with every tool. An orchestrator hands work to specialists that each see only their own tools, and every draft starts from instructions written for that client, that kind of content and that reader.

    1. AAsk

      • Agent chatin the appUI

        UI · in the app

        Where the team asks for plans, drafts and campaigns in plain words.

        Talks to

        • → Orchestrator
      • ClaudeMCP clientEXTERNAL

        EXTERNAL · MCP client

        Claude outside the app, using the same tools through a scoped key.

        Talks to

        • → Tool subsets (MCP)
    2. BLead

      • Orchestratorstreams · tool roundsAI

        AI · streams · tool rounds

        Streams its answer, runs tool calls in rounds up to a limit, and delegates to one of six specialists.

        Talks to

        • ← Agent chat
        • ← Agent prompts (instructions)
        • → Strategist (delegates)
        • → Creator
        • → Campaign manager
        • → Prompt engineer
      • Agent promptseditableSTORE

        STORE · editable

        Each agent’s instructions live in the database, so they can be tuned without a deploy, with built-in defaults if the database is unavailable.

        Talks to

        • → Orchestrator (instructions)
    3. CSpecialists

      • Strategistbrand · audiencesAI

        AI · brand · audiences

        Brand strategy, audiences, messaging frameworks, pillars and client context.

        Talks to

        • ← Orchestrator (delegates)
      • Creatorpieces · draftsAI

        AI · pieces · drafts

        Writes and manages pieces: LinkedIn posts, newsletters, case studies, articles.

        Talks to

        • ← Orchestrator
        • → Client prompts (reads)
      • Campaign managerplans · calendar · shootsAI

        AI · plans · calendar · shoots

        Content plans, the editorial calendar, photo and video shoots, assets, and updates from construction projects.

        Talks to

        • ← Orchestrator
      • Prompt engineerprompts · personasAI

        AI · prompts · personas

        Designs the prompt matrix and personas, and tunes generation quality.

        Talks to

        • ← Orchestrator
        • → Tool subsets
      • Tool subsetsper specialistSERVICE

        SERVICE · per specialist

        Each specialist gets its own list of tools plus one to hand work to another; nothing else is offered to it.

        Talks to

        • ← Claude (MCP)
        • ← Prompt engineer
    4. DMatrix

      • Client promptsclient · type · personaSTORE

        STORE · client · type · persona

        Instructions written for one client and one kind of content, optionally for one persona. These win when they exist.

        Talks to

        • ← Creator (reads)
        • → Draft (first choice)
      • Default matrixfallbackSTORE

        STORE · fallback

        The house prompts, used when a client has none of its own.

        Talks to

        • → Draft (fallback)
      • Drafttraced to its promptAI

        AI · traced to its prompt

        The generated draft records which prompt produced it, so a bad draft can be traced to its instructions.

        Talks to

        • ← Client prompts (first choice)
        • ← Default matrix (fallback)

    Connections

    1. Agent chat → Orchestrator
    2. Agent prompts → Orchestrator · instructions
    3. Orchestrator → Strategist · delegates
    4. Orchestrator → Creator
    5. Orchestrator → Campaign manager
    6. Orchestrator → Prompt engineer
    7. Claude → Tool subsets · MCP
    8. Prompt engineer → Tool subsets
    9. Creator → Client prompts · reads
    10. Client prompts → Draft · first choice
    11. Default matrix → Draft · fallback

    Two flows

    A topic becomes a published piece

    Step through it and the parts it runs through light up above.

    By count

    specialist agents
    6
    rounds of review: team, then client
    2
    actions Claude can take in it
    112

    Notes

    1. N.1Prompts are a matrix of client by kind of content. A newsletter for one contractor and a LinkedIn post for another start from different instructions.
    2. N.2Six specialist agents, from strategy to campaigns. Each gets only the tools its job needs, plus one to hand work to another.
    ContentSphere website
  8. 01.8

    C0

    Internal operations system. Runs Formwork day to day: clients, projects, tasks and invoices in one place, synced with the books. After each meeting, Claude drafts the follow-up tasks.

    Live · runs Formwork

    Fig.How Formwork runs: sales, clients, work, money and meetings in one place, with a portal for each kind of person.

    Architecture

    1. APortals

      • ExecutiveportalUI

        UI · portal

        The whole firm: money, clients, people and objectives.

        Talks to

        • → Middleware (cookie)
      • Manager · memberportalsUI

        UI · portals

        Managers see their team; members see their own tasks and time.

      • ClientportalUI

        UI · portal

        Clients see their services, billing, content, outreach and tasks.

        Talks to

        • → Middleware
      • ProspectportalUI

        UI · portal

        A prospect’s own view of what Formwork offers them.

      • ClaudeMCP clientEXTERNAL

        EXTERNAL · MCP client

        Claude over MCP, with tools scoped to the person’s role.

        Talks to

        • → MCP server (MCP)
    2. BApp

      • MiddlewareJWT · role routesSERVICE

        SERVICE · JWT · role routes

        Checks the session cookie, routes each role to its portal, and catches a role that changed since sign-in.

        Talks to

        • ← Executive (cookie)
        • ← Client
        • → Clients (by role)
      • ProspectsproposalsSERVICE

        SERVICE · proposals

        Prospects and proposals, until one converts to a client.

        Talks to

        • → Clients (converts)
      • Clientsservices · healthSERVICE

        SERVICE · services · health

        Each client and the services they buy, with one health score from 0 to 100.

        Talks to

        • ← Middleware (by role)
        • ← Prospects (converts)
        • → Projects · tasks
        • → Invoices · expenses (bills)
        • → Sales & content (outreach · content)
      • Projects · taskstime logsSERVICE

        SERVICE · time logs

        The work for each service, with dependencies and time logged.

        Talks to

        • ← Clients
        • ← Task drafting (drafts)
        • → PostgreSQL (SQL)
        • → Airtable (dual write)
      • Invoices · expensespaymentsSERVICE

        SERVICE · payments

        Invoices, payments and expenses, allocated to clients and services.

        Talks to

        • ← Clients (bills)
        • ← Plaid (bank feeds)
        • ← Bank matching (matches)
      • MCP server250+ tools by roleAI

        AI · 250+ tools by role

        Tools composed by role: a client sees about ten, an executive over two hundred.

        Talks to

        • ← Claude (MCP)
        • ← Chat agent (catalogue)
        • → Knowledge base (kb tools)
      • MeetingstranscriptsSERVICE

        SERVICE · transcripts

        Each meeting and its transcript, with a badge until its drafted tasks are approved.

        Talks to

        • → Task drafting (transcript)
        • → Knowledge base (mined)
      • Task draftingClaudeAI

        AI · Claude

        Drafts follow-up tasks from a transcript, with the context around the meeting.

        Talks to

        • ← Meetings (transcript)
        • → Projects · tasks (drafts)
        • → Claude · OpenRouter
      • Knowledge basefacts · reviewAI

        AI · facts · review

        Claims mined from meetings, embedded and merged into facts. New ones are candidates until a second model verifies them.

        Talks to

        • ← Meetings (mined)
        • ← MCP server (kb tools)
      • Bank matchingconfidence tiersSERVICE

        SERVICE · confidence tiers

        Matches each cash line from the books to an invoice, a subscription or a person, with a confidence score. Only the surest can be approved in bulk.

        Talks to

        • ← QuickBooks (webhooks)
        • → Invoices · expenses (matches)
      • Chat agentsearch · describe · runAI

        AI · search · describe · run

        Above a threshold it gets a category index and three meta-tools instead of every schema, and loads only the tools it means to call.

        Talks to

        • → MCP server (catalogue)
    3. CJobs

      • Due-date checksscheduledJOB

        JOB · scheduled

        Flags tasks coming due and invoices gone overdue.

        Talks to

        • → Slack (alerts)
      • Scheduled emailscheduledJOB

        JOB · scheduled

        Sends reports and scheduled emails.

    4. DData

      • PostgreSQLprimary · PrismaSTORE

        STORE · primary · Prisma

        Where every read comes from.

        Talks to

        • ← Projects · tasks (SQL)
      • Airtabledual writeSTORE

        STORE · dual write

        Writes for tasks, time and money also land here, so the rollups people already use stay right.

        Talks to

        • ← Projects · tasks (dual write)
    5. EOutside

      • QuickBooksOAuth · webhooksEXTERNAL

        EXTERNAL · OAuth · webhooks

        The books. Its webhooks bring each change across.

        Talks to

        • → Bank matching (webhooks)
      • Plaidbank feeds · webhooksEXTERNAL

        EXTERNAL · bank feeds · webhooks

        Live bank balances and transactions.

        Talks to

        • → Invoices · expenses (bank feeds)
      • Sales & contentFormwork’s own appsEXTERNAL

        EXTERNAL · Formwork’s own apps

        OutreachSphere and ContentSphere, read for each client’s outreach and content.

        Talks to

        • ← Clients (outreach · content)
      • SlackalertsEXTERNAL

        EXTERNAL · alerts

        Where the due-date and overdue alerts land.

        Talks to

        • ← Due-date checks (alerts)
      • Claude · OpenRoutermodelsEXTERNAL

        EXTERNAL · models

        The models behind drafting, the knowledge base and the agent.

        Talks to

        • ← Task drafting

    Connections

    1. Executive → Middleware · cookie
    2. Client → Middleware
    3. Middleware → Clients · by role
    4. Prospects → Clients · converts
    5. Clients → Projects · tasks
    6. Clients → Invoices · expenses · bills
    7. Meetings → Task drafting · transcript
    8. Task drafting → Projects · tasks · drafts
    9. Meetings → Knowledge base · mined
    10. Task drafting → Claude · OpenRouter
    11. QuickBooks ⇢ Bank matching · webhooks
    12. Plaid ⇢ Invoices · expenses · bank feeds
    13. Bank matching → Invoices · expenses · matches
    14. Claude → MCP server · MCP
    15. Chat agent → MCP server · catalogue
    16. MCP server → Knowledge base · kb tools
    17. Projects · tasks → PostgreSQL · SQL
    18. Projects · tasks ⇢ Airtable · dual write
    19. Due-date checks ⇢ Slack · alerts
    20. Clients → Sales & content · outreach · content

    Inside: meetings, tasks and what Formwork knows

    A meeting does two jobs. It becomes tasks people approve, and it teaches the firm something: claims are pulled out, matched to the people and companies they’re about, deduplicated, checked by a second model, and fed back into the next meeting about that client.

    1. AIn

      • Transcriptper meetingUI

        UI · per meeting

        The meeting’s transcript, internal or with a client.

        Talks to

        • → Meeting context
      • Meeting contextpeople · services · goalsSERVICE

        SERVICE · people · services · goals

        Who was there, the client and their active services, and the firm’s current objectives and projects, so tasks land in the right place.

        Talks to

        • ← Transcript
        • → Tasks + summary
      • Account memorywhat we already knowAI

        AI · what we already know

        What the firm already knows about this client, injected before analysis. A knowledge-base failure never blocks the meeting.

        Talks to

        • → Tasks + summary (injected)
        • → Search (account spine)
    2. BAnalysis

      • Tasks + summaryClaude · in parallelAI

        AI · Claude · in parallel

        Writes the meeting summary and the follow-up tasks at the same time, each with an assignee, a service, a project and a due date.

        Talks to

        • ← Meeting context
        • ← Account memory (injected)
        • → Approval (drafts)
        • → Slack
        • → Claim extraction (transcript)
      • Approvalbadge until approvedUI

        UI · badge until approved

        Drafted tasks wait for a person. Until they are approved the meeting shows a badge.

        Talks to

        • ← Tasks + summary (drafts)
      • Slacksummary · tasksEXTERNAL

        EXTERNAL · summary · tasks

        The summary and the drafted tasks are posted to Slack.

        Talks to

        • ← Tasks + summary
    3. CLearn

      • Claim extractionHaiku · Sonnet if unsureAI

        AI · Haiku · Sonnet if unsure

        Picks out claims worth keeping about the industry, the client or the business, tagged from a fixed vocabulary of 22 topics. Internal meetings need more confidence to count.

        Talks to

        • ← Tasks + summary (transcript)
        • → Entity resolution (mentions)
        • → Dedup (claims)
      • Entity resolutionnames · aliasesSERVICE

        SERVICE · names · aliases

        Maps “Logan”, “Logan Smith” and “chief estimator” to the same person, following merges; a new name starts as a candidate for review.

        Talks to

        • ← Claim extraction (mentions)
        • → Entity graph
      • Deduphash · cosine 0.92SERVICE

        SERVICE · hash · cosine 0.92

        An exact restatement or a near-duplicate becomes a new citation on the existing fact instead of a new row.

        Talks to

        • ← Claim extraction (claims)
        • → Facts
      • Auto-reviewsecond modelAI

        AI · second model

        Verifies or rejects new facts. Nothing is verified on the way in; borderline ones stay for a person to spot-check.

        Talks to

        • → Facts (verify)
      • Latest winssupersededSERVICE

        SERVICE · superseded

        When a newer claim replaces an old one, the old one is marked superseded rather than deleted.

        Talks to

        • → Facts
    4. DRecall

      • Factspgvector · 1024-dSTORE

        STORE · pgvector · 1024-d

        Canonical facts with their citations, embedded with one locked model whose name is stored beside each vector for future migrations.

        Talks to

        • ← Dedup
        • ← Auto-review (verify)
        • ← Latest wins
        • ← Search
      • Entity graphtyped edgesSTORE

        STORE · typed edges

        People, companies and projects, linked to the account they belong to.

        Talks to

        • ← Entity resolution
      • Searchverified-onlySERVICE

        SERVICE · verified-only

        Semantic search with metadata filters, verified facts only by default so agents don’t retrieve noise, plus a keyed account spine, newest first.

        Talks to

        • → Facts
        • ← kb tools
        • ← Account memory (account spine)
      • kb toolsMCPAI

        AI · MCP

        Search, expand an entity, add or verify a fact, and the review queue, for any agent.

        Talks to

        • → Search

    Connections

    1. Transcript → Meeting context
    2. Meeting context → Tasks + summary
    3. Account memory → Tasks + summary · injected
    4. Tasks + summary → Approval · drafts
    5. Tasks + summary ⇢ Slack
    6. Tasks + summary → Claim extraction · transcript
    7. Claim extraction → Entity resolution · mentions
    8. Claim extraction → Dedup · claims
    9. Entity resolution → Entity graph
    10. Dedup → Facts
    11. Auto-review ⇢ Facts · verify
    12. Latest wins → Facts
    13. Search → Facts
    14. kb tools → Search
    15. Account memory → Search · account spine

    Two flows

    A meeting becomes work

    Step through it and the parts it runs through light up above.

    By count

    portals: executive, manager, member, client, prospect
    5
    actions Claude can take in it
    250+

    Notes

    1. N.1Client health is one number from 0 to 100, computed in one place, so the members list, the invoice header and the exec dashboard never disagree.
    2. N.2Clients get their own portal with their services, billing, content, outreach and tasks.
    3. N.3Bank lines are matched to invoices and people with a confidence score. Only the surest matches can be approved in bulk.
  9. 01.9

    Delta Portal

    Custom enterprise platform. Delta Construction’s project system, which replaced Procore: RFIs, bidding, contracts, chat and Autodesk files. Architects and subs reply from a link.

    Live · Delta Construction

    Fig.Delta Construction’s project system, for its own team and for the architects and subs it works with.

    Architecture

    1. APeople

      • Delta’s teamweb · phones · iPadsUI

        UI · web · phones · iPads

        Delta’s project managers, engineers and field staff, in the app.

        Talks to

        • → Public API (HTTPS)
        • → Live sockets (live)
      • Architects & subsemailed linksUI

        UI · emailed links

        People outside Delta. They answer RFIs and submit bids from a link, without an account.

        Talks to

        • → Public API (emailed link)
    2. BGateway

      • Public APISpring Boot · JWTSERVICE

        SERVICE · Spring Boot · JWT

        Checks who is asking and forwards each request with their identity. Link tokens are checked here too.

        Talks to

        • ← Delta’s team (HTTPS)
        • ← Architects & subs (emailed link)
        • → Project (REST)
        • → Bid packages (REST)
      • Live socketsWebSocketsREALTIME

        REALTIME · WebSockets

        Pushes chat and notifications to open apps as they happen.

        Talks to

        • ← Delta’s team (live)
        • ← Redis (pub/sub)
    3. CProject

      • Projectteam · directorySERVICE

        SERVICE · team · directory

        Everything hangs off a project and the companies and people on it.

        Talks to

        • ← Public API (REST)
        • → Bid packages (packages)
        • → PostgreSQL (SQL)
        • ← Procore (import)
      • RFIsball in courtSERVICE

        SERVICE · ball in court

        Questions to the design team, with the ball moving between companies as the RFI is answered.

      • Submittalsrevise & resubmitSERVICE

        SERVICE · revise & resubmit

        Submittals go round in revisions until approved.

      • Drawingssheets · revisionsSERVICE

        SERVICE · sheets · revisions

        Plan sets split into sheets, with revisions side by side.

        Talks to

        • → Object storage (files)
        • → Autodesk APS (linked files)
      • Chatreal timeSERVICE

        SERVICE · real time

        Project conversations, live.

        Talks to

        • → Redis (publish)
      • Bid packagesinvites · levelingSERVICE

        SERVICE · invites · leveling

        A trade’s scope packaged for bidding, with the subs invited to it.

        Talks to

        • ← Public API (REST)
        • ← Project (packages)
        • → Bids (collects)
      • BidsSOV · alternatesSERVICE

        SERVICE · SOV · alternates

        Each sub’s bid, with a schedule of values and any alternates, levelled against the others.

        Talks to

        • ← Bid packages (collects)
        • → Contracts (awarded)
      • ContractsSOV from the awardSERVICE

        SERVICE · SOV from the award

        The awarded bid’s schedule of values is carried onto a payable contract on the same project.

        Talks to

        • ← Bids (awarded)
      • Notificationsin-app · emailSERVICE

        SERVICE · in-app · email

        Tells people when something they own moves.

        Talks to

        • → Redis (publish)
    4. DData

      • PostgreSQLSTORE

        STORE

        The record of every project, RFI, bid and contract.

        Talks to

        • ← Project (SQL)
      • Object storageS3-compatibleSTORE

        STORE · S3-compatible

        Drawings, attachments and photos.

        Talks to

        • ← Drawings (files)
      • Redispub/subSTORE

        STORE · pub/sub

        Carries chat and notification events to the sockets.

        Talks to

        • ← Chat (publish)
        • ← Notifications (publish)
        • → Live sockets (pub/sub)
    5. ELinks

      • Procoreone-time importEXTERNAL

        EXTERNAL · one-time import

        Projects came across from Procore once. Nothing writes back.

        Talks to

        • → Project (import)
      • Autodesk APSfolders · filesEXTERNAL

        EXTERNAL · folders · files

        Delta’s Autodesk folders and files, linked to the project.

        Talks to

        • ← Drawings (linked files)

    Connections

    1. Delta’s team → Public API · HTTPS
    2. Architects & subs → Public API · emailed link
    3. Delta’s team → Live sockets · live
    4. Public API → Project · REST
    5. Public API → Bid packages · REST
    6. Project → Bid packages · packages
    7. Bid packages → Bids · collects
    8. Bids → Contracts · awarded
    9. Chat ⇢ Redis · publish
    10. Notifications ⇢ Redis · publish
    11. Redis ⇢ Live sockets · pub/sub
    12. Project → PostgreSQL · SQL
    13. Drawings → Object storage · files
    14. Drawings → Autodesk APS · linked files
    15. Procore ⇢ Project · import

    One flow

    A bid package becomes a subcontract

    Step through it and the parts it runs through light up above.

    Notes

    1. N.1It replaced Procore. Projects were brought over from Procore once; nothing writes back to it.
    2. N.2People outside Delta answer RFIs and submit bids from an emailed link, so the people who owe a reply don’t need a login.
    3. N.3Chat is live, and you aren’t notified about a conversation you’re already reading.
  10. 01.10

    Delta Estimating Portal

    Bid pipeline & CRM. Shows Delta’s estimators what they’re bidding and when: each bid gets a slot with a name, dates and hours, beside the client account.

    Live · Delta Construction

    Fig.Delta’s bid pipeline: what the estimators are working on, for whom, and when.

    Architecture

    1. APeople

      • Delta’s teamweb appUI

        UI · web app

        The people who log leads and look after client accounts.

        Talks to

        • → Leads (logs)
      • Estimatorstheir scheduleUI

        UI · their schedule

        Each estimator sees what they’re bidding, and when.

        Talks to

        • → Estimating slots (their week)
    2. BPipeline

      • Leadsstatuses you setSERVICE

        SERVICE · statuses you set

        Every bid opportunity, moving through statuses the team defines.

        Talks to

        • ← Delta’s team (logs)
        • → Client accounts (for)
        • → Follow-ups
        • → Estimating slots (scheduled)
        • → Project (won)
      • Follow-upscalls · emailsSERVICE

        SERVICE · calls · emails

        Calls and emails due on a lead, logged when done.

        Talks to

        • ← Leads
        • → Interactions (logged as)
      • Estimating slotswho · dates · hoursSERVICE

        SERVICE · who · dates · hours

        A bid on the estimating schedule: which estimator, which dates, hours planned and hours actually spent.

        Talks to

        • ← Estimators (their week)
        • ← Leads (scheduled)
        • → Estimator profiles (assigned)
      • Estimator profilesspecialtiesSERVICE

        SERVICE · specialties

        Each estimator and their specialties.

        Talks to

        • ← Estimating slots (assigned)
      • Client accountsSERVICE

        SERVICE

        The companies Delta bids for, with their own statuses.

        Talks to

        • ← Leads (for)
        • → Contacts
      • ContactsSERVICE

        SERVICE

        The people at each account.

        Talks to

        • ← Client accounts
      • InteractionstimelineSERVICE

        SERVICE · timeline

        Every call, email and meeting with an account, on one timeline.

        Talks to

        • ← Follow-ups (logged as)
        • → PostgreSQL (SQL)
      • Projectwhen it’s wonSERVICE

        SERVICE · when it’s won

        A won lead becomes a project.

        Talks to

        • ← Leads (won)
    3. CData

      • PostgreSQLSTORE

        STORE

        The record of leads, accounts and the schedule.

        Talks to

        • ← Interactions (SQL)

    Connections

    1. Delta’s team → Leads · logs
    2. Estimators → Estimating slots · their week
    3. Leads → Client accounts · for
    4. Client accounts → Contacts
    5. Leads → Follow-ups
    6. Follow-ups → Interactions · logged as
    7. Leads → Estimating slots · scheduled
    8. Estimating slots → Estimator profiles · assigned
    9. Leads → Project · won
    10. Interactions → PostgreSQL · SQL

    One flow

    A lead gets an estimator

    Step through it and the parts it runs through light up above.

    Notes

    1. N.1An estimating slot keeps the hours planned next to the hours actually spent, per estimator.
    2. N.2The team sets its own lead statuses, so the pipeline uses their words.

Résumé

Virginia, USA

I’m a systems architect in Virginia. In 2024 I co-founded Formwork, and I build the software it and its clients run on.

Since 2022 I’ve also been at CGI Federal, building AI for Medicare and Medicaid. On my own time I build a synth and AI tools that test software and run agents. I studied computer information systems at James Madison.

  1. Nov 2024 to now

    Formwork

    Technical Co-Founder & CTO

    Formwork does sales, marketing and software for commercial construction contractors. I built all of its technology, and I decide how it fits together across the three units. It started as Sunrise Systems.

  2. Jun 2022 to now

    CGI Federal

    Senior Consultant1

    I work in the Health and Social Services unit. I built the AI prototypes that led to a contract award from the Centers for Medicare & Medicaid Services. I also built the tracking systems and the dashboards leadership uses to see the team’s work.

    1“He has been integral in the development of tracking systems and dashboards, automating and displaying team function at an executive level.”
    William HallDirector of Emerging IP, CGI Federal
  3. Class of 2023

    James Madison University

    B.B.A. Computer Information Systems2

    2“You have shown a speed and ability to solve problems that I have not seen in my students before.”
    Dr. Dmytro BabikProfessor of Information Systems, James Madison University

After hours

Off the clock

When I’m not at work I’m usually still building: SIGIL, Orbit and Thronos all started as side projects.

I read, I look after my two dogs, Pixel and Melon, and I follow racing, which is why this site is a race.

Writing

Guides for Formwork, letters on HEY World

Work with me

I take on a few product builds outside Formwork. I design the system and write the code.

Tell me what you’re making. I read every message myself and reply within a couple of days.

2 product slots open for Q4

Form

This is about
Budgetoptional
Timelineoptional