Last Updated: 2026-04-07 Status: Active (v2 — updated for Contact Intelligence integration)
This document defines the core business entities and their relationships for the Chat Engine.
1. Architecture Split
With AI Brain and Contact Intelligence now built, the Chat Engine's domain is narrower than originally planned:
| Domain | Owned By | Not Chat Engine |
|---|---|---|
| Sessions & Messages | Chat Engine | |
| Bot Config & Channels | Chat Engine | |
| Knowledge Base (RAG) | AI Brain | Moved to brain-service |
| Customer Memory/Mood | Contact Intelligence | ci_contact_* tables |
| Customer Entity Graph | Contact Intelligence | ci_contact_entities |
| Proactive Outreach | Contact Intelligence | ci_outreach_* tables |
| LLM Orchestration | AI Brain | brain orchestrator |
| Cost Governance | AI Brain | cost-governor |
2. Chat Engine Entities
2.1 BotConfig (1:1 per Tenant)
The AI persona and behavior settings.
| Field | Type | Required | Description |
|---|---|---|---|
id |
uuid | Y | Primary key |
tenantId |
string | Y | Workspace owner |
name |
string | Y | Persona name (e.g., "Sarah"). Default: "AI Assistant" |
personaPrompt |
text | Y | System instructions for tone and boundaries |
fallbackMessage |
text | Y | Message before human escalation |
handoffTrigger |
string | Y | Hidden LLM trigger string (e.g., [[HANDOFF]]) |
activeModel |
enum | Y | haiku, sonnet, opus (maps to AI Brain model tiers) |
creativity |
float | Y | LLM temperature (0.0–1.0). Default: 0.2 |
leadCaptureRules |
jsonb | N | Rules: [{ trigger: "pricing", askFor: "email", message: "..." }] |
createdAt |
date | Y | |
updatedAt |
date | Y |
Note: personaPrompt is merged with AI Brain's personality config. Brain's personality.customInstructions provides business context, while personaPrompt provides chatbot-specific behavior rules.
2.2 ChannelIntegration
Where the chatbot listens for messages.
| Field | Type | Required | Description |
|---|---|---|---|
id |
uuid | Y | Primary key |
tenantId |
string | Y | Workspace owner |
platform |
enum | Y | website_widget, whatsapp, telegram, instagram |
identifier |
string | Y | Platform-specific ID (phone number, bot ID, domain) |
credentials |
jsonb | Y | AES-256-GCM encrypted. OAuth tokens, API keys, webhook secrets |
status |
enum | Y | active, paused, auth_failed, rate_limited |
createdAt |
date | Y | |
updatedAt |
date | Y |
2.3 ChatSession
A conversation thread. The contactId links to Contact Intelligence for memory/mood.
| Field | Type | Required | Description |
|---|---|---|---|
id |
uuid | Y | Primary key |
tenantId |
string | Y | Workspace owner |
channelId |
uuid | Y | → ChannelIntegration |
contactId |
string | N | → Contact Intelligence ci_contacts.id. Null for anonymous widget |
status |
enum | Y | ai_handled, human_escalated, closed |
assignedAgentId |
string | N | Dashboard team member handling this chat |
summary |
text | N | AI-generated on session close |
slaBreachAt |
date | N | Escalation timeout |
messageCount |
int | Y | Running count |
createdAt |
date | Y | |
lastMessageAt |
date | Y |
2.4 ChatMessage
Immutable message atom. Append-only.
| Field | Type | Required | Description |
|---|---|---|---|
id |
uuid | Y | Primary key |
sessionId |
uuid | Y | → ChatSession |
externalMsgId |
string | N | WhatsApp/Telegram message ID (for idempotency) |
role |
enum | Y | user, assistant, agent, system, internal_note |
content |
text | Y | Message body |
intent |
string | N | AI classification (e.g., "pricing_query") |
createdAt |
date | Y | Immutable timestamp |
2.5 AuditLog
Configuration change tracking.
| Field | Type | Required | Description |
|---|---|---|---|
id |
uuid | Y | |
tenantId |
string | Y | |
actorId |
string | Y | Team member who made the change |
action |
enum | Y | bot_config_updated, channel_connected, session_assigned, etc. |
targetEntity |
string | Y | Entity type |
targetId |
string | Y | Entity ID |
diff |
jsonb | N | Before/after snapshot |
createdAt |
date | Y |
3. Entities NOT in Chat Engine (Delegated)
Handled by Contact Intelligence
- Contact profiles (
ci_contacts) — created/resolved by CI on first message - Contact state (
ci_contact_state) — mood, energy, relationship stage, churn risk - Contact memory (
ci_contact_memory) — facts, preferences, episodes extracted from conversations - Contact entities (
ci_contact_entities) — personal knowledge graph (people, pets, places) - Outreach triggers (
ci_outreach_triggers) — proactive re-engagement messages - Interaction logs (
ci_interaction_logs) — per-message mood/memory tracking
Handled by AI Brain
- Knowledge docs & chunks (
ai_knowledge_docs,ai_knowledge_chunks) — RAG pipeline - AI memory (
ai_memory) — per-tenant business memory - AI conversations (
ai_conversations) — copilot chat (not chatbot sessions) - AI usage (
ai_usage) — token/cost tracking - AI personality (
ai_personality) — business identity, tone
4. Entity Relationships
5. State Machines
5.1 ChatSession Status
[*] → AI_HANDLED (new conversation)
AI_HANDLED → HUMAN_ESCALATED:
- AI outputs [[HANDOFF]]
- User requests "talk to human"
- Contact mood is sustained negative (frustrated/angry)
- Tenant credits exhausted
HUMAN_ESCALATED → AI_HANDLED:
- Agent clicks "Re-assign to AI"
HUMAN_ESCALATED → CLOSED:
- Agent resolves ticket
AI_HANDLED → CLOSED:
- 24h idle timeout
CLOSED → AI_HANDLED:
- Customer sends new message5.2 Contact Intelligence Integration State
New message arrives
│
├─ Contact exists? → GET /context/{id} (mood + memories)
│ └─ mood = frustrated? → lower creativity, empathetic tone
│ └─ mood = excited? → match energy
│ └─ churn_risk > 0.7? → extra care, mention past positive memories
│
└─ Contact new? → POST /contacts (create profile)
└─ CI initializes: mood=neutral, stage=new, streak=06. Key Domain Rules
- Tenant Isolation: Every query MUST filter by
tenantId. No exceptions. - Idempotency:
external_message_id+channelIdunique constraint prevents duplicate webhook processing. - Contact Resolution: Anonymous widget users get a
contactIdon first message. If they later provide email (lead capture), merge with existing contact. - Message Immutability:
ChatMessageis append-only. No edits, no deletes. - Context Assembly: Chat Engine does NOT build LLM prompts. It sends
context_textfrom CI +messageto AI Brain, which handles prompt construction. - Mood Adaptation: Contact Intelligence provides mood + adaptation hints. Chat Engine injects these into the Brain request so the AI adapts tone automatically.