Multi-tenant AI agent platform. Businesses sign up, embed a chat widget on their site, plug in a knowledge base, and get a Claude-powered support / commerce assistant — with built-in product catalog, shopping cart, orders, Stripe billing, and Socket.IO realtime.
- Multi-tenant — every signup gets its own isolated tenant; data, conversations, and billing are scoped per-tenant.
- Embeddable chat widget — drop one
<script>on any site and get a Claude-powered chat that knows your business. - RAG-powered knowledge base — upload docs / FAQs; OpenAI embeddings index them into Qdrant; Claude grounds every reply on relevant chunks.
- Realtime conversations — Socket.IO streams agent + customer messages, supports typing indicators and presence.
- Built-in commerce — products, cart, orders. The agent can recommend products, walk customers through checkout, and confirm orders mid-conversation.
- Stripe-billed SaaS — tenants subscribe via Stripe; webhook updates plan + entitlements.
- Email + SMS notifications — SendGrid for transactional email (login, receipts), Twilio for SMS confirmations.
- JWT auth — bcrypt-hashed passwords, signed access tokens, rate limiting on every endpoint.
- Operator dashboard — React 19 + Tailwind 4 + TanStack Query for tenants to inspect conversations, manage knowledge base, configure the agent, and view metrics.
┌─────────────────────────┐
│ Customer's website │
│ <embeds chat widget/> │
└────────────┬─────────────┘
│ Socket.IO
▼
┌───────────────────────────────────────────────────────────┐
│ Backend (Express + TS) │
│ │
│ /auth /tenants /widget /conversations │
│ /dashboard /chat /products /cart /orders │
│ │
│ ┌─ chat service ──────────────────────────┐ │
│ │ Claude (Anthropic) for responses │ │
│ │ OpenAI embeddings for retrieval │ │
│ └────────────┬─────────────────────────────┘ │
│ │ │
│ ┌────────────▼───────────────┐ ┌────────────────────┐ │
│ │ knowledge service │ │ commerce service │ │
│ │ (RAG over Qdrant vectors) │ │ (catalog, cart, │ │
│ └─────────────────────────────┘ │ orders, Stripe) │ │
│ └────────────────────┘ │
└─────┬───────────────┬───────────────┬────────────────────┘
│ │ │
▼ ▼ ▼
┌───────────┐ ┌───────────┐ ┌────────────┐
│ Postgres │ │ Redis │ │ Qdrant │
│ (data) │ │ (cache, │ │ (vector DB │
│ │ │ rate-lim,│ │ for RAG) │
│ │ │ pubsub) │ │ │
└───────────┘ └───────────┘ └────────────┘
▲
│
Stripe / SendGrid / Twilio (3rd-party SaaS)
| Concern | Choice |
|---|---|
| Language | TypeScript 5.5 |
| Runtime | Node.js 20+ (tsx for dev) |
| Framework | Express 4 |
| Auth | JWT + bcrypt |
| DB | PostgreSQL via pg (raw SQL + migrations script) |
| Cache / pub-sub | Redis via ioredis |
| Realtime | Socket.IO 4 |
| LLM (responses) | Anthropic Claude (@anthropic-ai/sdk) |
| LLM (embeddings) | OpenAI (openai) |
| Vector DB | Qdrant |
| Payments | Stripe |
| SendGrid | |
| SMS | Twilio |
| Validation | Zod |
| Rate limiting | express-rate-limit |
| Concern | Choice |
|---|---|
| Framework | React 19 |
| Build tool | Vite 8 |
| Styling | Tailwind CSS 4 |
| Data fetching | TanStack Query 5 |
| Routing | React Router 7 |
| Forms | React Hook Form + Zod resolver |
| State | Zustand 5 |
| HTTP | Axios |
| Charts | Recharts |
| Icons | Lucide |
| Notifications | react-hot-toast |
| Linting | ESLint 9 + typescript-eslint 8 |
.
├── package.json # backend deps + scripts
├── tsconfig.json
├── .env.example # all env vars documented
├── public/ # static assets served by the API
├── src/ # backend source
│ ├── index.ts # entry point
│ ├── config/ # env + service clients
│ ├── db/ # migrations, query helpers
│ ├── middleware/ # auth, tenant, rate-limit, error
│ ├── routes/
│ │ ├── auth.ts # login / signup / refresh
│ │ ├── tenants.ts # tenant CRUD + invitations
│ │ ├── chat.ts # send/receive messages
│ │ ├── conversations.ts # list / archive / search
│ │ ├── dashboard.ts # metrics + analytics
│ │ ├── widget.ts # embeddable widget bootstrap
│ │ ├── products.ts # catalog
│ │ ├── cart.ts # shopping cart
│ │ └── orders.ts # checkout + order history
│ ├── services/
│ │ ├── chat/ # Claude orchestration, streaming
│ │ ├── commerce/ # cart, pricing, Stripe, orders
│ │ └── knowledge/ # ingest, embed, retrieve (Qdrant)
│ └── types/ # shared TS types
└── frontend/ # React + Vite dashboard
├── package.json
├── vite.config.ts
├── tsconfig.json
├── public/
└── src/
- Node.js 20+
- PostgreSQL 14+
- Redis 7+
- Qdrant (
docker run -p 6333:6333 qdrant/qdrant) - API keys for: Anthropic, OpenAI, Stripe, SendGrid, Twilio
git clone https://github.com/Muhammad-Adil-code/Automation.git ai-agent-saas
cd ai-agent-saas
npm install
cd frontend && npm install && cd ..cp .env.example .env
# fill in DATABASE_URL, REDIS_URL, all the API keys, etc.The .env.example documents every variable with placeholder values.
npm run migrateIn two terminals:
# Terminal 1 — backend (Express on :3000 by default)
npm run dev
# Terminal 2 — frontend (Vite on :5173)
cd frontend
npm run devThe dashboard is at http://localhost:5173. Sign up, create a tenant, get your widget script, and embed it on a test page.
- Every request is scoped by a
tenantIdresolved from the auth token (dashboard) or widget API key (embed). - Postgres rows carry
tenant_id; every query indb/filters on it. - Stripe customers are namespaced per tenant; webhook handler verifies signature before mutating tenant state.
- Rate limiting is per-tenant + per-IP via Redis-backed
express-rate-limit. - Knowledge base vectors in Qdrant are partitioned by tenant collection.
- Customer message hits
/chat(or arrives via Socket.IO). services/knowledgeembeds the message via OpenAI → searches the tenant's Qdrant collection for top-k chunks.services/chatbuilds a Claude prompt with the retrieved chunks + recent conversation history.- Claude streams a response back over Socket.IO; tokens are persisted to
conversationsas they land. - If the agent decides to surface a product or trigger checkout, it calls
services/commercemid-stream (tool use).
- Stripe handles plans, subscriptions, and invoices.
routes/tenants.tsexposes a checkout-session endpoint that returns the Stripe Checkout URL.webhooks/(TODO) receivescustomer.subscription.*events and updates the tenant'splan+ entitlements (e.g. monthly message cap, knowledge-base size).
Once a tenant is set up, the dashboard generates a snippet:
<script src="https://your-saas.com/widget.js" data-tenant="abc123"></script>The widget loads, opens a Socket.IO connection scoped to the tenant, and renders a floating chat bubble.
- Webhooks for Stripe subscription lifecycle
- Per-tenant agent configuration UI (system prompt, model, temperature)
- Conversation transcript export (CSV / PDF)
- Multi-language support (Whisper for voice messages → text)
- Slack / WhatsApp connectors
- Self-serve analytics (response time, deflection rate, CSAT)
- Admin role + audit log
- CI: GitHub Actions workflow running
npm test+ lint + typecheck
PRs welcome. Please open an issue first if you're proposing a non-trivial change so we can align on direction.
# run linter
npm run lint
# typecheck
npx tsc --noEmit
cd frontend && npx tsc --noEmitCurrently no license file is shipped — treat the code as proprietary. A LICENSE will be added before any open-source release.
If you build something interesting on top of this, drop me a note — always curious to see how others stack chat agents with commerce.