Raw Renter Messages

design · inbound listing-site email · 2026-10-07 · Proposed, pending Fede

30 days to 2026-10-07, inbound prospect emails

Problem. When a renter replies through a listing site, we store the whole relay email as their message: logo, “New message from a renter”, “Reply on Zillow”, scam footer. The thread shows it and Clara’s model reads it. Keep only what the renter typed.

Stored today ≈ 420 characters

[logo] New message from a renter
Reply on Zillow
Some rental inquiries may be scams…
RENTER’S NAME …

RENTER’S MESSAGE Are you meeting us there

Raw message, 24 characters

Are you meeting us there
CompanyInboundWrappedRenter’s share of text
Camellia4618 (39%)20%
Western Slope7818 (23%)7%
Situsno data (index gap)
Test properties12625 (20%)—

61 of 61 wrapped messages were stored with noise. Camellia: AppFolio “New Lead” emails and website forms. Western Slope: Zillow (3 templates), Zumper, AppFolio relays. No Hotpads, Trulia, Rent. or RentCafe seen.

Cause

First lead emails have parsers. Zillow’s reply template has none, so the fallback stores the full body. Clara still answered correctly.

Recommendation: build

One extractor at ingestion outputs renterText (what the person typed) and keeps the full body as rawBody. One extractor per known relay, including the Zillow reply; unknown ones are cut at the first footer marker and raise an engineering alert. The thread shows renterText (“show original” available); so does Clara’s model. Backfill 90 days. Ships as a fix.

OptionTrade-offEffort
A. Parser per template + generic footer cutter recommendedDeterministic2 PRs
B. LLM extraction per emailToken cost and delay on every message1 PR + eval
C. Hide in the UI onlyModel still reads the noise1 PR
A. What a thread looks like today

A Western Slope renter, one thread (names removed). “+ wrapper” = the relay text below.

TimeRenter wroteStored text
Oct 4 15:47I would like to schedule a tour.clean
Oct 7 00:43Hi yes when would you be available for a tour+ wrapper
Oct 7 00:47Could I do 1+ wrapper
Oct 7 00:49Thanks you!+ wrapper
Oct 7 00:49See you tomorrow+ wrapper
Oct 7 19:11Hi are you steal good for one 1 today+ wrapper
Oct 7 19:12Are you meeting us there+ wrapper
Oct 7 19:13Or is it a self tour+ wrapper

Wrapper, verbatim: “[Brand logo] New message from a renter / Regarding your listing at: <address> / Reply on Zillow / Some rental inquiries may be scams… / RENTER’S NAME <name> / RENTER’S MESSAGE <the words again>”

B. By source
SourceRowsCompanyMedian stored / renter chars
AppFolio New Lead (Zillow inside)11Camellia610 / 99
AppFolio New Lead (Apartments.com inside)3Camellia634 / 71
Zillow “New message from a renter”9Western Slope424 / 24
Zillow “says:”5Western Slope 2, test 33,808 / 116
Zillow Rentals inquiry form3Western Slope467 / 63
Website form4Camellia255 / 58
Zumper1Western Slope134 / 31
AppFolio relay of tenant message or document notice3Western Slope350 / 59
Direct replies187all116 / 116
C. Where the code decides

The stored text is built in the email ingestion step (agents/clara/lib/email/process-email-record.ts, about lines 915–946: zillowRenterMessage || strippedAgentBody || …). The Zillow relay matcher (parse-lead-source.ts L1210) only accepts the exact lines “New message”, “New application request” and “New tour request”. The lead parser looks for a “<Name> says:” line (L1241). Neither matches the reply template. The fallback stripQuotedReply only cuts “On … wrote:” chains.

Message rows have one content field: no html, no sender, no cleaned text. The UI renders content; the model history sends content verbatim.

TemplateExtractor
Zillow “says:”covered
Zillow Rental Manager bannercovered first inquiry only
Zillow “New message from a renter”missing
Apartments.com “says”covered replies unverified
AppFolio lead relaycovered
TenantTurner, Apartments247, contact formcovered first leads only
Zumper, Rent., RentCafe, HotPads, Trulia, Realtornone (HotPads and Trulia recognised for routing only)
D. Design detail
E. Limits of the numbers
F. Sources
PropFlow Docs