Approval-first agents
Agents that draft, with a person in the loop
An operating system for a small professional-services company, built around one rule: nothing leaves the building without a person's approval.
How it fits together
Inputs
Inbound mail
A scheduled poll reads new threads, with a hard cap on how many one run can touch.
- Gmail
n8n
Time entry by text
Plain-language messages from a phone go to one shared bot that serves every agent.
Telegram
Web leads
Form posts reach a webhook that checks a header secret and a honeypot before anything runs.
Engine
Workflow engine
n8n workflows with Postgres state on Supabase. Every business fact comes from one version-controlled source.
n8n
Supabase
- PostgreSQL
Classify and parse
A smaller Claude model returns structured fields through forced tool calls. If the classifier fails, mail passes through instead of being dropped.
- Claude
Match without guessing
Client names are matched by rules. An ambiguous match asks which client was meant.
Draft
A stronger Claude model drafts replies, invoices, and posts. No workflow has a send step.
- Claude
Outputs
Approve in Telegram
Each draft waits until a person approves, edits, or rejects it.
Telegram
Draft invoices
Approved time becomes a draft invoice in QuickBooks Online, never a sent one.
- QuickBooks Online
Lead records
Qualified leads are recorded in HubSpot.
- HubSpot
Guardrails
- Monthly spend limit and a daily spend watchdog
- Hard cap on items per run
- Tests on every push and a daily health check
- A second model reviews every plan before it is builtOpenAI
The problem
A small services company spends its week on intake, invoicing, call follow-up, and content. Nearly all of it goes to clients or the public, and a mistake is visible. Automating that work is easy. Automating it safely is the job.
What I built
- Agents that triage inbound mail and draft replies, invoices, and posts, with no send step that a person does not trigger.
- Time entry by plain-language text message that becomes a draft invoice, and asks which client was meant instead of guessing when a name is ambiguous.
- Public-facing agents with authenticated entry, hard limits on how many items one run can touch, and a classifier that fails open so a failed model cannot swallow real mail.
- Spend controls for unattended runs: monthly limits, a daily watchdog, and a hard limit on each run.
- Automated tests on every push to every site, and a daily health check that exercises the whole submission path.
How I built it
The workflows run on n8n with Postgres on Supabase, Claude models for parsing and drafting, and Telegram for approvals. A smaller model handles classification and parsing through forced tool calls, and a stronger model drafts. A second model reviews each plan before I build it, and every business fact lives in one written source that the agents and the sites read from.
What it shows
I treat approval, spend, and failure behavior as design requirements from the first day, not as cleanup after launch.