chatwoot-develop/.context/docs/custom-architecture.md

81 lines
3.3 KiB
Markdown

# Custom Architecture: WuzAPI, Jasmine & Captain V2
This document outlines the **specific customizations** applied to this Chatwoot instance. It supersedes generic documentation for the modules listed below.
## 1. WuzAPI Integration Module (V1.5)
We do not use the standard WhatsApp Cloud API. We use a custom integration with **WuzAPI** (a Go-based WhatsApp gateway).
### 1.1 V1 Contract (Critical)
- **Token Storage:** TOKENS ARE NEVER PLAIN TEXT. They are stored in `encrypted_wuzapi_user_token` and `encrypted_wuzapi_admin_token` in the `channel_whatsapp` table.
- **Deduplication:** We use a `Redis` lock + `Source ID` check to prevent processing the same message twice (WuzAPI often sends retries).
- **Loop Protection:** Messages with `key.fromMe = true` are **OUTGOING** messages synced from the phone. They must be created as `message_type: :outgoing` and MUST NOT trigger bots.
### 1.2 Webhook Flow
1. **Ingress:** `POST /webhooks/whatsapp/:phone_number`
2. **Controller:** `Webhooks::WhatsappController` delegates to `WhatsappEventsJob`.
3. **Job:** Detects `wuzapi` provider -> delegates to `IncomingMessageWuzapiService`.
4. **Service:**
- Finds/Creates Contact (checking variations of DDI 55).
- Creates Message.
- **Sync Logic:** If `IsFromMe: true` -> Create Outgoing Message.
---
## 2. Jasmine Brain (The Intelligence Layer)
Jasmine is a specialized logical layer responsible for **Intent Detection**, **Strategy Decision**, and **Sales Development (SDR)** behavior.
### 2.1 Core Components
- **BrainService:** The entry point. Receives a conversation context and decides "What to do".
- **IntentDetector:** Analyzes user input (using Gemini/OpenAI) to classify intent (e.g., `sales_inquiry`, `support_ticket`, `spam`).
- **StrategyDecider:** Based on intent, decides the workflow (e.g., "Handover to human", "Consult Knowledge Base", "Qualify Lead").
- **Playbooks:** Structured scripts for SDR qualification (Ask Name -> Ask Budget -> Schedule Demo).
---
## 3. Captain V2 (The Unification)
We are unifying Jasmine (Brain) into Captain (Body).
### 3.1 Architecture Shift
- **Legacy Captain:** Used OpenAI hardcoded logic to summarize/reply.
- **Captain V2:** A flexible Agent Runner that executes the **Jasmine Brain**.
### 3.2 Key Classes
- **`AgentRunnerService`:** The orchestrator. It manages the conversation loop, tool execution, and thinking process.
- **`ProviderFactory`:** A factory that returns the configured LLM client (Gemini, OpenRouter, OpenAI) based on the Inbox settings.
- **`JasmineBrain`:** A specialized Agent/Tool injected into the runner to perform high-level reasoning.
### 3.3 Configuration (Multi-LLM)
Configurations are stored in `captain_inbox_configs` (or `chat_assistants`):
- `llm_provider`: `gemini` | `openai` | `openrouter`
- `llm_model`: `gemini-1.5-flash` | `gpt-4o`
- `api_key`: Encrypted credential for the specific inbox (optional, falls back to ENV).
---
## 4. Troubleshooting & Operational Rules
### 4.1 Database Connectivity
- Development uses Docker Postgres on **Port 5438**.
- `export POSTGRES_PORT=5438` is REQUIRED before `rails c` or `foreman start`.
### 4.2 Ruby Environment
- Project uses **Ruby 3.4.4**.
- Always run `eval "$(rbenv init -)"` if `bundle` fails.
### 4.3 Webhooks
- WuzAPI URL must include the FULL phone number with DDI (e.g., `5561...`).
- Database `phone_number` must match exactly.