<!-- https://vatio.ai/guides/ai-agent-for-real-estate · Updated: 2026-10-11 -->

> Build an AI agent that qualifies buyers and renters, shows matching listings and books viewings on WhatsApp and Instagram, then hands leads to a broker.

# AI agent for real estate agencies

An AI agent for a real estate agency answers the people who write in about a property on WhatsApp, Instagram DMs and your website. It finds out whether they want to buy or rent, their budget, the area and how they will pay, shows the listings that match with a link to each, and books a viewing with a broker. It never negotiates or gives financing advice; that goes to a person. With Vatio you describe that agent in one `vatio.yml` file and it answers from your own WhatsApp number and Instagram account.

This guide builds one end to end: the instructions, the tools that reach your listings and your brokers' calendars, the knowledge it reads, and the rules that keep it from promising what only a broker can.

## What the agent handles

Most of what an agency receives on WhatsApp and Instagram is the same few conversations:

- **"Price?" under a post.** The most common Instagram DM, often with a screenshot. The agent finds the listing and answers with the price, the key facts and the link.
- **Qualifying.** Buy or rent, budget, areas, bedrooms, and for buyers whether they have a pre-approved mortgage or are paying cash. Asked in conversation, one or two at a time, not as a form.
- **Matching listings.** A search of your listings with what the person said, and up to three results, each with its link.
- **Booking viewings.** Free times for that listing, and a booking in your system with the lead's answers attached.
- **Process questions.** What renting requires, what buying costs beyond the price, how long it takes.
- **Everything else goes to a broker.** Offers, negotiation, contracts, financing advice, owners who want to list.

A typical exchange on Instagram, with what the agent did inside:

> **Visitor:** price? *(screenshot of a post)*
>
> **Agent:** That's listing CN-2041, a two-bedroom apartment in Old Town: $1,450 a month, available from November 1. Photos and details: https://casa-norte.example/listings/CN-2041
>
> **Visitor:** can we see it this week? it's me and my partner
>
> **Agent:** Sure. Thursday at 18:00 or Saturday at 11:00 work for the broker. Before I book it: when would you like to move in?

Behind those replies, the agent read the listing code in the screenshot, called `search_listings` with it, then called `viewing_slots`. The link came back from the tool, which is what allows the agent to send it. Every tool call is visible in the inbox, next to the reply it produced.

## Before writing anything: five questions for the agency

1. **Who writes in, and from where?** Instagram posts, listing portals, the website; mostly renters or mostly buyers.
2. **What makes a lead worth a viewing?** The minimum the brokers want to know first: budget, area, move-in date, financing.
3. **What must it never say?** Whether the price is negotiable, whether a bank will lend, anything about a contract.
4. **When does a broker take over?** Offers, contracts, owners who want to list, complaints, anyone who asks.
5. **Where do listings and calendars live?** The API of your CRM or listings database, the brokers' calendars, the address of each listing page.

The answers become the instructions, the `handoff` conditions, the tools and the knowledge, in that order.

## The `vatio.yml`

```yaml
workspace: casa-norte
agent:
  name: Casa Norte Realty
  personality: Friendly and efficient. One or two questions at a time, never pushy.
  instructions: |
    You help people buy or rent a property through Casa Norte Realty: you
    find out what they need, show matching listings and book viewings with
    a broker.

    Answer what they asked first, then qualify. Find out whether they want
    to buy or rent, their maximum budget, the areas they would consider and
    the bedrooms they need. Ask buyers whether they will use a mortgage and
    whether it is pre-approved; ask renters their move-in date. Ask one or
    two things at a time, and save what they tell you with remember.

    Listings: call search_listings with what you know and offer at most
    three results, each with its price, area, bedrooms and the link it
    returned. If the visitor sends a screenshot, look for the listing code
    in it and search by that code.

    Viewings: call viewing_slots and offer the times it returns. Before
    calling book_viewing, ask for a name and, except on WhatsApp, a phone
    number, and read the viewing back. Only say a viewing is booked when
    book_viewing returned it.

    Rules you never break:
    - Never negotiate, accept an offer or suggest the price can come down.
    - Never say whether a bank will approve a mortgage, quote interest
      rates, or give legal or tax advice.
    - Never share an owner's contact details, or an exact address that
      search_listings did not return.
    - Never describe an area by who lives there. Describe the property,
      transport and services.
  tools: [search_listings, viewing_slots, book_viewing, knowledge_lookup, identify_contact, remember]
  knowledge: [agency]
  links:
    area:
      url: https://casa-norte.example/{operation}/{area}
      when: The visitor wants to browse everything in an area.
      values:
        operation: [buy, rent]
        area: [old-town, riverside, northgate, westfield]
    sell:
      url: https://casa-norte.example/sell
      when: An owner wants to sell or rent out their property.
  handoff:
    after_turns: 20
    when:
      - the visitor wants to make an offer or negotiate the price
      - questions about a contract, a deposit or a legal matter
      - the visitor asks for advice on a mortgage or other financing
      - an owner wants to sell or rent out their property
      - a complaint about a broker or a viewing
```

A few choices worth explaining:

- **Answer first, qualify second.** Someone who asked "price?" and got four questions back stops answering. The instructions make the agent give the price and the link, then ask, one or two things at a time.
- **`remember` saves what the lead said.** Budget, areas and financing become notes on the contact, and those notes are in the agent's prompt whenever that contact writes again, so a buyer who comes back next week is not asked their budget twice. The agent never decides on its own to follow up; when your CRM sends one through the Messages API, those same notes are there.
- **Listing links come from the tool, area pages from `links`.** Listings change every day, so their pages come back from `search_listings`, and a URL a tool returned in the conversation is one the agent may send. The area pages are fixed, so `links` declares them and the placeholders expand into eight URLs at deploy time. Any other URL in a reply is stripped.
- **A handoff waits in the inbox.** The agency sets its business hours on the inbox's Business page, not in `vatio.yml`: here weekdays 9:00–19:00 and Saturday 10:00–16:00, Chicago time. Inside them the agent goes quiet so a broker can pick up; outside them it keeps helping and says a broker will reply. Vatio does not notify anyone of a handoff yet, so someone has to keep the inbox open during office hours. `after_turns: 20` is higher than a booking agent needs, because qualifying takes a few turns.

## Tools: listings and viewings

A tool is one HTTP request to your backend, described in YAML. Keep the address and the key in secrets:

```bash
vatio secrets set CRM_API https://api.casa-norte.example
vatio secrets set CRM_API_KEY sk_live_...
```

`tools/search_listings.yml`:

```yaml
description: Search active listings for sale or rent.
when_to_use: The visitor wants to see properties, or asks about a listing by its code or a screenshot.
parameters:
  type: object
  properties:
    operation: { type: string, enum: [buy, rent] }
    areas: { type: string, description: "comma-separated, e.g. old-town,riverside" }
    max_price: { type: number, description: "total price to buy, monthly rent to rent" }
    bedrooms: { type: integer, description: "minimum number of bedrooms" }
    code: { type: string, description: "listing code, e.g. CN-2041" }
access: public
request:
  method: GET
  base_url: "$env.CRM_API"
  path: /listings/search
  headers:
    Authorization: "Bearer $env.CRM_API_KEY"
  query:
    operation: "$params.operation"
    areas: "$params.areas"
    max_price: "$params.max_price"
    bedrooms: "$params.bedrooms"
    code: "$params.code"
respond:
  data:
    listings: "$.listings"
  message:
    when_empty: No active listings match those conditions.
    default: "Found {{count}} matching listings."
```

Your endpoint returns a handful of listings, each with its code, price, area, bedrooms and `url`, the listing page on your site. Parameters the agent did not fill are left out of the request.

`tools/book_viewing.yml`:

```yaml
description: Book a viewing of a listing with the broker in charge of it.
when_to_use: The visitor chose a time from viewing_slots and gave a name.
parameters:
  type: object
  properties:
    slot_id: { type: string }
    name: { type: string }
    phone: { type: string, description: "Instagram and web only. On WhatsApp the tool uses the contact's number" }
    operation: { type: string, enum: [buy, rent] }
    budget: { type: number }
    financing: { type: string, description: "e.g. pre-approved mortgage, mortgage not approved yet, cash" }
  required: [slot_id, name]
access: public
request:
  method: POST
  base_url: "$env.CRM_API"
  path: /viewings
  requires: [params.slot_id, params.name]
  headers:
    Authorization: "Bearer $env.CRM_API_KEY"
  body:
    slot_id: "$params.slot_id"
    name: "$params.name"
    phone: "$params.phone || $contact.phone_number"
    operation: "$params.operation"
    budget: "$params.budget"
    financing: "$params.financing"
respond:
  data:
    viewing: "$.viewing"
```

The qualification travels with the booking, so the broker opens the viewing in your CRM already knowing the budget and how the lead will pay. On WhatsApp the lead's number comes with their message, so `phone` falls back to `$contact.phone_number` and the agent asks for it only on Instagram and the website. `viewing_slots` is a `GET` with the listing code that returns the next free times of the broker in charge; which calendar it reads is up to your backend. If a slot was taken in the meantime, answer `409`: Vatio turns any non-2xx response into an error the agent can explain, so it offers another time instead of confirming one that is gone.

### What a public tool may return

A WhatsApp or Instagram contact is anonymous until they sign in, so only public tools run for them, and all three of these are public. That is fine for listings, which are public anyway, but it sets the rule for what your endpoints return: what is on the listing page, and nothing else. No owner details, no exact unit for a listing you only publish by area, no lowest price the owner would accept. Whatever a tool returns, the model can repeat. `book_viewing` writes into your CRM for anonymous visitors, so treat it like a contact form: validate the phone number and cap bookings per number. Anything that belongs to one client, such as a tenant's lease or payments, needs a signed-in visitor and a tool marked `access: private`, which on WhatsApp and Instagram [sends them to sign in](https://vatio.ai/docs/authentication/sessions#on-whatsapp) first; see [Connect your backend](/guides/connect-your-backend).

## Knowledge: the process, in your words

```bash
vatio kb create agency
vatio kb write agency renting renting.md
vatio kb write agency buying buying.md
vatio kb write agency areas areas.md
vatio kb write agency fees fees.md
```

A good entry answers a question per section:

```markdown
# Renting with Casa Norte

## What you need to apply
A photo ID, proof of income of at least three times the monthly rent, and
one reference from a previous landlord.

## What you pay before moving in
The first month's rent and a security deposit of one month. The application
fee is $50 and is not refundable.

## How long it takes
We answer within two business days of receiving every document.
```

Vatio does not read your website. If the answer lives on a page, put what the agent needs in an entry. When fees change, a supervisor edits the entry from the inbox, and every edit is kept as a version.

## Instagram: "price?" and a screenshot

Real estate lives on Instagram. A reel of an apartment brings DMs that say "price?", "info" or "still available?", often with a screenshot, because the visitor wrote from the feed rather than from the post. Two things make those conversations work:

- **Put the listing code on every post**, in the image and the caption. The agent reads images, so a screenshot with "CN-2041" in a corner becomes a `search_listings` call by code instead of a guess about which two-bedroom it was.
- **Answer before you ask.** "Price?" deserves a price. The qualifying happens over the next few messages.

The agent cannot send photos; the listing page carries them, and the link is what it sends. Voice notes are transcribed, and Vatio groups a burst of messages into one turn before answering. On Instagram a business cannot write first, so if a lead goes quiet there, the follow-up goes through another channel; on WhatsApp your CRM can send it through the [Messages API](https://vatio.ai/docs/api/messages). When they write again, the agent picks up with the notes it saved. The [Instagram docs](https://vatio.ai/docs/channels/instagram) cover connecting your professional account.

## Try it before any lead does

```bash
vatio push
vatio chat "Hi, I'm looking to rent a 2 bedroom in Old Town, up to 1,500"
vatio chat "Can we see the first one on Saturday?"
vatio chat --new "If I sign this week, can you take 10% off the price?"
vatio chat --new "I earn 4,000 a month. Will the bank give me a mortgage for CN-3108?"
vatio chat --new "What's the owner's phone number for CN-2041?"
vatio chat show
```

The three `--new` chats are the important ones: a negotiation it must hand to a broker, a financing question it must not answer, and an owner's details it must not give out. `chat show` prints every tool call. `book_viewing` writes for real, so point preview at a sandbox CRM with a test value for its secret (`--tests`). Then add your Instagram account as a test account on the inbox's **Test** page and send the shared preview account a screenshot of one of your posts.

## Make it better every week

Once brokers answer in the inbox, they **flag** any reply that was wrong and write what should have happened: a lead it qualified badly, a listing it should have offered. `vatio flags` turns those notes into a document your coding agent can fix from, each flag becomes an eval case, and the flag is marked fixed when live passes it. See [Improve your agent](/guides/improve-your-ai-agent).

## Go live

```bash
vatio publish
```

Then connect the agency's WhatsApp Business number and Instagram professional account on the inbox's **Channels** page, then switch WhatsApp's **Live** on. Instagram answers as soon as the account is connected. Brokers can keep using the WhatsApp Business app on the agency's phone: a reply sent from it takes the conversation over, and the agent steps back until it is released in the inbox. For your website, `vatio tokens create --env live --origin https://casa-norte.example` creates the token for the widget's script tag.

Leads' names, phone numbers and finances are personal data. Vatio shows conversations only behind a sign-in or a Vatio token; your CRM should be as careful. What your local rules require of property advertising and of handling leads' data is still yours to check.

## Frequently asked questions

### Can an AI agent qualify real estate leads on WhatsApp and Instagram?

Yes. The agent asks whether the person wants to buy or rent, their budget, the area and how they will pay, then searches your listings through a tool that calls your API. When it books a viewing, those answers go to your CRM with it, so the broker starts with a qualified lead.

### Can the agent send photos of a property?

No. Replies are text only, so the agent sends the link to the listing page, where the photos are. It does read the photos and screenshots visitors send, which is how it finds the listing someone is asking about from a screenshot of a post.

### Will the agent negotiate the price or give mortgage advice?

Not if you write the rule, and you should. List negotiation, offers, financing advice and contracts as things it never does, and put them under handoff.when so a broker takes the conversation.

### Does the agent follow up with leads who stopped answering?

On WhatsApp, when your CRM asks it to. Your CRM or backend calls Vatio's Messages API for that lead, with an approved template once 24 hours have passed, and the agent continues with the notes it saved about their budget and areas. The agent never decides on its own to follow up, and on Instagram a business cannot write first.

### How does a broker know a lead needs them?

A handoff marks the conversation as waiting in the Vatio inbox. Vatio does not notify anyone yet, so someone has to watch the inbox during office hours. A viewing booked through your API lands wherever your backend puts it, such as your CRM.
