Skip to content
Learn Agentic AI
Learn Agentic AI12 min read3 views

AI Tenant Support Agent: Maintenance Requests, Rent Inquiries, and Lease Questions

Build an AI tenant support agent that handles maintenance ticket creation, rent balance lookups, lease question answering, and smart escalation to property management staff.

The Property Management Communication Problem

Property managers spend 60-70% of their time answering repetitive tenant questions: "When is my rent due?", "What is the status of my maintenance request?", "Can I have a pet?" An AI tenant support agent handles these inquiries instantly while creating proper tickets for issues that need human attention.

This guide walks through building a tenant support agent with maintenance ticket creation, rent inquiry handling, lease lookups, and intelligent escalation.

Tenant Data Models

We start with the data layer that the agent needs to access.

flowchart TD
    START["AI Tenant Support Agent: Maintenance Requests, Re…"] --> A
    A["The Property Management Communication P…"]
    A --> B
    B["Tenant Data Models"]
    B --> C
    C["Building the Maintenance Ticket System"]
    C --> D
    D["Rent and Lease Inquiry Tools"]
    D --> E
    E["Escalation Logic"]
    E --> F
    F["Assembling the Agent"]
    F --> G
    G["FAQ"]
    G --> DONE["Key Takeaways"]
    style START fill:#4f46e5,stroke:#4338ca,color:#fff
    style DONE fill:#059669,stroke:#047857,color:#fff
from dataclasses import dataclass, field
from datetime import datetime, date
from enum import Enum
from typing import Optional

class TicketPriority(Enum):
    LOW = "low"
    MEDIUM = "medium"
    HIGH = "high"
    EMERGENCY = "emergency"

class TicketStatus(Enum):
    OPEN = "open"
    IN_PROGRESS = "in_progress"
    SCHEDULED = "scheduled"
    COMPLETED = "completed"

@dataclass
class MaintenanceTicket:
    ticket_id: str
    tenant_id: str
    unit: str
    category: str  # plumbing, electrical, hvac, appliance, etc.
    description: str
    priority: TicketPriority
    status: TicketStatus
    created_at: datetime
    scheduled_date: Optional[date] = None

@dataclass
class TenantAccount:
    tenant_id: str
    name: str
    unit: str
    lease_start: date
    lease_end: date
    monthly_rent: float
    balance_due: float
    pet_policy: str
    parking_spot: Optional[str] = None

Building the Maintenance Ticket System

The ticket creation tool needs to classify urgency automatically. A burst pipe is an emergency; a squeaky door is low priority.

from agents import function_tool
import uuid

EMERGENCY_KEYWORDS = ["flood", "fire", "gas leak", "no heat", "burst pipe", "sewage", "electrical fire"]
HIGH_PRIORITY_KEYWORDS = ["no hot water", "ac broken", "heater broken", "leak", "mold"]

def classify_priority(description: str) -> TicketPriority:
    desc_lower = description.lower()
    for kw in EMERGENCY_KEYWORDS:
        if kw in desc_lower:
            return TicketPriority.EMERGENCY
    for kw in HIGH_PRIORITY_KEYWORDS:
        if kw in desc_lower:
            return TicketPriority.HIGH
    return TicketPriority.MEDIUM

@function_tool
async def create_maintenance_ticket(
    tenant_id: str,
    category: str,
    description: str,
) -> str:
    """Create a maintenance request ticket for a tenant."""
    priority = classify_priority(description)
    ticket_id = str(uuid.uuid4())[:8]

    # In production, this writes to a database
    ticket = MaintenanceTicket(
        ticket_id=ticket_id,
        tenant_id=tenant_id,
        unit="auto-resolved",  # looked up from tenant_id
        category=category,
        description=description,
        priority=priority,
        status=TicketStatus.OPEN,
        created_at=datetime.now(),
    )

    response = f"Ticket {ticket_id} created (Priority: {priority.value})."
    if priority == TicketPriority.EMERGENCY:
        response += " EMERGENCY: Maintenance team has been paged immediately."
    return response

@function_tool
async def check_ticket_status(ticket_id: str) -> str:
    """Look up the status of an existing maintenance ticket."""
    # In production, this queries the database
    return (
        f"Ticket {ticket_id}: Status is IN_PROGRESS. "
        f"Scheduled for Tuesday between 9 AM and 12 PM. "
        f"Technician: Mike R."
    )

The priority classification is intentionally keyword-based rather than LLM-based. For safety-critical routing like emergency maintenance, deterministic rules are more reliable than probabilistic model outputs.

See AI Voice Agents Handle Real Calls

Book a free demo or calculate how much you can save with AI voice automation.

Rent and Lease Inquiry Tools

@function_tool
async def get_rent_info(tenant_id: str) -> str:
    """Get rent balance, due date, and payment history for a tenant."""
    # In production, this queries the accounting system
    return (
        "Monthly rent: $1,850.00\n"
        "Current balance: $0.00 (paid through March 2026)\n"
        "Next due date: April 1, 2026\n"
        "Payment method: Auto-pay (Chase checking ending 4521)"
    )

@function_tool
async def lookup_lease_terms(tenant_id: str, question: str) -> str:
    """Answer a question about a tenant's lease terms."""
    # In production, this searches a parsed lease document
    lease_data = {
        "pet_policy": "Cats and small dogs (under 35 lbs) allowed with $500 deposit.",
        "guest_policy": "Guests may stay up to 14 consecutive days without notification.",
        "subletting": "Subletting is not permitted without written landlord approval.",
        "early_termination": "60-day notice required. Early termination fee: 2 months rent.",
        "parking": "One assigned spot included. Additional spots $75/month if available.",
    }
    q_lower = question.lower()
    for key, answer in lease_data.items():
        if any(word in q_lower for word in key.split("_")):
            return answer
    return "I could not find that specific clause. Let me connect you with property management."

Escalation Logic

Not every issue should stay with the AI. We build an explicit escalation tool.

@function_tool
async def escalate_to_manager(
    tenant_id: str,
    reason: str,
    urgency: str = "normal",
) -> str:
    """Escalate an issue to the property manager when AI cannot resolve it."""
    return (
        f"Your request has been escalated to the property manager. "
        f"Reason: {reason}. "
        f"Expected response time: {'1 hour' if urgency == 'urgent' else '24 hours'}."
    )

Assembling the Agent

from agents import Agent

tenant_agent = Agent(
    name="TenantSupportAgent",
    instructions="""You are a tenant support assistant for Oakwood Apartments.
    Identify the tenant by their unit number or tenant ID first.
    Handle maintenance requests by creating tickets.
    Answer rent and lease questions from the system.
    Escalate to a manager for: complaints about neighbors, legal disputes,
    lease negotiations, or anything you are unsure about.
    Be empathetic and professional.""",
    tools=[
        create_maintenance_ticket,
        check_ticket_status,
        get_rent_info,
        lookup_lease_terms,
        escalate_to_manager,
    ],
)

FAQ

How does the agent handle emergency maintenance requests after hours?

The priority classifier detects emergency keywords and automatically pages the on-call maintenance team. The agent confirms to the tenant that emergency staff have been notified and provides safety instructions when applicable (e.g., "shut off the water main valve").

Should rent payment processing go through the AI agent?

No. The agent should only provide balance information and payment status. Actual payment processing should happen through a secure payment portal. The agent can share a link to that portal but should never collect payment card details directly.

How do you prevent tenants from accessing other tenants' information?

Authentication happens before the agent conversation begins. The tenant's ID is injected into the session context, and all tool calls are scoped to that ID. The agent never accepts a tenant ID from the conversation — it uses only the authenticated session identity.


#TenantSupport #PropertyManagement #AgenticAI #Python #MaintenanceAutomation #LearnAI #AIEngineering

Share
C

Written by

CallSphere Team

Expert insights on AI voice agents and customer communication automation.

Try CallSphere AI Voice Agents

See how AI voice agents work for your industry. Live demo available -- no signup required.

Related Articles You May Like

Case Studies

AI Voice Agents for Real Estate & Property Management

See how property management companies use AI voice agents to handle tenant inquiries, maintenance requests, and leasing calls around the clock.

AI Interview Prep

7 AI Coding Interview Questions From Anthropic, Meta & OpenAI (2026 Edition)

Real AI coding interview questions from Anthropic, Meta, and OpenAI in 2026. Includes implementing attention from scratch, Anthropic's progressive coding screens, Meta's AI-assisted round, and vector search — with solution approaches.

Learn Agentic AI

Fine-Tuning LLMs for Agentic Tasks: When and How to Customize Foundation Models

When fine-tuning beats prompting for AI agents: dataset creation from agent traces, SFT and DPO training approaches, evaluation methodology, and cost-benefit analysis for agentic fine-tuning.

AI Interview Prep

7 Agentic AI & Multi-Agent System Interview Questions for 2026

Real agentic AI and multi-agent system interview questions from Anthropic, OpenAI, and Microsoft in 2026. Covers agent design patterns, memory systems, safety, orchestration frameworks, tool calling, and evaluation.

Learn Agentic AI

Building a Multi-Agent Data Pipeline: Ingestion, Transformation, and Analysis Agents

Build a three-agent data pipeline with ingestion, transformation, and analysis agents that process data from APIs, CSVs, and databases using Python.

Learn Agentic AI

Adaptive Thinking in Claude 4.6: How AI Agents Decide When and How Much to Reason

Technical exploration of adaptive thinking in Claude 4.6 — how the model dynamically adjusts reasoning depth, its impact on agent architectures, and practical implementation patterns.