A system that answers inbound enquiries across WhatsApp, email and web forms, checks consent before it says anything, books appointments against a live calendar, sends reminders, and recovers no-shows. It is deployed under systemd on a hardened server with verified backups, and hands over to a human when it must.
Status, stated plainly: the deployment is live, but every outbound channel is switched off at the operator's instruction, so the system sends nothing at present. What follows describes what it does when the channels are open — and the decisions behind it, which are what a reader can actually judge.
This repository contains no source code and no customer data.
| Production code | 34,831 lines of Python |
| Tests | 31,260 lines across 116 test files |
| Runtime dependencies | standard library, plus HTTP |
| Deployment | systemd units, scheduler and web service, verified backups |
| Integrations | WhatsApp Business API, IMAP/SMTP, Google Calendar, Instagram, a gym management API |
Counted on 29 September 2026. The test-to-code ratio is close to 1:1. That is not a vanity metric here: most of those tests cover failure, not success — API outages, partial writes, duplicate webhooks, expired tokens, and legal edge cases.
inbound outbound
─────── ────────
WhatsApp ─┐ ┌─ WhatsApp
email ─┼─► ingest ─► consent gate ─► dialogue ─┼─ email
web form ─┘ │ │ │ └─ Instagram
│ │ │
▼ ▼ ▼
audit suppression guardrails
log list (no health claims)
│
▼
calendar seam ─► capacity check
│
▼
booking · reminder ·
no-show recovery
Every adapter sits behind one interface. Swapping the calendar provider or the messaging channel touches one file, never the dialogue logic.
1. Consent is a data structure, not a checkbox. Under GDPR Art. 7 and § 7 of the German Unfair Competition Act, you must be able to prove consent existed at the moment you sent a message, not that it exists now. The consent store is therefore append-only and timestamped, and the suppression list is keyed by contact, not by lead record — because the same person can appear as three leads and an objection covers the person.
2. A slot label carries no date. "Tuesday 6pm" is not a point in time. Resolving labels against a live calendar in a separate module removed an entire class of bug where a check would block a free slot and let a full one through. A capacity check that is wrong in both directions is worse than no check at all.
3. An appointment that cannot be honoured is never sold. The capacity module refuses to confirm a booking it cannot hold. This sounds obvious and is the single most common failure in booking automations: the system confirms first and discovers the conflict later, in front of the customer.
4. Compliance lives in code, not in a policy document. A guardrail module blocks health claims in outbound messages, because German pharmaceutical advertising law makes them unlawful regardless of consent. It is a test suite, not a paragraph in a README. There is a separate test file for the data-processing agreement boundary — the system refuses to act where no valid agreement covers the data.
5. Everything fails, so failure is the test surface. Dedicated test files cover API outages, bridge failures, partial writes and proof windows. The JSON store was hardened for go-live specifically around interrupted writes: write to a neighbouring file, fsync, then rename, so a process dying mid-write leaves the previous state intact rather than a truncated file.
Not that I can write Python. That the boring parts are done: idempotency, audit trails, graceful degradation, a human handover path, and legal constraints expressed as executable tests. Those are the parts that decide whether an automation survives its first month in production.
The source is private because it is a commercial system. I am happy to walk through
any part of it on a call, and the three public repositories next to this one
(whatsapp-starter, inbox-automation, table-pipeline) are extracted from the
same engineering approach and free to read in full.