ADR-010: Tenant Engine Architecture
Status: Accepted Owner: @bilal @deen Date: 2025-01-10
Context
Envo’s core value proposition is 24/7 automated tenant support. The Tenant Engine enables tenants to report issues and receive responses through multiple channels without requiring landlord intervention.
Channels: WhatsApp (primary V1, via Twilio), Voice AI (V1, via VAPI), Email (future), Web Chat (see ADR-016 Tenant Chat App).
Decision
1. Conversation Model
CREATE TABLE conversations (
id UUID PRIMARY KEY,
organisation_id UUID NOT NULL,
tenant_id UUID REFERENCES tenants(id),
property_id UUID REFERENCES properties(id),
channel conversation_channel NOT NULL, -- whatsapp, voice, email, chat, sms
external_id TEXT, -- Twilio SID, VAPI call ID
contact_phone TEXT, contact_email TEXT, -- For unidentified tenants
status conversation_status NOT NULL DEFAULT 'active',
issue_id UUID REFERENCES issues(id),
resolution_type resolution_type,
started_at TIMESTAMPTZ, ended_at TIMESTAMPTZ,
handled_by_ai BOOLEAN DEFAULT true,
escalated_to_human BOOLEAN DEFAULT false,
summary TEXT,
metadata JSONB DEFAULT '{}'
);2. Message Model
CREATE TABLE messages (
id UUID PRIMARY KEY,
conversation_id UUID NOT NULL REFERENCES conversations(id),
direction message_direction NOT NULL, -- inbound, outbound
role message_role NOT NULL, -- tenant, ai, staff
content_type message_content_type NOT NULL,
content TEXT,
media_url TEXT, media_mime_type TEXT,
audio_url TEXT, -- Compliance tier only
transcript TEXT, -- Always stored for voice
external_id TEXT,
sent_at TIMESTAMPTZ, delivered_at TIMESTAMPTZ, read_at TIMESTAMPTZ
);3. Conversation Flow
Tenant sends message/makes call
→ Webhook to Envo Engine
→ Create/update conversation + store message
→ AI processes message → response + intent
→ If issue detected: create issue, link to conversation, notify landlord
→ Store AI response, send to tenant
4. Tenant Identification
- Lookup by phone/email → match to existing tenant
- Lookup by property → check if phone matches property
- Unknown contact → store conversation with contact info, allow manual linking
5. What’s Stored by Default
| Data Type | Default | Optional |
|---|---|---|
| Chat messages | Stored | — |
| Voice transcripts | Stored | — |
| AI summaries | Stored | — |
| Media attachments | Stored | — |
| Call recordings | Not stored | Compliance tier opt-in |
6. AI Summaries
Generated when conversation ends, becomes inactive 24h, or manually closed. Captures: what tenant reported, AI response, outcome, key details.
7. Issue Auto-Creation
AI creates issues when: maintenance problem reported, emergency keywords detected, explicit help request. Includes auto-categorisation, urgency assessment, conversation link.
8. Storage Scaling
~150,000 messages/year at target scale (3,000 properties). PostgreSQL handles this easily. Design supports future partitioning or archive if needed.
Consequences
Positive
- Complete audit trail of all tenant communications
- Enables regulatory compliance
- Rich reporting capability
- Media capture works natively
Negative
- Increased storage costs for media
- More complex data model
- Must handle failed message delivery