OTB tenant communications are a routing problem before they are a writing problem. A polished wrong reply is worse than no reply if a message describes a gas smell, water intrusion, a fair-housing issue, or a payment dispute. Build the triage layer first; only then let a model draft a response.
The agent receives an inbound message, property and unit context, recent maintenance tickets, payment state when authorized, and office-hours policy. It returns a typed disposition: intent, urgency, confidence, required human role, permitted next action, and a draft only when policy allows it. Emergency detection uses rules plus a conservative classifier. Anything with safety, habitability, legal, discrimination, lockout, threat, or low confidence becomes a human task.
This project teaches a crucial builder habit: separate classification, retrieval, action selection, and drafting. Your response writer should never decide whether to waive a fee or dispatch a vendor. Those are policy decisions exposed as constrained actions.
The walkthrough gives a concrete contract, gates, and eval approach. Ship in shadow mode first: compare its dispositions with what staff actually did, then improve the label definitions before sending any automated reply.
Before adding complexity, run this design through a small representative eval and inspect the trace with the operator who will own failures. Make the boundary, escalation, and rollback visible in the product. That discipline will expose more useful work than another round of prompt cleverness.
Accept {message_id, tenant_id, property_id, channel, body, attachments}. Enrich server-side with unit, open work orders, recent conversation, lease status, and policies the tenant may see. Return {intent, urgency, confidence, evidence, route, action_proposal, draft, hitl_reason}. Valid intents include maintenance, emergency, payment, lease question, access, complaint, renewal, document request, and unknown. Do not let the model invent categories.
Classify, then route
Run deterministic emergency terms first: fire, gas, carbon monoxide, flooding, no heat in cold conditions, threat, and lockout. The rule result can only raise urgency. Then use a low-cost structured classifier with examples from actual OTB traffic. Route emergency to the on-call workflow immediately and draft only the approved emergency instruction. Route maintenance to an existing-ticket lookup; create a proposed ticket when none exists. Route payment and lease questions to a human unless an approved answer template applies.
Drafting contract
The drafter sees the classified intent, permitted policy snippets, and relevant records—not raw database access. It must use a short, property-safe tone, identify any requested next step, and avoid promises, diagnoses, legal advice, fees, or vendor commitments. For example, it may say “We’ve shared this with maintenance and will update you,” not “A plumber will arrive at 2 PM” unless a confirmed appointment record exists.
HITL gates
Require approval for emergencies, habitability, fair housing, eviction, payment arrangements, rent changes, threats, refunds, lease interpretation, negative sentiment, attachments, low confidence (<0.85), and any proposed write. Staff approve from a view showing source message, classifications, policy, retrieved facts, and final draft. One click should be able to override both label and response.
Eval and rollout
Build 200 labeled messages, deliberately oversampling emergencies and sensitive cases. Measure intent accuracy, emergency recall, escalation recall, unsafe-draft rate, and staff override rate. Launch in shadow mode, then auto-send only low-risk acknowledgement categories with a verified template. Monitor false negatives weekly; a single missed emergency is a severity-one incident, not a dashboard footnote.