9.2 KiB
9.2 KiB
Integrated Suite — Conversational Interface Plan
Pattern: Every suite app exposes its own
PROMPT.md+ internal tools. The shared chat bar activates app-specific context when the user is inside that app. WhatsApp campaigns is the first full example.
Architecture
User (WhatsApp / Suite chat bar)
↓
BotOrchestrator (core/bot/mod.rs)
↓
detect active app context
↓
load app PROMPT.md + app InternalTools
↓
LLM with tools → tool_executor.rs
↓
app data / actions
Key existing pieces
| File | Role |
|---|---|
core/bot/mod.rs |
get_session_tools() + ToolExecutor::execute_tool_call() |
tasks/PROMPT.md |
Pattern for app-level LLM prompt |
marketing/whatsapp.rs |
WhatsApp campaign send/metrics |
marketing/campaigns.rs |
Campaign CRUD |
marketing/lists.rs |
Recipient lists |
botui/ui/suite/campaigns/ |
Campaigns UI |
Standard: Every Suite App
1. PROMPT.md per app folder
Location: botserver/src/<app>/PROMPT.md
# <App> — Internal Tools Guide
You are the <App> assistant. When the user is in <App>, you have access to:
- tool: list_<entities>
- tool: create_<entity>
- tool: search_<entity>
- tool: <app_specific_action>
Rules:
- Always confirm destructive actions before executing
- Show results as structured summaries, not raw JSON
- If user uploads a file, parse it and confirm before acting
2. tools.rs per app
Location: botserver/src/<app>/tools.rs
Registers Vec<Tool> (LLM function-calling schema) + handler mapping.
Loaded by get_session_tools() when session's active app = this app.
3. App context detection
core/bot/mod.rs reads session.active_app (set by UI via POST /api/session/context).
Loads <app>/PROMPT.md as system prompt prefix + <app>/tools.rs tools.
WhatsApp Campaigns — Full Conversational Flow
Meta Rules (enforced in tools)
- Only approved Message Templates for marketing (non-session-initiated)
- 24h session window for free-form after user replies
- Media: image/video/document via Media Upload API before send
- Opt-out: always honor STOP, add to suppression list immediately
- Rate: respect per-phone-number rate limits (1000 msg/s business tier)
- Template category: MARKETING requires explicit opt-in from recipient
Conversation Flow (WhatsApp → campaign creation)
User sends to bot number:
"I want to send a campaign"
↓
Bot: "Great! Send me:
1. Your contact list (.xlsx or .csv)
2. The message text
3. An image (optional)
4. When to send (or 'now')"
↓
User uploads contacts.xlsx
↓
[tool: parse_contact_file]
→ extract phone numbers, names
→ validate E.164 format
→ show preview: "Found 342 contacts. First 3: +55..."
↓
User sends message text
↓
[tool: check_template_compliance]
→ check if free-form or needs approved template
→ if template needed: list available approved templates
→ suggest closest match
↓
User sends image (optional)
↓
[tool: upload_media]
→ upload to Meta Media API
→ return media_id
↓
Bot: "Ready to send to 342 contacts at 14:00 today.
Preview: [image] Hello {name}, ...
Estimated cost: $X
Confirm? (yes/no)"
↓
User: "yes"
↓
[tool: create_and_schedule_campaign]
→ create campaign record
→ apply warmup limit if IP warming
→ schedule via TaskScheduler
WhatsApp Campaign Tools (marketing/whatsapp_tools.rs)
// Tool definitions for LLM function calling
pub fn whatsapp_campaign_tools() -> Vec<Tool> {
vec![
Tool::new("parse_contact_file", "Parse uploaded xlsx/csv into contact list"),
Tool::new("list_templates", "List approved WhatsApp message templates"),
Tool::new("check_template_compliance", "Check if message needs approved template"),
Tool::new("upload_media", "Upload image/video to Meta Media API"),
Tool::new("preview_campaign", "Show campaign preview with cost estimate"),
Tool::new("create_and_schedule_campaign", "Create campaign and schedule send"),
Tool::new("get_campaign_status", "Get delivery/read metrics for a campaign"),
Tool::new("pause_campaign", "Pause an in-progress campaign"),
Tool::new("list_campaigns", "List recent campaigns with metrics"),
Tool::new("add_to_suppression", "Add number to opt-out list"),
]
}
WhatsApp PROMPT.md (marketing/WHATSAPP_PROMPT.md)
# WhatsApp Campaign Assistant
You help users create and manage WhatsApp marketing campaigns.
## Meta Platform Rules (MANDATORY)
- Marketing messages MUST use pre-approved templates outside 24h session window
- Always check opt-in status before adding to campaign
- Honor STOP/unsubscribe immediately via add_to_suppression tool
- Never send more than warmup daily limit if IP is warming up
- Image must be uploaded via upload_media before referencing in campaign
## Conversation Style
- Guide step by step: contacts → message → media → schedule → confirm
- Show cost estimate before confirming
- After send: proactively share open/read rates when available
## File Handling
- .xlsx/.csv → use parse_contact_file tool
- Images → use upload_media tool
- Always confirm parsed data before proceeding
Integrated Suite Chat Bar — Standard
How it works
- User opens any suite app (CRM, Campaigns, Drive, etc.)
- Chat bar at bottom activates with app context
POST /api/session/context { app: "campaigns" }setssession.active_app- BotOrchestrator loads
campaigns/PROMPT.md+campaigns/tools.rs - User can ask natural language questions or trigger actions
Examples per app
| App | Example query | Tool activated |
|---|---|---|
| Campaigns | "How did last week's campaign perform?" | get_campaign_metrics |
| CRM | "Show deals closing this month" | list_deals with filter |
| Drive | "Find the Q1 report" | search_files |
| Tasks | "Create a task to follow up with Acme" | create_task |
| People | "Who hasn't been contacted in 30 days?" | list_contacts with filter |
| "Summarize unread emails from clients" | list_emails + LLM summary |
|
| Sheet | "What's the total revenue in column D?" | query_sheet |
| Learn | "What does our refund policy say?" | search_kb |
Implementation Plan
Phase 1 — Infrastructure (1 sprint)
core/bot/mod.rs— readsession.active_app, load app PROMPT + toolscore/tool_context.rs— app tool registry:register_app_tools(app_name) -> Vec<Tool>POST /api/session/context— set active app from UI- Suite chat bar UI component (
botui/ui/suite/partials/chatbar.html)
Phase 2 — WhatsApp Campaigns (1 sprint)
marketing/whatsapp_tools.rs— 10 tools abovemarketing/WHATSAPP_PROMPT.mdmarketing/file_parser.rs— xlsx/csv → contact list- Meta warmup enforcement in send path
- Conversational campaign creation flow (state machine in session)
Phase 3 — App-by-app rollout (1 app/sprint)
Priority order based on value:
- CRM (deals, contacts, pipeline queries)
- Campaigns (email + WhatsApp)
- Tasks (create, assign, status)
- Drive (search, summarize docs)
- Mail (summarize, draft reply)
- People (segment, find contacts)
- Sheet (query, calculate)
- Learn (KB search)
Phase 4 — Cross-app intelligence
- Global search across all apps via single query
- "What happened today?" — aggregates activity across CRM + Mail + Tasks
- Proactive suggestions: "You have 3 deals closing this week and no follow-up tasks"
File Structure to Create
botserver/src/
├── marketing/
│ ├── whatsapp_tools.rs ← NEW: LLM tool definitions + handlers
│ ├── WHATSAPP_PROMPT.md ← NEW: WhatsApp assistant system prompt
│ ├── file_parser.rs ← NEW: xlsx/csv → contacts
│ └── warmup.rs ← NEW: (from campaigns.md plan)
├── core/
│ ├── tool_registry.rs ← NEW: app → tools mapping
│ └── bot/
│ └── app_context.rs ← NEW: load app prompt + tools per session
├── crm/
│ ├── tools.rs ← NEW
│ └── PROMPT.md ← NEW
├── tasks/
│ └── tools.rs ← NEW (PROMPT.md exists)
└── <each app>/
├── tools.rs ← NEW per app
└── PROMPT.md ← NEW per app
botui/ui/suite/
└── partials/
└── chatbar.html ← NEW: shared chat bar component
Chat Bar UI (partials/chatbar.html)
<div id="suite-chatbar" class="chatbar">
<div id="chatbar-messages" hx-ext="ws" ws-connect="/ws/suite-chat"></div>
<form ws-send>
<input type="hidden" name="app_context" value="{{ active_app }}">
<input type="file" id="chatbar-file" name="file" accept=".xlsx,.csv,.png,.jpg,.pdf" style="display:none">
<button type="button" onclick="document.getElementById('chatbar-file').click()">📎</button>
<input type="text" name="message" placeholder="Ask anything about {{ active_app }}...">
<button type="submit">→</button>
</form>
</div>
File uploads go to POST /api/suite/upload → stored in Drive → media_id passed to tool.