● SIDE PROJECT · 03
MarketingAgent(Paperclip)
Status · Pre-launch · onboarding first practice
Year
2026
Role
Solo build
Focus
- Multi-tenant SaaS
- AI agents
- Security
(01) Context
The Marketing Agent started with a practicing physician and a simple frustration: the all-in-one marketing tools every clinic pays for (the GoHighLevel category) are really just static if-this-then-that builders. I wanted to know what that same product looks like when the automation engine is a roster of reasoning agents instead — so I built one, multi-tenant from the first line.
The problem
An all-in-one CRM for medical practices is a multi-tenant problem before it's an AI problem: every lead, message, and booking has to stay sealed inside the practice it belongs to — even when autonomous agents, not humans, are the ones reading and writing the data. Getting that isolation right under an agent threat model was the whole game.
(02) Approach
- 01
Multi-tenant from day one
A 13-table Postgres schema where every row is scoped to a tenant, modeled as a Clerk Organization. Isolation is enforced at both the data layer and the API layer, so a new endpoint can't accidentally leak across practices.
- 02
A company of agents, not a workflow builder
Nine specialized agents — follow-up, scheduling, content, SEO, social, reputation, reactivation, insights, and a director — run on an open-source control plane with an org chart, heartbeat scheduling, and budgets. They act only through a constrained skill interface against the CRM, with every action written to an audit log.
- 03
Security, caught by adversarial review
An adversarial multi-agent code review surfaced a cross-tenant isolation gap before a single practice was onboarded. I rearchitected agent auth around per-practice hashed API keys — deriving the tenant server-side from the key rather than trusting the request — with ownership checks on every child write.
- 04
Real communication, done compliantly
Twilio SMS and Resend email with a signature-validated inbound webhook, STOP/opt-out handling, and per-practice number routing — the unglamorous parts that decide whether a messaging product is allowed to exist.
- 05
Correct by construction
Timezone-aware availability plus a Postgres GiST exclusion constraint that makes double-booking impossible at the database level. End-to-end TypeScript with Zod-validated boundaries, Drizzle migrations, and typecheck/build gates on every change.
(03) Outcome
A working first slice — public lead form to AI follow-up to booked appointment — that's clean on typecheck and production build, security-reviewed, and pre-launch with its first practice onboarding.
9
cooperating AI agents
Multi-tenant
isolated per practice
Pre-launch
first practice onboarding
Next case
MatchYard →