Skip to content
Automation

Systems

A one-person portfolio of ten products still has a back office — support inboxes, release notes, broadcasts, outreach. Instead of hiring it out, I built it. Two systems run most of it, and both are designed to stop themselves before they can do harm.

How Work Flows

Signals
Customer emailOps alertsApp-store reviewsProduct CHANGELOGs
Agents
Mailroom (classify · draft · escalate)marketing-os (draft weekly PR)
Human gate
Approve high-confidence sends · merge the PR
Actions
Replies sentPosts publishedBroadcasts & outreach

Mailroom

Unified inbox agent

One agent answering support for eight products

Every product's customer email, ops alert, and app-store review lands in a single Fastmail mailbox via Cloudflare Email Routing. Mailroom classifies each message, drafts a reply grounded in that product's own knowledge base, and either auto-sends when it's confident or leaves a draft for review. Anything risky escalates and stays escalated.

  • Per-product Markdown KBs, prompt-cached into the drafter so replies stay on-voice and on-policy
  • Auto-send only above a confidence threshold; everything else becomes a review draft
  • Sticky escalation via risk keywords, negative sentiment, or a manual /human — it never un-escalates itself
  • Cost-guarded with daily spend tracking; native push via Pushover + macOS banners
Python 3.12FastAPIn8nFastmail JMAPCloudflare Email RoutingSQLiteClaude

marketing-os

Portfolio marketing automation

One weekly PR is the only recurring human cost

Each Monday a job reads every product's CHANGELOG and drafts the blog, social, and email worth writing that week into a pull request. Merging the PR is approval. From there, publishing, broadcasts, and cold-outreach sequencing all run on a schedule — and stop at the first sign of trouble.

  • Draft → review → merge: nothing publishes or sends off a branch, ever
  • No news means no PR — silent weeks are correct, and filler is treated as a bug
  • Scheduled publish commits blog posts, sends Resend broadcasts, and queues social slots
  • Outbound sequences auto-pause on bounce/complaint thresholds and Pushover-notify when they do
TypeScriptlaunchdgit PR flowResendPostizCHANGELOG-driven

Built to fail closed

Merge is the only approval

Nothing reaches a customer off a branch. A human merge to main is the single gate every outbound action passes through.

Silence is correct

When a product has nothing worth saying, the system says nothing. No filler content, no manufactured cadence.

Dry-run by default

Every job runs in DRY_RUN mode unless explicitly flipped. The default posture is 'compute the action, take none of it.'

Self-stopping

Daily cost caps, sticky escalation, and automatic campaign pauses mean the systems fail closed — they stop themselves before I have to.

8Products served
1Weekly human touchpoint
0Sends off a branch

Same approach, for your team

The human-in-the-loop, on-prem automation I run for my own portfolio is what I deploy for regulated clients through Sovereign AI.