Author: Claude Opus 4.5 (Anthropic) Date: 2026-01-28 Status: Proposal
This plan transforms Moltbot from a self-hosted CLI-first messaging gateway into a cloud-hosted consumer product. The core value proposition shifts from "set up your own AI messaging hub" to "connect your messaging apps and get an AI assistant across all of them in under 2 minutes."
The architecture decomposes the current monolithic gateway into cloud-native services while preserving the proven channel plugin system, reply pipeline, and protocol foundations. iMessage remains the only local component via an edge connector.
The monolithic gateway splits into five services:
┌─────────────────────────────┐
│ Web / Mobile UI │
│ (Next.js + React Native) │
└──────────────┬──────────────┘
│ HTTPS / WSS
▼
┌──────────────────────────────────────────────────────────────────┐
│ Moltbot Cloud │
│ │
│ ┌─────────────┐ ┌──────────────┐ ┌──────────────────────────┐│
│ │ Control API │ │ Realtime │ │ Agent Runner ││
│ │ (Hono/Bun) │ │ Gateway │ │ (Stateless workers) ││
│ │ │ │ (WSS+SSE) │ │ Claude API + tools ││
│ └──────┬───────┘ └──────┬──────┘ └────────────┬─────────────┘│
│ │ │ │ │
│ ▼ ▼ ▼ │
│ ┌────────────────────────────────────────────────────────────┐ │
│ │ Supabase (Managed) │ │
│ │ Postgres │ Auth │ Realtime │ Storage │ Edge Functions │ │
│ └────────────────────────────────────────────────────────────┘ │
│ │
│ ┌──────────────────────────────────────────────────────────────┐│
│ │ Connector Workers (Fly.io) ││
│ │ Telegram │ Discord │ Slack │ WhatsApp │ Signal │ Teams ││
│ └──────────────────────────────────────────────┬───────────────┘│
└──────────────────────────────────────────────────│───────────────┘
│
WSS (outbound only)
│
┌──────────────▼──────────────┐
│ iMessage Edge Connector │
│ (macOS menubar app) │
└─────────────────────────────┘
- JWT verification (Supabase Auth tokens)
- Tenant authorization (RBAC)
- Channel account CRUD + connect/disconnect flows
- Idempotent message send (writes to outbox)
- Device pairing for edge connectors
- Routing rule management
- Billing/usage metering
- WebSocket/SSE subscriptions for clients
- Event fan-out from the
eventstable - Resume-from-offset support (
event_idbased) - Presence tracking (which conversations user is viewing)
- Stateless Claude API execution per conversation turn
- Tool orchestration (web search, code execution, media analysis)
- Streaming responses back via events table
- Model selection per tenant/agent configuration
- Token usage tracking and budget enforcement
- One process per channel type (or per-account for WhatsApp)
- Consume outbox commands (send, start_login, refresh_status)
- Ingest inbound messages into normalized schema
- Manage channel credentials (encrypted in DB)
- Emit status events (connected, disconnected, error, QR updates)
- Accept outbound WSS from macOS edge connectors
- Device pairing via one-time codes
- Forward inbound iMessage to DB
- Push outbound sends to connected devices
-- Multi-tenant foundation
CREATE TABLE tenants (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
name TEXT NOT NULL,
plan TEXT NOT NULL DEFAULT 'free' CHECK (plan IN ('free','pro','team','enterprise')),
stripe_customer_id TEXT,
created_at TIMESTAMPTZ NOT NULL DEFAULT now()
);
CREATE TABLE tenant_members (
tenant_id UUID NOT NULL REFERENCES tenants(id) ON DELETE CASCADE,
user_id UUID NOT NULL, -- Supabase auth.users.id
role TEXT NOT NULL CHECK (role IN ('owner','admin','member')),
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
PRIMARY KEY (tenant_id, user_id)
);
-- Channel connections
CREATE TABLE channel_accounts (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
tenant_id UUID NOT NULL REFERENCES tenants(id) ON DELETE CASCADE,
channel TEXT NOT NULL, -- 'telegram','discord','slack','whatsapp','signal','imessage','msteams'
account_key TEXT NOT NULL DEFAULT 'default',
status TEXT NOT NULL CHECK (status IN ('connected','connecting','disconnected','error','paused')),
display_name TEXT,
metadata JSONB DEFAULT '{}',
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT now(),
UNIQUE (tenant_id, channel, account_key)
);
CREATE TABLE channel_credentials (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
channel_account_id UUID NOT NULL REFERENCES channel_accounts(id) ON DELETE CASCADE,
cipher_version INT NOT NULL DEFAULT 1,
encrypted_blob BYTEA NOT NULL, -- AES-256-GCM encrypted
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
rotated_at TIMESTAMPTZ
);
-- Conversations and messages
CREATE TABLE conversations (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
tenant_id UUID NOT NULL REFERENCES tenants(id) ON DELETE CASCADE,
channel_account_id UUID NOT NULL REFERENCES channel_accounts(id) ON DELETE CASCADE,
channel TEXT NOT NULL,
remote_conversation_id TEXT NOT NULL,
kind TEXT NOT NULL CHECK (kind IN ('direct','group','channel','thread')),
title TEXT,
last_message_at TIMESTAMPTZ,
metadata JSONB DEFAULT '{}',
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT now(),
UNIQUE (tenant_id, channel_account_id, remote_conversation_id)
);
CREATE TABLE messages (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
tenant_id UUID NOT NULL REFERENCES tenants(id) ON DELETE CASCADE,
conversation_id UUID NOT NULL REFERENCES conversations(id) ON DELETE CASCADE,
channel TEXT NOT NULL,
direction TEXT NOT NULL CHECK (direction IN ('in','out')),
sender_display TEXT,
content JSONB NOT NULL, -- [{type:'text',text:'...'}, {type:'image',url:'...',mime:'...'}]
media JSONB, -- [{bucket,path,mime,size,sha256}]
provider_message_id TEXT,
agent_run_id UUID, -- links to agent_runs if AI-generated
tokens_in INT,
tokens_out INT,
model TEXT,
raw_envelope JSONB, -- original provider payload
created_at TIMESTAMPTZ NOT NULL DEFAULT now()
);
CREATE INDEX idx_messages_conv_time ON messages (tenant_id, conversation_id, created_at);
CREATE INDEX idx_messages_search ON messages USING gin (
to_tsvector('english', COALESCE(content->0->>'text', ''))
);
-- Deduplication
CREATE TABLE message_dedupe (
tenant_id UUID NOT NULL,
channel_account_id UUID NOT NULL,
provider_message_id TEXT NOT NULL,
message_id UUID NOT NULL REFERENCES messages(id) ON DELETE CASCADE,
PRIMARY KEY (tenant_id, channel_account_id, provider_message_id)
);
-- Command outbox (DB-based queue)
CREATE TABLE outbox (
id BIGSERIAL PRIMARY KEY,
tenant_id UUID NOT NULL REFERENCES tenants(id) ON DELETE CASCADE,
channel TEXT NOT NULL,
channel_account_id UUID REFERENCES channel_accounts(id),
kind TEXT NOT NULL, -- 'send_message','start_login','stop_connector','refresh_status'
idempotency_key TEXT,
payload JSONB NOT NULL,
status TEXT NOT NULL DEFAULT 'pending' CHECK (status IN ('pending','claimed','done','error')),
claimed_by TEXT,
claimed_at TIMESTAMPTZ,
next_attempt_at TIMESTAMPTZ NOT NULL DEFAULT now(),
attempt_count INT NOT NULL DEFAULT 0,
last_error TEXT,
created_at TIMESTAMPTZ NOT NULL DEFAULT now()
);
CREATE INDEX idx_outbox_pending ON outbox (status, next_attempt_at) WHERE status = 'pending';
CREATE UNIQUE INDEX idx_outbox_idem ON outbox (tenant_id, kind, idempotency_key)
WHERE idempotency_key IS NOT NULL;
-- Event log (durable, replayable)
CREATE TABLE events (
id BIGSERIAL PRIMARY KEY,
tenant_id UUID NOT NULL REFERENCES tenants(id) ON DELETE CASCADE,
type TEXT NOT NULL, -- 'message.received','message.sent','channel.status','channel.qr','agent.started','agent.streaming','agent.complete'
payload JSONB NOT NULL,
created_at TIMESTAMPTZ NOT NULL DEFAULT now()
);
CREATE INDEX idx_events_tenant ON events (tenant_id, id);
-- Agent configuration
CREATE TABLE agents (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
tenant_id UUID NOT NULL REFERENCES tenants(id) ON DELETE CASCADE,
name TEXT NOT NULL DEFAULT 'default',
model TEXT NOT NULL DEFAULT 'claude-sonnet-4-5-20250929',
system_prompt TEXT,
tools JSONB DEFAULT '[]',
routing_rules JSONB DEFAULT '{}', -- which channels/conversations route to this agent
enabled BOOLEAN DEFAULT true,
created_at TIMESTAMPTZ NOT NULL DEFAULT now()
);
-- Agent execution runs
CREATE TABLE agent_runs (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
tenant_id UUID NOT NULL REFERENCES tenants(id) ON DELETE CASCADE,
agent_id UUID NOT NULL REFERENCES agents(id),
conversation_id UUID NOT NULL REFERENCES conversations(id),
trigger_message_id UUID REFERENCES messages(id),
status TEXT NOT NULL CHECK (status IN ('pending','running','complete','error','cancelled')),
model TEXT NOT NULL,
tokens_in INT,
tokens_out INT,
cost_usd NUMERIC(10,6),
started_at TIMESTAMPTZ,
completed_at TIMESTAMPTZ,
error TEXT,
created_at TIMESTAMPTZ NOT NULL DEFAULT now()
);
-- Device pairing (for iMessage edge connectors)
CREATE TABLE devices (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
tenant_id UUID NOT NULL REFERENCES tenants(id) ON DELETE CASCADE,
display_name TEXT,
token_hash TEXT NOT NULL, -- bcrypt hash of device token
last_seen_at TIMESTAMPTZ,
created_at TIMESTAMPTZ NOT NULL DEFAULT now()
);
CREATE TABLE device_pairing_codes (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
tenant_id UUID NOT NULL REFERENCES tenants(id) ON DELETE CASCADE,
code TEXT NOT NULL UNIQUE,
expires_at TIMESTAMPTZ NOT NULL,
used_at TIMESTAMPTZ,
device_id UUID REFERENCES devices(id)
);
-- Usage metering
CREATE TABLE usage_records (
id BIGSERIAL PRIMARY KEY,
tenant_id UUID NOT NULL REFERENCES tenants(id) ON DELETE CASCADE,
period DATE NOT NULL, -- YYYY-MM-DD (daily bucket)
metric TEXT NOT NULL, -- 'messages_in','messages_out','ai_tokens_in','ai_tokens_out','media_bytes'
value BIGINT NOT NULL DEFAULT 0,
UNIQUE (tenant_id, period, metric)
);| Layer | Technology | Rationale |
|---|---|---|
| Auth | Supabase Auth | OAuth (Google/GitHub/Apple), magic link, handles JWTs, free tier generous |
| Database | Supabase Postgres | Managed, RLS, Realtime built-in, Storage included |
| Realtime | Supabase Realtime | Subscribe to events table inserts, no extra infra |
| Object Storage | Supabase Storage | Media blobs, signed URLs, integrated with auth |
| Compute | Fly.io | Long-lived processes for connectors, global edge, affordable |
| API Framework | Hono on Bun | Fast, TypeScript, works on Fly.io and Cloudflare |
| Web UI | Next.js on Vercel | SSR, fast, great DX, easy deploy |
| Mobile | React Native (existing apps) | Already built, connect directly to cloud |
| Mac App | Swift/SwiftUI (existing) | Becomes thin client + iMessage edge connector |
| Payments | Stripe | Industry standard, usage-based billing support |
| Monitoring | Sentry + Axiom | Error tracking + structured logs |
| CI/CD | GitHub Actions | Already in use |
-
Supabase over custom: Supabase gives us Auth + Postgres + Realtime + Storage in one managed service. This eliminates 4 separate infrastructure decisions and reduces ops burden dramatically.
-
DB-based outbox over message queue: A Postgres outbox table (
SELECT ... FOR UPDATE SKIP LOCKED) eliminates the need for Redis/NATS/Kafka initially. Scales to thousands of messages/minute before needing a dedicated queue. -
Fly.io for long-lived workers: WhatsApp Web (Baileys), Discord gateway, and Slack socket mode require persistent connections. Fly.io supports long-lived processes at $3-7/mo per machine.
-
Event log for subscriptions: Instead of ephemeral WebSocket events (current model), every state change writes to
events. Clients subscribe with a resume offset. This is the single biggest architectural improvement. -
Credential encryption at application layer: Even with Supabase's DB encryption at rest, we encrypt channel credentials with a separate key held only by Fly.io services. Defense in depth.
| Step | Current (Self-Hosted) | Proposed (Cloud) |
|---|---|---|
| Entry point | npm i -g moltbot |
Visit moltbot.com |
| Account | None (local) | OAuth signup (Google/GitHub/Apple) |
| Configure AI | Set ANTHROPIC_API_KEY in env |
BYOK or included credits |
| Start gateway | moltbot gateway start |
Automatic (cloud) |
| Connect channel | CLI prompts | Web dashboard |
| First message | ~10 minutes | ~90 seconds |
1. Visit moltbot.com → "Get Started Free"
2. OAuth (Google / GitHub / Apple) → 1 click
3. Auto-create tenant + default agent
4. Land on dashboard: "Connect your first channel"
5. Pick channel → guided connect flow
6. Send first message → AI responds
- Dashboard shows step-by-step guide with screenshots
- User pastes bot token
- Backend validates token, starts connector
- Status goes
connecting→connected - Dashboard shows "Ready! Send a message to @YourBot"
- Click "Connect Slack" → OAuth popup
- User authorizes workspace
- Callback stores tokens, starts connector
- Dashboard shows workspace connected
- Click "Connect WhatsApp"
- Dashboard shows QR code (streamed from connector via events)
- User scans with phone WhatsApp
- Session authenticated, connector stores credentials
- Dashboard shows "WhatsApp connected"
- Click "Connect iMessage"
- Dashboard shows: "Install the Moltbot app on your Mac, then enter this code:
AB3X-7KMN" - One-liner install:
curl -sSL https://molt.bot/install | bashor Mac App Store - Mac app prompts for pairing code
- Edge connector establishes WSS, starts streaming
- Dashboard shows "iMessage connected"
Free tier: Uses included Claude Haiku credits (limited). No API key needed.
Pro tier: Options:
- "Use included credits" (metered, part of subscription)
- "Bring your own key" (Anthropic, OpenAI, Google) → paste key, select model
Agent customization (post-onboarding):
- System prompt editor with templates ("Personal assistant", "Customer support", "Creative writer")
- Tool toggles (web search, code execution, image generation)
- Per-channel routing rules
- No installation for cloud channels
- OAuth instead of manual token setup for Slack/Teams
- Guided QR flow for WhatsApp (same as web.whatsapp.com)
- Default agent pre-configured (no AI setup needed on free tier)
- Instant feedback - dashboard shows messages in real-time
The primary interface for cloud users. Built with Next.js + shadcn/ui.
Pages:
/- Landing page + pricing/login- Auth (Supabase Auth UI)/dashboard- Overview: connected channels, recent conversations, usage stats/conversations- Unified inbox across all channels with search/conversations/:id- Conversation view with real-time messages/channels- Manage connected channels (connect/disconnect/status)/agents- Configure AI agents (model, system prompt, tools, routing)/settings- Account, billing, API keys, team members/bridge- iMessage/local bridge setup and status
Key features:
- Real-time message streaming via Supabase Realtime
- Full-text search across all messages
- Conversation filters by channel, date, participant
- Inline media viewing (images, audio playback)
- Agent configuration with live preview
- Usage graphs and billing
Current: Hosts the gateway process, native notifications, voice wake.
Proposed: Becomes a thin cloud client + iMessage edge connector.
- Remove: Gateway hosting, local channel management, local config UI
- Keep: iMessage bridge (via edge connector), native notifications, voice wake, menubar status
- Add: Cloud auth (Supabase JWT), cloud connection indicator, pairing flow UI
- Architecture: The app connects to cloud via WSS. iMessage messages flow: iMessage → local imsg → edge connector → WSS → cloud → DB. Outbound: cloud → WSS → edge connector → imsg → iMessage.
Current: Connect to local gateway via bridge protocol (TCP JSONL).
Proposed: Connect directly to cloud API.
- Remove: Bridge protocol client, gateway discovery, local pairing
- Keep: Push notifications, conversation UI, media handling
- Add: Supabase Auth, direct API calls, Supabase Realtime subscriptions
- Benefit: No gateway needed. Phone connects to cloud directly. Push notifications via FCM/APNs triggered by cloud events.
Current: Full gateway lifecycle management (moltbot gateway start/stop/status).
Proposed: Cloud client + optional self-hosted mode.
# Cloud mode (default)
moltbot login # Supabase Auth (opens browser)
moltbot channels list # List connected channels (from cloud)
moltbot channels connect telegram # Connect channel (opens browser flow)
moltbot conversations list # List recent conversations
moltbot send "Hello" --to "+1234567890" --channel imessage
moltbot agent config # Configure agent (opens browser)
moltbot status # Cloud status (channels, usage, plan)
# Self-hosted mode (preserved for power users)
moltbot gateway start --self-hosted # Original local gatewayThe CLI becomes primarily a convenience interface for the cloud API, with self-hosted mode preserved as an advanced option.
- 1 AI agent
- 2 channel connections
- 500 AI messages/month (Claude Haiku)
- 100 MB media storage
- 30-day message retention
- Community support
- 3 AI agents
- Unlimited channel connections
- 5,000 AI messages/month (Claude Sonnet)
- 5 GB media storage
- Unlimited message retention
- Full-text search
- Priority support
- BYOK for any model (no message limit with own key)
- Everything in Pro
- 5 team members included
- Shared conversation views
- Role-based access control
- Audit log
- SSO (Google Workspace, Okta)
- Everything in Team
- Unlimited seats
- Dedicated infrastructure
- Custom SLA
- On-premise option
- SOC 2 compliance
- Dedicated support
- Additional AI messages: $0.01/message (Haiku), $0.05/message (Sonnet), $0.15/message (Opus)
- Additional storage: $0.50/GB/month
- WhatsApp Business API: $5/mo (uses official Cloud API instead of Web)
Cost per free user: ~$0.30/mo (DB rows, minimal compute) Cost per Pro user: ~$2-4/mo (DB, compute, AI credits) Target margin: 70-80% on Pro tier
Path to $1M ARR: ~5,500 Pro subscribers or ~7,000 Team seats.
BYOK (Bring Your Own Key) is strategically important:
- Eliminates AI cost risk for us
- Appeals to power users who want specific models
- Pro with BYOK has excellent margins (~90%)
- Users feel ownership of their AI spend
- Create Supabase project
- Deploy schema with RLS policies
- Set up Storage buckets
- Configure Auth providers (Google, GitHub, Apple)
Acceptance: Signed-in user can create tenant and read only their data.
- Deploy Hono API on Fly.io
- JWT verification, tenant auth middleware
- Channel account CRUD
- Outbox writes for send/connect commands
- Telegram connector (simplest, webhook-based)
- Basic web dashboard (Next.js) with auth + Telegram connect
Acceptance: User signs up, connects Telegram bot, sends/receives messages via dashboard.
- Discord connector (WebSocket gateway)
- Slack connector (Events API)
- Supabase Realtime subscriptions for events table
- Dashboard conversation view with real-time updates
- Message search (Postgres full-text)
Acceptance: Multi-channel inbox with live updates.
- Stateless agent execution on Fly.io
- Claude API integration with streaming
- Tool support (web search, image analysis)
- Agent configuration UI
- Token usage tracking
Acceptance: Incoming messages trigger AI responses, streamed to dashboard and back to channel.
- WhatsApp Web connector (Baileys)
- QR code streaming via events
- Credential persistence (encrypted)
- Reconnect handling
Acceptance: User connects WhatsApp by scanning QR in dashboard.
- iMessage edge hub (Fly.io WSS)
- Device pairing (one-time code flow)
- Mac app refactor (edge connector mode)
- Inbound/outbound message relay
Acceptance: iMessage messages appear in cloud dashboard; can send from dashboard.
- Mobile app refactor (direct cloud connection)
- Push notifications via cloud events
- Stripe integration for billing
- Usage metering and limits
- Plan upgrade/downgrade flows
Acceptance: Full consumer product ready for public launch.
- Signal connector
- MS Teams connector (via extension)
- Analytics dashboard
- Team features (shared views, RBAC)
- Self-hosted migration tool
- Performance optimization
For existing self-hosted users:
moltbot migrate --to-cloudcommand- Exports local JSONL transcripts + session metadata
- Creates cloud account, uploads history
- Re-authenticates channels in cloud
- Verifies message parity
- Decommissions local gateway
Self-hosted mode remains available indefinitely as an advanced option.
| Risk | Impact | Likelihood | Mitigation |
|---|---|---|---|
| WhatsApp Web (Baileys) instability | High | Medium | Parallel Cloud API connector for business accounts |
| Supabase Realtime scaling | Medium | Low | Can migrate to dedicated NATS/Kafka if needed |
| AI cost overruns on free tier | High | Medium | Strict rate limits, Haiku-only, low context window |
| iMessage edge connector complexity | Medium | Medium | Phase 5 (not blocking launch) |
| Channel credential security breach | Critical | Low | App-layer encryption, key rotation, audit logging |
For non-technical users: "One AI assistant across all your messaging apps. No setup, no coding."
For technical users: "The messaging hub you'd build yourself, but managed. BYOK, extensible, with a self-hosted escape hatch."
| Feature | Moltbot Cloud | Beeper | texts.com | Unified Inbox Apps |
|---|---|---|---|---|
| AI Agent | Yes (core feature) | No | No | No |
| Multi-channel | 7+ channels | 15+ | 5+ | Varies |
| Self-hosted option | Yes | No | No | No |
| BYOK AI | Yes | N/A | N/A | N/A |
| Open source | Partial (CLI) | No | No | No |
| Price | $0-15/mo | $0-5/mo | Free | Varies |
Key differentiator: Moltbot is the only unified messaging platform with a built-in AI agent. This is not "yet another inbox aggregator" -- it's "your AI assistant, everywhere you chat."
-
Message history lock-in (positive): All your messages in one searchable place. The longer you use it, the more valuable the archive.
-
AI personalization: Agent learns your preferences, writing style, and context over time. Switching away means losing this.
-
Cross-channel continuity: Start a conversation on Telegram, continue on WhatsApp, reference it from iMessage. Only works with Moltbot.
-
Automation rules: "If anyone messages me on Telegram after 10pm, auto-reply with my AI." Power users build workflows that are hard to replicate.
- Launch on Product Hunt with free tier
- Content marketing: "How I replaced 5 messaging apps with one AI" blog posts
- Developer community: Open-source the channel plugin SDK, encourage community connectors
- Referrals: "Invite a friend, get 1 month Pro free"
- Integration marketplace: Let users share agent configurations and tool setups
- No jargon: Dashboard uses plain language ("Connect Telegram" not "Configure Telegram Bot API webhook")
- Guided setup: Step-by-step wizards with screenshots for each channel
- Sensible defaults: AI agent works out of the box without configuration
- Mobile-first: Most consumers will primarily use mobile app
- Support: In-app chat support (powered by Moltbot itself, of course)
POST /v1/auth/signup # Create account
POST /v1/auth/login # OAuth flow
GET /v1/channels # List available channels
POST /v1/channels/connect # Start channel connection
DELETE /v1/channels/:id # Disconnect channel
GET /v1/channels/status # All channel statuses
GET /v1/conversations # List conversations (paginated)
GET /v1/conversations/:id # Conversation detail
GET /v1/conversations/:id/messages # Messages (paginated, cursor-based)
POST /v1/messages/send # Send message (idempotent)
GET /v1/messages/search # Full-text search
GET /v1/agents # List agents
POST /v1/agents # Create agent
PUT /v1/agents/:id # Update agent config
POST /v1/agents/:id/test # Test agent with sample input
POST /v1/devices/pair # Generate pairing code
GET /v1/devices # List paired devices
GET /v1/usage # Usage stats
GET /v1/billing # Billing info
POST /v1/billing/upgrade # Upgrade plan
// Client → Server
{ type: 'subscribe', filters: { tenant_id: '...', since_event_id: 12345 } }
{ type: 'unsubscribe' }
// Server → Client
{ type: 'event', event: { id: 12346, type: 'message.received', payload: {...} } }
{ type: 'event', event: { id: 12347, type: 'agent.streaming', payload: { text: 'Hello...', delta: ' world' } } }
{ type: 'event', event: { id: 12348, type: 'channel.status', payload: { channel: 'telegram', status: 'connected' } } }| Resource | Service | Cost |
|---|---|---|
| Supabase (Pro) | Database + Auth + Realtime + Storage | $25/mo base |
| Fly.io Control API | 1x shared-cpu-1x 256MB | $3/mo |
| Fly.io Connector Workers | 2x shared-cpu-1x 512MB | $14/mo |
| Fly.io Edge Hub | 1x shared-cpu-1x 256MB | $3/mo |
| Fly.io Agent Runner | 1x shared-cpu-2x 512MB | $7/mo |
| Vercel (Web) | Pro plan | $20/mo |
| Sentry | Team plan | $26/mo |
| Stripe | 2.9% + $0.30/transaction | Variable |
| Domain + DNS | Cloudflare | $0/mo |
| Total base | ~$100/mo |
At 1,000 users: ~$200/mo (mostly Supabase compute scaling) At 10,000 users: ~$800/mo (add Fly.io machines, Supabase scaling) At 100,000 users: ~$5,000/mo (dedicated Postgres, multiple Fly regions)
This gives excellent unit economics at the Pro tier ($15/mo) with costs under $1/user/mo at scale.
The transformation from self-hosted gateway to cloud consumer product requires:
- Decomposing the monolithic gateway into 5 cloud services
- Replacing file-based storage with Supabase Postgres + Storage
- Adding durable event log with replayable subscriptions
- Building a web dashboard as the primary consumer interface
- Refactoring Mac and mobile apps from gateway clients to cloud clients
- Preserving the channel plugin system and reply pipeline
- Implementing Stripe billing with free/pro/team/enterprise tiers
The phased approach delivers value early (Phase 1-3 = functional cloud product with Telegram + AI) while deferring complex work (iMessage edge, billing) to later phases. Self-hosted mode is preserved as an escape hatch for power users.
The key insight: Moltbot's unique value is not "unified messaging" (Beeper does that) -- it's "AI assistant across all your messaging channels." The cloud product should lead with AI and treat channel aggregation as the enabling infrastructure.