# Chatlytics v2 — Product Requirements Document

## Executive Summary

Chatlytics is a WhatsApp automation platform that makes any AI agent framework "WhatsApp-native" — send messages, manage groups, enforce human-like behavior, and control policies, all through a single API. Built on WAHA (WhatsApp HTTP API), it currently runs as an OpenClaw plugin. v2 extracts the core into a standalone, multi-tenant SaaS at chatlytics.ai, distributable via OpenAPI, MCP server, SKILL.md files, and framework-specific plugins.

## Problem Statement

1. **Framework lock-in**: The platform is deeply coupled to OpenClaw's plugin SDK (`openclaw/plugin-sdk/*`). Claude Code, Codex CLI, Gemini CLI, Roo Code, and dozens of other AI agent frameworks cannot use it.

2. **Single-tenant**: One config file (`openclaw.json`), one set of WAHA sessions, one SQLite database. No way for multiple users to share infrastructure.

3. **No self-service onboarding**: Setup requires SSH access, manual config editing, and gateway restarts. No API key provisioning, no QR code flow, no dashboard signup.

4. **Distribution gap**: The only way to consume the platform is as an npm package installed into OpenClaw. No REST API docs, no MCP server, no standalone agent skill files.

## Product Vision

**chatlytics.ai** — A WhatsApp automation platform for AI agents.

Users sign up, scan a QR code to connect their WhatsApp, get an API key, and integrate with their AI agent of choice. The platform handles mimicry (human-like sending patterns), policy enforcement (who can message whom), directory management (contacts/groups), and the full WhatsApp API surface — so agent developers don't have to.

### Core Value Propositions

1. **Human mimicry**: Time-of-day gates, progressive hourly caps, typing simulation, adaptive activity profiles — prevents WhatsApp bans and makes bot messages indistinguishable from human ones.
2. **Policy engine**: DM/group filters, allow-lists, per-contact rules, god-mode bypass, pairing challenges — production-grade access control out of the box.
3. **Full WhatsApp API**: 109+ actions covering messaging, groups, contacts, channels, labels, status, presence, profile, media, and more.
4. **Framework-agnostic**: One backend, multiple consumption methods — REST API, MCP server, SKILL.md, framework plugins.

## User Personas

### 1. AI Agent Developer (Primary)
- Building AI assistants that need WhatsApp communication
- Uses Claude Code, Codex CLI, Cursor, Roo Code, or similar
- Wants a simple API — send a message, read messages, manage groups
- Does NOT want to deal with WhatsApp protocol details, ban prevention, or policy logic

### 2. Business Operator
- Non-technical user running an AI assistant for their business
- Needs a dashboard to manage contacts, set policies, monitor activity
- Cares about: who can message the bot, message limits, active hours

### 3. Platform Builder
- Building a product on top of WhatsApp (CRM, support tool, marketing)
- Needs programmatic access to everything — multi-session, webhooks, full API
- Will use the OpenAPI spec or REST API directly

## User Journey

### Onboarding Flow

```
1. Sign up at chatlytics.ai (email + password or OAuth)
2. Create a "workspace" (isolated tenant)
3. Connect WhatsApp:
   a. Platform provisions a WAHA session
   b. User scans QR code displayed in dashboard
   c. Session becomes "connected" — webhook URL auto-configured
4. Get API key (displayed once, stored hashed)
5. Choose integration method:
   a. MCP Server → copy config JSON into claude_desktop_config.json / .mcp.json
   b. SKILL.md → download and place in agent's skill directory
   c. OpenAPI → copy base URL + API key, use any HTTP client
   d. Framework plugin → npm install / pip install with API key in env
6. Send first message (guided in dashboard)
```

### Day-2 Flow

```
1. Open dashboard at chatlytics.ai
2. Review mimicry status (messages sent vs cap, active hours)
3. Adjust policies (allow-list, keyword filters, per-group overrides)
4. Monitor directory (contacts, groups, participants)
5. Check session health (connected, QR needed, error)
```

## Architecture

### Current State (v1.x — OpenClaw Plugin)

```
OpenClaw Gateway (jiti runtime)
  └─ waha-openclaw-channel plugin
       ├─ channel.ts        — action dispatch (ChannelPlugin interface)
       ├─ monitor.ts        — HTTP server (webhooks + admin API + SSE)
       ├─ send.ts           — 60+ WAHA API wrappers (~1600 lines)
       ├─ inbound.ts        — webhook message processing
       ├─ directory.ts       — SQLite contact/group directory
       ├─ mimicry-gate.ts   — time gate + hourly cap (SQLite)
       ├─ mimicry-enforcer.ts — send pipeline enforcement
       ├─ activity-scanner.ts — adaptive peak-hour learning
       ├─ http-client.ts    — centralized WAHA HTTP client
       ├─ adapter.ts        — PlatformAdapter abstraction layer
       ├─ 25+ more modules  — health, sync, pairing, rules, etc.
       └─ admin/             — React dashboard (Vite + shadcn/ui)
```

**Key coupling points to OpenClaw:**
- `index.ts` — `OpenClawPluginApi.registerChannel()`
- `channel.ts` — `ChannelPlugin` interface, `ChannelMessageActionAdapter`
- `inbound.ts` — `OutboundReplyPayload`, `createNormalizedOutboundDeliverer`
- `config-schema.ts` — `buildSecretInputSchema()` from plugin SDK
- `accounts.ts` — `DEFAULT_ACCOUNT_ID`, `normalizeAccountId` from SDK
- `monitor.ts` — `readRequestBodyWithLimit` from SDK

### Target State (v2 — Standalone + Multi-Tenant)

```
chatlytics.ai (Cloud)
  ├─ Auth service (API keys, OAuth, workspace provisioning)
  ├─ API Gateway (rate limiting, routing, API key validation)
  │
  ├─ Chatlytics Core (per-workspace process or container)
  │    ├─ HTTP Server (Express or native http)
  │    │    ├─ /api/v1/*          — public REST API (OpenAPI 3.1)
  │    │    ├─ /webhook/waha      — WAHA webhook receiver
  │    │    ├─ /mcp               — MCP server (SSE transport)
  │    │    └─ /admin/*           — dashboard API
  │    ├─ send.ts                — WAHA API wrappers (reuse as-is)
  │    ├─ inbound.ts             — webhook processing (decouple from OC)
  │    ├─ directory.ts           — SQLite directory (reuse as-is)
  │    ├─ mimicry-gate.ts        — mimicry system (reuse as-is)
  │    ├─ mimicry-enforcer.ts    — send enforcement (reuse as-is)
  │    ├─ activity-scanner.ts    — adaptive profiles (reuse as-is)
  │    ├─ http-client.ts         — WAHA HTTP client (reuse as-is)
  │    └─ adapter.ts             — PlatformAdapter (reuse as-is)
  │
  ├─ WAHA Instance(s)
  │    └─ Multi-session WAHA with per-workspace session isolation
  │
  ├─ Dashboard (React SPA)
  │    └─ Existing admin panel + onboarding + workspace management
  │
  └─ Distribution Layer
       ├─ OpenAPI 3.1 spec (auto-generated)
       ├─ MCP Server (tools + resources)
       ├─ SKILL.md (per-framework)
       └─ Framework plugins (OpenClaw, LangChain, etc.)
```

### Standalone Deployment (Docker)

```dockerfile
# Minimal standalone container
FROM node:22-alpine
WORKDIR /app
COPY package.json tsconfig.json ./
COPY src/ ./src/
COPY dist/admin/ ./dist/admin/
RUN npm ci --production
EXPOSE 8050
ENV WAHA_BASE_URL=http://waha:3000
ENV WAHA_API_KEY=...
ENV CHATLYTICS_API_KEY=...
CMD ["node", "--import=tsx", "src/standalone.ts"]
```

Key requirements for standalone mode:
- Own HTTP server (currently piggybacks on OpenClaw's webhook server in monitor.ts — already self-contained)
- Own config store (currently reads from `openclaw.json` — needs config-io.ts abstraction)
- Own webhook registration (currently OpenClaw registers WAHA webhooks — needs self-registration)
- Inbound message routing (currently delivers to OpenClaw's agent — needs webhook forwarding or MCP notification)

### Multi-Tenant Architecture

Each tenant (workspace) gets:
- **Isolated WAHA session(s)**: Own WhatsApp connection, own QR code
- **Isolated SQLite databases**: directory.db, mimicry.db, analytics.db per workspace
- **Isolated config**: Own policy settings, filters, mimicry config
- **Own API key**: Scoped to workspace, rotatable

Tenant isolation model (recommended: **process-per-tenant**):
- Each workspace runs in its own process/container
- SQLite files scoped by workspace directory
- WAHA sessions namespaced by workspace ID (already supported via `tenantId` field in `ResolvedWahaAccount`)
- API gateway routes by API key → workspace → process

Alternative (later): shared-process with in-memory tenant context switching. The existing `accountId` pattern already supports this — `DirectoryDb` and `MimicryDb` are instantiated per account.

## Distribution Strategy

### 1. OpenAPI 3.1 Spec

Auto-generate from existing HTTP routes in monitor.ts. Current admin API already has ~30 endpoints. Add public-facing endpoints:

**Public API Surface (v1):**

| Category | Endpoints |
|----------|-----------|
| Messaging | `POST /api/v1/send`, `POST /api/v1/send/image`, `POST /api/v1/send/poll`, `POST /api/v1/react` |
| Reading | `GET /api/v1/chats`, `GET /api/v1/chats/:id/messages`, `GET /api/v1/messages/:id` |
| Groups | `GET /api/v1/groups`, `POST /api/v1/groups`, `GET /api/v1/groups/:id/participants` |
| Contacts | `GET /api/v1/contacts`, `GET /api/v1/contacts/:id` |
| Directory | `GET /api/v1/directory`, `PUT /api/v1/directory/:jid/settings` |
| Search | `GET /api/v1/search?q=...&scope=group\|contact\|channel` |
| Mimicry | `GET /api/v1/mimicry/status`, `GET /api/v1/mimicry/activity-profiles` |
| Config | `GET /api/v1/config`, `PATCH /api/v1/config` |
| Sessions | `GET /api/v1/sessions`, `GET /api/v1/sessions/:id/health` |
| Webhooks | `POST /api/v1/webhooks` (register callback URL for inbound messages) |

**Generation approach**: Manual OpenAPI YAML with `$ref` components. The routes are in a single raw `http.createServer` handler (not Express), so auto-generation tools like tsoa/swagger-jsdoc won't work cleanly. Write the spec by hand, validate with spectral, generate SDK clients with openapi-generator.

### 2. MCP Server

Expose Chatlytics capabilities as MCP tools and resources for Claude Code, Claude Desktop, and any MCP-compatible client.

**Tools (actions the agent can perform):**

| Tool | Description |
|------|-------------|
| `send_message` | Send text to a contact or group (auto-resolves names) |
| `send_image` | Send image with optional caption |
| `send_poll` | Create a poll |
| `send_reaction` | React to a message |
| `read_messages` | Read recent messages from a chat |
| `search` | Find contacts, groups, channels by name |
| `get_chat_messages` | Get message history for a chat |
| `create_group` | Create a WhatsApp group |
| `add_participants` | Add members to a group |
| `get_directory` | List contacts/groups from directory |
| `update_contact_settings` | Update DM settings for a contact |
| `get_mimicry_status` | Check current gate/cap status |
| `get_session_health` | Check WhatsApp connection status |

**Resources (read-only data the agent can access):**

| Resource | URI | Description |
|----------|-----|-------------|
| Contacts | `chatlytics://contacts` | All contacts in directory |
| Groups | `chatlytics://groups` | All groups in directory |
| Sessions | `chatlytics://sessions` | Session status and health |
| Config | `chatlytics://config` | Current policy configuration |
| Mimicry Status | `chatlytics://mimicry` | Gate/cap status per session |
| Activity Profiles | `chatlytics://activity-profiles` | Per-chat peak hour data |

**Prompts (reusable prompt templates):**

| Prompt | Description |
|--------|-------------|
| `whatsapp-assistant` | System prompt for a WhatsApp-aware AI assistant |
| `group-manager` | System prompt for managing WhatsApp groups |

**Transport**: SSE (for remote/cloud) and stdio (for local installs). The MCP server wraps the same internal functions that the admin API and OpenClaw plugin use.

**MCP Config Example:**
```json
{
  "mcpServers": {
    "chatlytics": {
      "url": "https://api.chatlytics.ai/mcp",
      "headers": {
        "Authorization": "Bearer ctl_xxx"
      }
    }
  }
}
```

### 3. SKILL.md Files

Already have a comprehensive SKILL.md (v6.0.0) with 10 category files. For v2:
- Adapt SKILL.md to reference Chatlytics API endpoints instead of OpenClaw actions
- Generate framework-specific variants (Claude Code, Codex CLI, etc.)
- Include API key configuration instructions per framework

### 4. Framework Plugins

- **OpenClaw**: Keep existing plugin as-is, but delegate to Chatlytics API instead of embedding logic
- **Claude Code**: MCP server (primary) + SKILL.md (fallback)
- **Others**: OpenAPI spec + SKILL.md — most frameworks support HTTP tool calling

## Feature Requirements

### P0 — Must Have (v2.0)

| ID | Feature | Notes |
|----|---------|-------|
| F01 | Standalone HTTP server | Decouple from OpenClaw gateway. Own process, own config, own webhook receiver. |
| F02 | API key authentication | Per-workspace API keys. Header: `Authorization: Bearer ctl_xxx`. |
| F03 | Public REST API (v1) | Send, read, search, directory, config, sessions, mimicry status. |
| F04 | OpenAPI 3.1 spec | Hand-written YAML, validated, published at `api.chatlytics.ai/openapi.yaml`. |
| F05 | MCP server (tools) | Send, read, search, directory, config tools via MCP protocol. |
| F06 | Docker container | Single-container deployment with env var config. |
| F07 | Webhook forwarding | Forward inbound messages to registered callback URLs (replacing OpenClaw agent delivery). |
| F08 | Config abstraction | Read/write config from standalone JSON file (not openclaw.json). |

### P1 — Should Have (v2.1)

| ID | Feature | Notes |
|----|---------|-------|
| F09 | Multi-tenant workspace isolation | Per-workspace processes, databases, sessions. |
| F10 | User registration + dashboard | Sign up, connect WhatsApp, manage workspace. |
| F11 | QR code provisioning flow | Provision WAHA session, display QR in dashboard. |
| F12 | MCP resources | Read-only resources for contacts, groups, sessions, config, mimicry. |
| F13 | Webhook subscription management | CRUD for webhook URLs with event filters. |
| F14 | SDK clients | Auto-generated TypeScript and Python clients from OpenAPI spec. |

### P2 — Nice to Have (v2.2+)

| ID | Feature | Notes |
|----|---------|-------|
| F15 | Usage billing | Track messages per workspace, enforce plan limits. |
| F16 | Team management | Multiple users per workspace with roles. |
| F17 | MCP prompts | Reusable prompt templates for common WhatsApp agent patterns. |
| F18 | Framework-specific SKILL.md | Auto-generated skill files per agent framework. |
| F19 | Audit log | Per-workspace log of all API calls and policy decisions. |
| F20 | Custom WAHA instance | Allow users to bring their own WAHA deployment. |

## Technical Requirements

### T01: Decouple from OpenClaw SDK
- Remove all `openclaw/plugin-sdk/*` imports from core modules
- Replace with local equivalents or thin adapters
- Keep OpenClaw plugin as a separate wrapper that delegates to the core

**Modules with SDK dependencies (must decouple):**
- `channel.ts` — `ChannelPlugin`, `ChannelMessageActionAdapter` (heavy coupling)
- `inbound.ts` — `OutboundReplyPayload`, `createNormalizedOutboundDeliverer`, `resolveDefaultGroupPolicy`
- `config-schema.ts` — `buildSecretInputSchema()`
- `accounts.ts` — `DEFAULT_ACCOUNT_ID`, `normalizeAccountId`, `resolveAccountWithDefaultFallback`
- `monitor.ts` — `readRequestBodyWithLimit`, `isRequestBodyLimitError`
- `normalize.ts` — `isWhatsAppGroupJid`

**Modules with zero SDK dependencies (reuse as-is):**
- `send.ts` — only depends on `http-client.ts`
- `directory.ts` — pure SQLite
- `mimicry-gate.ts` — pure SQLite
- `mimicry-enforcer.ts` — depends on mimicry-gate + send (typing)
- `activity-scanner.ts` — depends on directory + send
- `http-client.ts` — pure fetch + token bucket
- `adapter.ts` — PlatformAdapter interface (already abstracted)
- `logger.ts` — pure structured logger
- `dedup.ts` — pure in-memory dedup
- `dm-filter.ts` — pure filter logic
- `health.ts` — pure health check logic

### T02: Standalone HTTP Server
- Reuse `monitor.ts` HTTP server (already `http.createServer`)
- Add public API routes under `/api/v1/`
- Add API key middleware
- Add CORS headers for dashboard
- Keep existing `/api/admin/` routes for dashboard

### T03: MCP Server Implementation
- Use `@modelcontextprotocol/sdk` for TypeScript MCP server
- SSE transport for remote (cloud deployment)
- stdio transport for local (`npx chatlytics-mcp`)
- Tools map 1:1 to public API endpoints
- Resources backed by directory and config queries

### T04: Multi-Tenant Data Isolation
- SQLite databases in `~/.chatlytics/workspaces/{workspaceId}/`
- WAHA sessions prefixed with workspace ID
- Config files per workspace
- In-memory LRU cache scoped by workspace

### T05: Webhook Forwarding
- Replace OpenClaw's `deliverWahaReply` with a webhook forwarder
- Register callback URLs per workspace
- Retry with exponential backoff (3 attempts)
- HMAC signature on payloads
- Event filters (message, group_join, reaction, etc.)

### T06: Backward Compatibility
- OpenClaw plugin continues to work unchanged
- Plugin becomes a thin wrapper: receives action from gateway, calls Chatlytics API
- All existing SKILL.md action names preserved
- Existing admin panel routes preserved

## Success Metrics

| Metric | Target | Timeframe |
|--------|--------|-----------|
| Standalone container boots and sends a message | Working | v2.0 |
| MCP server connects to Claude Code and sends a message | Working | v2.0 |
| OpenAPI spec validates and generates working SDK client | Working | v2.0 |
| Time to first message (new user signup to sent message) | < 5 minutes | v2.1 |
| Concurrent workspaces on single host | 50+ | v2.1 |
| API response time (send_message, p95) | < 500ms (excluding mimicry delay) | v2.0 |
| Existing OpenClaw integration unbroken | Zero regressions | All versions |

## Milestones

### Phase 1: Core Extraction (v2.0-alpha)
- Extract standalone entry point (`standalone.ts`)
- Decouple config-io from openclaw.json
- Add API key authentication middleware
- Docker container that boots and serves admin panel
- **Exit criteria**: Container starts, admin panel loads, health endpoint responds

### Phase 2: Public REST API (v2.0-beta)
- Public `/api/v1/` endpoints for send, read, search, directory
- Proxy-send endpoint with mimicry enforcement (already exists as `/api/admin/proxy-send`)
- OpenAPI 3.1 spec (hand-written YAML)
- **Exit criteria**: Can send a message via `curl` with API key auth

### Phase 3: MCP Server (v2.0-beta)
- MCP server with SSE + stdio transports
- Core tools: send_message, read_messages, search, get_directory
- Test with Claude Code and Claude Desktop
- **Exit criteria**: Claude Code can send a WhatsApp message via MCP

### Phase 4: Webhook Forwarding (v2.0-rc)
- Inbound message webhook forwarder
- Callback URL registration API
- HMAC signatures on outbound webhooks
- Retry with backoff
- **Exit criteria**: Inbound WhatsApp message triggers callback to registered URL

### Phase 5: Dashboard + Onboarding (v2.1)
- User registration (email + password)
- Workspace creation
- QR code scanning flow
- API key management in dashboard
- Integration setup wizard (MCP config, SKILL.md download, API docs link)

### Phase 6: Multi-Tenant (v2.1)
- Per-workspace process isolation
- Per-workspace SQLite databases
- Per-workspace WAHA session management
- API gateway with workspace routing

### Phase 7: Distribution (v2.2)
- Auto-generated TypeScript + Python SDK clients
- Published npm/PyPI packages
- Framework-specific SKILL.md files
- OpenClaw plugin refactored as thin Chatlytics API wrapper

## Open Questions

1. **Hosting model**: Single WAHA instance shared across tenants (cheaper, harder isolation) vs WAHA-per-tenant (expensive, clean isolation)? Leaning toward single shared WAHA with session-level isolation — WAHA already supports multi-session.

2. **Pricing model**: Per-message, per-workspace/month, or usage tiers? Need to instrument billing counters early if per-message.

3. **WAHA licensing**: WAHA Plus has features (multi-device, webhooks) that free WAHA lacks. Do we bundle WAHA Plus, require users to bring their own, or maintain a WAHA fork?

4. **Inbound message delivery**: MCP doesn't have a "push" mechanism — tools are pull-only. For real-time inbound messages, options are: (a) webhook callbacks, (b) SSE stream resource, (c) polling via `read_messages` tool, (d) MCP notifications (experimental). Which to prioritize?

5. **OpenClaw backward compatibility**: Keep the OpenClaw plugin as a first-class distribution or deprecate it once Chatlytics API is stable? The plugin has 50+ phases of battle-tested code — rewriting as a thin wrapper risks regressions.

6. **Auth provider**: Build custom auth (JWT + API keys) or use a provider (Clerk, Better Auth, Supabase Auth)? Dashboard needs auth; API needs API keys. Could be two separate systems.

7. **Domain architecture**: `chatlytics.ai` for dashboard, `api.chatlytics.ai` for REST API, `mcp.chatlytics.ai` for MCP server? Or single domain with path routing?

8. **Existing admin panel**: The React admin panel (shadcn/ui + Vite) currently serves from the webhook server. In standalone mode, serve from same process or separate static hosting (Vercel/Cloudflare)?

9. **Rate limiting scope**: Current rate limiting is per-IP for admin routes and token-bucket for WAHA API calls. Multi-tenant needs per-workspace rate limits. How to layer these?

10. **Activity scanner in multi-tenant**: The scanner learns per-chat peak hours by reading message history. In a shared WAHA instance, do we run one scanner per workspace or share activity data across workspaces for the same phone number?
