Skip to content
Learn Agentic AI
Learn Agentic AI11 min read1 views

Building a Property Inquiry Agent: Answering Buyer Questions About Listings 24/7

Learn how to build an AI agent that answers buyer questions about property listings around the clock, including database lookups, FAQ handling, photo sharing, and automated showing scheduling.

Why Real Estate Needs 24/7 Inquiry Agents

The average buyer browses listings at 9 PM on a Tuesday. By the time an agent responds the next morning, that buyer has already messaged three competitors. A property inquiry agent eliminates this gap by answering questions about listings, sharing photos, and scheduling showings instantly — no matter the hour.

In this guide, we will build a property inquiry agent that connects to a listing database, handles common buyer questions, serves property photos, and books showings automatically.

Designing the Listing Database Layer

Every property inquiry agent starts with structured access to listing data. We will use a simple schema and a retrieval layer that the agent can call as a tool.

flowchart TD
    START["Building a Property Inquiry Agent: Answering Buye…"] --> A
    A["Why Real Estate Needs 24/7 Inquiry Agen…"]
    A --> B
    B["Designing the Listing Database Layer"]
    B --> C
    C["Building the Agent with Tools"]
    C --> D
    D["Handling FAQs with a Knowledge Base"]
    D --> E
    E["Running the Agent"]
    E --> F
    F["FAQ"]
    F --> DONE["Key Takeaways"]
    style START fill:#4f46e5,stroke:#4338ca,color:#fff
    style DONE fill:#059669,stroke:#047857,color:#fff
import asyncpg
from dataclasses import dataclass
from typing import Optional

@dataclass
class PropertyListing:
    listing_id: str
    address: str
    price: float
    bedrooms: int
    bathrooms: float
    sqft: int
    description: str
    photo_urls: list[str]
    status: str  # active, pending, sold
    listing_agent: str

class ListingDatabase:
    def __init__(self, pool: asyncpg.Pool):
        self.pool = pool

    async def search_listings(
        self,
        min_price: Optional[float] = None,
        max_price: Optional[float] = None,
        min_beds: Optional[int] = None,
        city: Optional[str] = None,
        limit: int = 10,
    ) -> list[PropertyListing]:
        conditions = ["status = 'active'"]
        params = []
        idx = 1

        if min_price is not None:
            conditions.append(f"price >= ${idx}")
            params.append(min_price)
            idx += 1
        if max_price is not None:
            conditions.append(f"price <= ${idx}")
            params.append(max_price)
            idx += 1
        if min_beds is not None:
            conditions.append(f"bedrooms >= ${idx}")
            params.append(min_beds)
            idx += 1
        if city is not None:
            conditions.append(f"LOWER(city) = LOWER(${idx})")
            params.append(city)
            idx += 1

        where_clause = " AND ".join(conditions)
        query = f"""
            SELECT * FROM listings
            WHERE {where_clause}
            ORDER BY created_at DESC
            LIMIT {limit}
        """
        rows = await self.pool.fetch(query, *params)
        return [PropertyListing(**dict(r)) for r in rows]

    async def get_listing(self, listing_id: str) -> Optional[PropertyListing]:
        row = await self.pool.fetchrow(
            "SELECT * FROM listings WHERE listing_id = $1",
            listing_id,
        )
        return PropertyListing(**dict(row)) if row else None

This layer gives the agent parameterized search capabilities. The key design choice is returning structured data rather than raw SQL rows so the agent can format responses naturally.

Building the Agent with Tools

Now we wire the database into an agent using tool functions. Each tool handles a specific buyer intent.

See AI Voice Agents Handle Real Calls

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

from agents import Agent, Runner, function_tool

listing_db: ListingDatabase  # initialized at startup

@function_tool
async def search_properties(
    city: str,
    max_price: float = None,
    min_bedrooms: int = None,
) -> str:
    """Search available properties by city, price range, and bedroom count."""
    results = await listing_db.search_listings(
        city=city,
        max_price=max_price,
        min_beds=min_bedrooms,
        limit=5,
    )
    if not results:
        return "No matching properties found. Try broadening your search."
    lines = []
    for p in results:
        lines.append(
            f"- {p.address}: {p.bedrooms}bd/{p.bathrooms}ba, "
            f"{p.sqft} sqft, ${p.price:,.0f} (ID: {p.listing_id})"
        )
    return "\n".join(lines)

@function_tool
async def get_property_details(listing_id: str) -> str:
    """Get full details and photos for a specific listing."""
    p = await listing_db.get_listing(listing_id)
    if not p:
        return "Listing not found."
    photos = "\n".join(p.photo_urls[:5])
    return (
        f"Address: {p.address}\n"
        f"Price: ${p.price:,.0f}\n"
        f"Beds/Baths: {p.bedrooms}/{p.bathrooms}\n"
        f"Sqft: {p.sqft}\n"
        f"Description: {p.description}\n"
        f"Photos:\n{photos}"
    )

@function_tool
async def schedule_showing(
    listing_id: str,
    buyer_name: str,
    buyer_phone: str,
    preferred_date: str,
) -> str:
    """Schedule a property showing for a buyer."""
    # In production, this writes to a calendar/CRM system
    return (
        f"Showing scheduled for {buyer_name} at listing "
        f"{listing_id} on {preferred_date}. "
        f"A confirmation will be sent to {buyer_phone}."
    )

property_agent = Agent(
    name="PropertyInquiryAgent",
    instructions="""You are a helpful real estate assistant. Answer
    questions about available properties using the search and detail
    tools. When a buyer is interested, offer to schedule a showing.
    Always be accurate — never invent property details.""",
    tools=[search_properties, get_property_details, schedule_showing],
)

Handling FAQs with a Knowledge Base

Many buyer questions are not about specific listings but about process — closing costs, inspection timelines, mortgage pre-approval. We handle these with a lightweight FAQ retrieval tool.

FAQ_DATA = {
    "closing_costs": "Typical closing costs range from 2-5% of the purchase price...",
    "inspection": "Home inspections usually occur within 7-10 days of accepted offer...",
    "preapproval": "Mortgage pre-approval typically requires pay stubs, tax returns...",
}

@function_tool
async def lookup_faq(topic: str) -> str:
    """Look up common real estate FAQs by topic keyword."""
    topic_lower = topic.lower()
    for key, answer in FAQ_DATA.items():
        if key in topic_lower or topic_lower in key:
            return answer
    return "I do not have a specific FAQ on that topic. Let me connect you with an agent."

This approach keeps the agent grounded in verified information rather than hallucinating answers about legal or financial topics.

Running the Agent

import asyncio

async def main():
    result = await Runner.run(
        property_agent,
        input="I am looking for a 3-bedroom house in Austin under $500k",
    )
    print(result.final_output)

asyncio.run(main())

The agent will call search_properties with the extracted parameters and present matching listings in a conversational format.

FAQ

How does the agent handle questions about properties not in the database?

The agent is instructed to never fabricate details. If a listing is not found, it responds honestly and suggests broadening the search or contacting a human agent for off-market properties.

Can this agent handle multiple languages for international buyers?

Yes. Since the underlying LLM supports multilingual input and output, you can add an instruction to detect the buyer's language and respond accordingly. The database queries remain the same — only the presentation layer changes.

What happens when the agent cannot answer a question?

The FAQ tool returns a fallback message suggesting human escalation. You can extend this by adding a handoff to a live agent tool that creates a callback request in your CRM.


#RealEstateAI #PropertyInquiry #AgenticAI #Python #Chatbot #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

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.

Learn Agentic AI

How NVIDIA Vera CPU Solves the Agentic AI Bottleneck: Architecture Deep Dive

Technical analysis of NVIDIA's Vera CPU designed for agentic AI workloads — why the CPU is the bottleneck, how Vera's architecture addresses it, and what it means for agent performance.