If you searched for how to set up OpenClaw for real estate agents and brokers, you probably want a working playbook, not another fluffy product pitch. I just wired OpenClaw 0.38.4 into a five-person brokerage last month. Below is everything that worked (and what blew up) so you can copy the repo, avoid the face-plants, and get listings flowing into your client chats by lunch.
Why real-estate teams are wiring OpenClaw into their stack
Most brokerages already juggle half a dozen point tools—MLS web portals, Redfin, Realtor.com, Gmail, Calendly, Mailchimp, maybe Slack or WhatsApp. Nothing talks to each other. OpenClaw glues them together with:
- 800+ integrations via Composio (Gmail, Google Calendar, Notion, HubSpot, etc.)
- First-class chat connectors—WhatsApp, Telegram, Slack, iMessage—so buyers get updates where they actually read them
- Browser automation for sites with no API (e.g., MLS systems that still think it’s 2005)
- Scheduled tasks and persistent memory—perfect for drip campaigns and CMA snapshots
Drawbacks? You need Node 22+ on a machine that can keep Chromium running headless. And if your MLS terms of service prohibit scraping, get explicit permission first. I’m not your lawyer.
Prerequisites: Node 22+, secure MLS credentials, ClawCloud or local box
Versions and tooling
- Node.js 22.3 or newer (LTS works, just stay on 22+).
- npm 10+ (ships with Node 22).
- OpenClaw 0.38.4 (current at 2024-06-14).
- Chrome/Chromium 124+ (bundled by Puppeteer if you let it).
- Git for pulling templates.
Accounts and keys
- MLS / IDX credentials with two-factor app passwords—store them in
process.envor your CI secret manager, not in the repo. - A Twilio WhatsApp sandbox or a Slack bot token for messaging.
- A ClawCloud account if you want zero-ops hosting. Free tier handles a small brokerage fine.
Installing and bootstrapping OpenClaw for real estate agents
1. Spin up the agent locally first
You’ll burn time if you deploy before you know the workflows work.
# macOS/Linux
brew install node@22 # or use asdf/volta
npm create openclaw@latest real-estate-bot
cd real-estate-bot
npm install
The scaffold gives you gateway (web UI) and daemon (background jobs). Start both:
# two terminals or tmux panes
npm run gateway
npm run daemon
Hit http://localhost:14500. Name your agent “RE-Bot” or whatever. The gateway writes config to claw.config.json.
2. Wire messaging channels
For WhatsApp:
# .env
WHATSAPP_ACCOUNT_SID=ACxxx
WHATSAPP_AUTH_TOKEN=yyy
WHATSAPP_FROM="whatsapp:+14155238886"
WHATSAPP_TO="whatsapp:+15551234567"
Slack is similar—just export SLACK_BOT_TOKEN and SLACK_SIGNING_SECRET.
3. Commit, then push to ClawCloud
git remote add claw https://git.clawcloud.com/your-team/real-estate-bot.git
git push claw main
In the ClawCloud dashboard: New Agent → Import Git Repo → Environment = Node 22 → Deploy. First build takes ~90 seconds; after that, webhooks auto-redeploy.
Automating listing monitoring across MLS and property portals
This is where OpenClaw’s browser engine—Puppeteer 20 under the hood—pays off. Most MLS systems (Bright, CRMLS, Matrix) have zero public API. We mimic a real user session, cache cookies in persistent storage, and poll on a cron.
Headless login flow
// src/tasks/mls-login.ts
import { browser } from "openclaw/browser";
export async function mlsLogin(page) {
await page.goto("https://bright.mlsmatrix.com", { waitUntil: "domcontentloaded" });
await page.type("#UserID", process.env.MLS_USER);
await page.type("#Password", process.env.MLS_PASS);
await page.click("button[type=submit]");
await page.waitForNavigation();
// multi-factor prompt? brighten this accordingly
return page.cookies();
}
Cron job to fetch new listings
// src/crons/fetch-new-listings.ts
import { schedule } from "openclaw/cron";
import { sendMessage } from "openclaw/messages";
import { mlsLogin } from "../tasks/mls-login";
schedule("*/15 * * * *", async () => {
const page = await browser.newPage();
await page.setCookie(...await mlsLogin(page));
await page.goto("https://bright.mlsmatrix.com/Matrix/Search/Residential");
// Assume saved search ID 123456 emits JSON
const data = await page.evaluate(() => fetch("/Matrix/Export/ExportResults.aspx?SavedSearchID=123456&Format=JSON").then(r => r.json()));
const newOnes = filterSinceLastRun(data);
for (const listing of newOnes) {
await sendMessage("whatsapp", formatListing(listing));
}
await page.close();
});
Persist lastRunTimestamp in OpenClaw’s built-in KV store (openclaw/store) so restarts don’t flood clients.
Scraping Realtor.com as a backup
Realtor’s HTML is heavy but predictable. document.querySelectorAll("li.component_property-card") gets you the goods. Same cron pattern applies. I keep it at hourly cadence to avoid getting my IP throttled.
Streamlining client communication from WhatsApp to email
Unified message router
Create one handler so a client can ask, “Can we see 123 Maple tomorrow?” on any channel and get the same response.
// src/routes/messages.ts
import { router } from "openclaw/router";
import { scheduleShowing } from "../tasks/showings";
router.on("message", async (ctx) => {
const { text, from } = ctx;
if (/^see\s+\d+\s+.+/i.test(text)) {
const date = parseDate(text); // use chrono-node
await scheduleShowing(from, date, text);
return ctx.reply(`Got it. Tentatively penciled for ${date}. I’ll confirm with the seller.`);
}
});
The router fires for Slack, WhatsApp, Telegram, Signal—wherever you enabled connectors. No more copy-pasting between apps at 10 PM.
Managing showing schedules and calendar sync
Brokerages live in calendars. Double-booking a showing is death to credibility. OpenClaw plus Composio gives first-class calendar integration in eight lines.
// src/tasks/showings.ts
import { googleCalendar } from "composio/google";
export async function scheduleShowing(client, when, note) {
const event = await googleCalendar.events.insert({
summary: `Showing: ${note}`,
start: { dateTime: when.toISOString() },
end: { dateTime: new Date(when.getTime() + 30*60*1000).toISOString() },
attendees: [{ email: `${client}@example.com` }]
});
return event.htmlLink;
}
Set a cron to reconcile MLS showing approvals and update events with lockbox codes once confirmed.
Market analysis and CMA preparation with OpenClaw toolchain
Data ingestion
Pull historical sold data via the MLS’s export (CSV) and ingest to a local DuckDB. Why DuckDB? It’s embedded, ACID, and OpenClaw’s TypeScript client is trivial.
// src/db/duck.ts
import Duck from "duckdb";
export const db = new Duck.Database("cma.db");
Generating the report
// src/tasks/generate-cma.ts
import { db } from "../db/duck";
import { writeFileSync } from "fs";
import { execSync } from "child_process";
export async function generateCMA(address) {
const comps = db.prepare("SELECT * FROM sales WHERE geo_distance(addr, ?) < 0.5 AND sold_date > date('now', '-6 months')").all(address);
const markdown = `# CMA for ${address}\n\n| Address | Beds | Baths | SqFt | Price | DOM |\n|---|---|---|---|---|---|\n` + comps.map(row => `|${row.address}|${row.beds}|${row.baths}|${row.sqft}|$${row.price}|${row.days_on_market}|`).join("\n");
writeFileSync("/tmp/cma.md", markdown);
execSync("pandoc /tmp/cma.md -o /tmp/cma.pdf");
return "/tmp/cma.pdf";
}
Auto-emailing the PDF
import { sendEmail } from "openclaw/email";
await sendEmail({
to: clientEmail,
subject: `Your CMA for ${address}`,
attachments: [{ path: await generateCMA(address) }]
});
This shaves ~45 minutes off every listing appointment prep.
Lead nurturing workflows: drip campaigns and reminders
New leads drop in from Zillow Premier Agent API? Pipe them straight into OpenClaw and let the agent decide if it’s a hot buyer.
Webhook intake
// src/routes/zillow.ts
router.post("/zillow/lead", async (ctx) => {
const lead = ctx.request.body;
await store.set(`lead:${lead.id}`, lead);
await sendMessage("whatsapp", `New Zillow lead: ${lead.name} asking about ${lead.property_address}`);
});
24-hour follow-up sequence
// src/crons/leads.ts
schedule("0 * * * *", async () => { // hourly sweep
const stale = await store.keys("lead:*", (k, v) => hoursSince(v.created_at) > 24 && !v.touched);
for (const lead of stale) {
await sendEmail({
to: lead.email,
subject: "Still interested in seeing homes?",
html: renderTemplate("follow-up", lead)
});
lead.touched = true;
await store.set(`lead:${lead.id}`, lead);
}
});
If WhatsApp is more your style, swap sendEmail for sendMessage("whatsapp", ...). Either way, the team never misses the critical day-one touch.
Hard lessons, trade-offs, and next steps
- MLS portals sometimes break XPaths when they push an update. Keep selectors in one file and add Sentry to alert when a scrape fails.
- Chromium in headless mode still needs ~150 MB RAM per page. On ClawCloud’s free instance you get 512 MB; run one scrape at a time or pay for the 2 GB tier.
- Composio’s Google Calendar connector throttles at 10 requests/second. Batch inserts to stay under quota when importing historical showings.
- For brokerages with strict compliance, disable shell access in
claw.config.json({"allowShell": false}) so agents can’trm -rf /by accident. - Always test automations with your own phone number/email first. Accidentally blasting 64 buyers at midnight is a quick path to angry sellers.
The playbook above covers 90 % of what a typical small-to-mid brokerage needs: real-time listing alerts, unified chat replies, calendar-solid showings, one-click CMA PDFs, and a drip that never sleeps. Fork the repo, swap in your MLS credentials, and push to ClawCloud. Your clients will think you hired an assistant—nobody has to know it’s 400 lines of TypeScript.