AU
auapps / work · workshop
Filed23:47
Three projects · systems Section B · Workshop

Workshop.

Three systems-design pieces. The first I built to run everything else — open source, in daily use; the other two are one academic, one paused for honest reasons. Combined because the substance is in the shape of each system, not the polish.

00

What connects them

system shape · end-to-end

All three are exercises in system shape: pick a domain (agent orchestration, traffic dynamics, lead outreach), then build the thing end-to-end so the actual constraints surface — not just the diagrammed ones. One I use daily, one is academic, one is commercial. Each forced choices that don't appear until you've shipped past the wireframe and into the messy part. The shape of those choices is what's worth showing.

01CrewBoard · multi-agent orchestration · open source · 2026

One board to run a crew of AI agents.

A local web board that runs many headless claude -p sessions at once and routes work between them through one hub — so I stop being the copy-paste relay. A vanilla-JS front end over a Flask hub that launches, streams, and resumes each agent as an ephemeral subprocess. Runs entirely on a Claude Pro/Max subscription — no Agent SDK, no API key.

Python Flask Server-Sent Events MCP claude -p Vanilla JS MIT
01a

Why one hub

STAR topology · not a mesh

Run several Claude sessions in parallel and you become the wire between them, copying one's output into another's prompt over and over. CrewBoard makes the hub that wire: sessions never talk directly — every hand-off, whether I trigger it or the secretary suggests it, goes through one channel and is executed deterministically as a claude -p --resume call. The source output is delivered verbatim; the workers stay focused.

01b

A secretary that watches the board

model-tiered · cost-gated

After each turn a cheap Haiku pass writes a one-line brief and a name for that session. A heavier Sonnet pass reads the whole board and proposes the moves — which output should feed which session, what needs my attention, which sessions belong to one initiative. That second pass is the expensive one, so it's gated: it runs only with two or more live sessions, collapses bursts of activity into a single call, and can be switched off entirely (Quiet mode). Spending the model where it earns its keep was a design constraint, not an afterthought.

01c

The control surface

relay · advisor · step-in

Relay delivers a session's output into another with a click. An Opus advisor — one persistent, streaming session with real cross-turn memory and no tools — answers board-wide questions when I need to reason about everything at once. And I can step into any single session to steer it directly. Informational relays inside a group can auto-fire; if the target is mid-turn the hand-off is queued and re-surfaces as a confirm chip, while steering relays always stay manual. Status lights — running · done · needs-you · errored — show which sessions want attention without opening them.

01d

A canvas, not a list

group by initiative

Two views of the same state: a reading-room rail and a spatial map. On the map I drag sessions into place and bundle related ones into named groups — and the secretary proposes a grouping on its own when it spots several working toward the same thing. Positions, groups, and who-feeds-whom persist on disk, so the map I built is still there after a restart.

01e

Fork when the context fills

handoff · without losing the thread

Claude sessions have a finite context window. When one fills up, CrewBoard runs a last turn asking the session to write its own handoff summary, then launches a fresh session seeded with it — on the same tile, keeping the session's identity and all its edges and groups. The underlying session id changes; the board doesn't notice.

Open source (MIT) at github.com/alperumul/crewboard — I built it to build the rest of this; it's how I run the parallel Claude sessions behind FBI and this site. State needed to resume any session lives on disk, so sessions survive a hub restart.

02Sumo · traffic simulation · group g8 · jan 2025

Adaptive traffic light controller, 2D/3D hybrid.

Java 21 + JavaFX desktop app driving Eclipse SUMO through libtraci (Java bindings to the simulation kernel). Adds a layer the stock SUMO GUI doesn't ship: batch vehicle injection, an adaptive controller that retunes phase splits from live queue density, FXyz3D for elevated 3D rendering, CSV reporting per intersection.

Java 21 JavaFX libtraci FXyz3D Maven SUMO 1.18
02a

The adaptive controller

−22% wait · benchmark dataset

SUMO ships with fixed-cycle traffic light logic by default — every phase gets a predetermined slice of the cycle regardless of who's waiting. The adaptive controller tears that out and replaces it with a feedback loop: every tick, it reads the queue length per approach via libtraci, weights it against minimum-green and pedestrian-cycle constraints, and retunes the next phase split toward whichever direction has the most pent-up demand. Result: a 22% drop in average wait time on the synthetic 4-way intersection dataset (group benchmark), at the cost of slightly noisier phase transitions that the report had to address explicitly.

02b

What the 3D layer is for

scrutability · not graphics

FXyz3D renders the intersection as an extruded geometry — buildings, road grade, vehicles. Not for graphics; for scrutability. A 2D top-down simulation is great until you need to argue about lane-line geometry or sightlines, at which point a top-down arrow stops being enough. The 3D view became the explanation surface: when the group reviewed the controller's decisions, the 3D render let us point at exactly which sightline the adaptive logic was responding to.

Documented — Code Documentation, Enhancements & Design Decisions, and AI Declaration PDFs ship alongside the binary. Runs locally; not deployed (academic project). Four-person group; my responsibility was the controller layer + the 3D rendering integration.

03Lead Outreach · n8n + supabase + twilio + gmailpaused · day 8/14

Deterministic, audit-friendly outreach stack.

Sheets → Supabase upsert (idempotent, fingerprinted) → LLM-drafted message per lead → multi-channel send (Email · SMS · WhatsApp) → tracking → unsubscribe enforcement → send queue + archive. DB-trigger-driven state machine; n8n patches queue to state='sent' and the trigger handles archive + draft-status. provider_message_id dedupes inbound; before-send check against (lead_id, draft_id, provider) blocks resends.

n8n Cloud Supabase Twilio Gmail API LLM (classifier + composer) paused
03a

Why this architecture

audit-friendly · deterministic

Lead outreach is the kind of system where the cost of a bug is asymmetric — a double-send or a missed unsubscribe is not a refactor, it's a complaint. So the design philosophy was: every state change has a database fingerprint, every send is checked against an idempotency key, and every external action is queued through a trigger rather than fired in-flight. If the workflow dies mid-execution, picking it up again replays cleanly. If the audit comes, the path from lead to sent message is one SQL query away.

n8n was chosen for the visual workflow layer not because it's the fastest path, but because the audit trail it produces is human-readable. A reviewer (regulator, client, or future-me) can open the run history and see exactly which lead got which message at which timestamp via which channel — without parsing logs.

03b

"Paused, day 8 of 14" — what it means

half-built · honest pause

Days 0–8 shipped: env + auth setup, import (Sheets → Supabase with write-back), LLM compose, Gmail send, Twilio send (SMS + WhatsApp), tracking outcomes (not pre-marked sent), unsubscribe handling, reliability hardening (retries · rate limits · idempotency).

Days 9–14 pending: inbound classifier with ACT.YES / ACT.NO / POTENTIAL.* / HUMAN routing, scheduling/templates, analytics, Airtable parity, polish.

The pause is honest: the half that's built is the "send" half, and continuing without a real outreach list to run against would mean building the "classify replies" half on synthetic data — which never matches production. Audit kit prepared and the system resumes the moment there's a live campaign to run. The reason it's mentioned here at all is because shipping half of a serious thing taught more than shipping a small thing whole.

Code & docs available on request — repos private during the paused window.