Skip to content

thomasetienne/manifold

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

1 Commit
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Manifold

A verticalized WhatsApp agent for tradespeople. Voice or text in → signed PDF quotes and invoices out.

Node TypeScript PostgreSQL OpenAI License


Why this exists

Tradespeople (plumbers, electricians, heating engineers) spend hours a week doing admin: quotes, invoices, chasing confirmations, hunting down past jobs. They live on WhatsApp. Typing into accounting software in the van, between clients, does not happen.

Manifold is an agent that lives inside WhatsApp. The tradesperson sends a voice note: "just finished at Mrs. Martin, 340 euros, replaced the kitchen faucet". Manifold extracts the client, the service, the amount, applies the right VAT rate, generates a compliant PDF invoice, and asks for confirmation — all in 10 seconds.

It's a narrow, opinionated, vertical agent. Not a chatbot. Not a general assistant. One job, done well.

What it does

  • 🎙️ Voice-first — Whisper transcribes the voice note; written confirmation is requested for client names to avoid transcription errors on legal documents.
  • 📝 Quote / invoice generation — Produces compliant French PDF (SIRET, VAT, payment terms, validity duration, legal penalties).
  • 🔁 Status tracking"Martin accepted", "Lefebvre paid", "cancel the last quote" — all handled conversationally.
  • 🔍 Search old documents"find the Dupont quote from January" — queries the DB, returns the match.
  • 📧 Email delivery — Resend integration; sends the PDF directly to the client.
  • 🏢 Multi-tenant — each tradesperson is identified by their phone number; full data isolation between businesses.
  • 🚪 Self-serve onboarding — a new tradesperson is whitelisted by phone number, then the agent walks them through their company info on WhatsApp.
  • Rate-limited — 20 req/min, 100/hour per phone number.

Tech stack

Layer Choice Why
Runtime Node.js 20 · Express 5 · TypeScript Boring, fast, typed
DB PostgreSQL · Drizzle ORM Typed queries, small surface
LLM OpenAI GPT (agent loop) + Whisper (voice) Best tool-calling reliability for a prod agent
PDF pdf-lib + @pdf-lib/fontkit Full control, no headless browser
Email Resend Modern deliverability
Messaging WhatsApp Cloud API (Meta) Direct, webhook-based
Deploy Railway git push to prod

Architecture

┌──────────────────────┐   webhook   ┌──────────────────────────┐
│  WhatsApp Cloud API  │ ──────────▶ │  Express webhook handler │
│  (Meta)              │             │  • dedup + rate-limit    │
└──────────────────────┘             │  • voice → Whisper       │
         ▲                           │  • load business context │
         │ signed PDF                └────────────┬─────────────┘
         │                                        │
         │                                        ▼
         │                           ┌──────────────────────────┐
         │                           │      Agent loop          │
         │                           │  system_prompt(business) │
         │                           │  ↓                       │
         │                           │  GPT tool calls:         │
         │                           │  • create_devis          │
         │                           │  • create_facture        │
         │                           │  • modify_document       │
         │                           │  • send_document_email   │
         │                           │  • update_status         │
         │                           │  • list_documents        │
         │                           │  • (+ onboarding tools)  │
         │                           └────────────┬─────────────┘
         │                                        │
         │                                        ▼
         │                            ┌──────────────────────┐
         └────── PDF + preview ◀──────│   pdf-lib renderer   │
                                      │   + Postgres storage │
                                      └──────────────────────┘

Getting started

git clone https://github.com/thomasetienne/manifold.git
cd manifold
cp .env.example .env        # fill in the required keys
npm install
npm run db:push             # applies the schema to your database
npm run dev                 # http://localhost:3000

Required environment variables

Variable Purpose
DATABASE_URL PostgreSQL connection string
WA_ACCESS_TOKEN WhatsApp Cloud API token (Meta)
WA_VERIFY_TOKEN Custom string echoed back during webhook verification
WA_APP_SECRET Meta app secret (validates webhook signatures)
OPENAI_API_KEY GPT + Whisper
RESEND_API_KEY Email delivery

Whitelist a tradesperson

npx tsx src/scripts/whitelist-plumber.ts 33612345678

The tradesperson can then message the bot to start their onboarding conversation.

Project structure

src/
├── agent/
│   ├── system-prompt.ts   # Templated; reads business data from DB
│   ├── tools.ts           # Tool schemas (OpenAI function calling)
│   ├── tool-executor.ts   # Tool dispatch
│   ├── context.ts         # Conversation / document context builders
│   ├── onboarding.ts      # Step-by-step business setup flow
│   └── index.ts           # Agent loop
├── db/                    # Drizzle schema + repositories (businesses, clients, devis, factures, conversations)
├── middleware/            # Rate limiting, processing lock (dedup)
├── routes/                # webhook + health
├── scripts/               # seeds, migrations, whitelist, tests
├── utils/                 # logger, numeric helpers
├── config.ts              # env validation with Zod
└── index.ts               # entry point

Design notes

Why vertical, not general? General-purpose agents fail at boring, high-stakes document generation because they hedge. Tradespeople need a tool that commits: "this is the VAT rate, this is the legal mention, this is the PDF." Narrowing the domain lets the system prompt be precise, the tool surface be minimal, and the prompt engineering be actually maintainable.

Why voice-confirmed names? Whisper is excellent, but not for "Madame Lefèbvre-Grospiron". A single misspelled name on a legal invoice is painful. Manifold detects voice inputs, generates the doc from the transcription, then explicitly asks the tradesperson to confirm proper nouns in writing before finalizing.

Multi-tenancy via phone number. The tradesperson's personal WhatsApp number is the tenant key. No login, no password, no app to install. That's the point.

Status

Reference implementation extracted from a production codebase. The domain model (French quotes/invoices, SIRET, VAT rates) is France-specific; extending to other jurisdictions is straightforward — replace system-prompt.ts and the PDF templates.

License

MIT


Built by @thomasetienne · part of the Momentum operating system for AI-native businesses.

About

A verticalized WhatsApp agent for tradespeople — voice and text in, signed PDF invoices out.

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors