Property Knowledge Base — Redesign Findings
Aug 26, 2026 · Proposed — pending Fede's review Triggered by Hayley's buzz-code question at Camellia. Four research tracks: a code audit, a live-data audit of Camellia, outside research on how others do this, and a four-lens UX review. Answers in section 5 are multiple-choice.
1 · What's true today (verified)
How Clara gets facts
- Each property has one knowledge record: structured fields (fees, hours, utilities, amenities, specials, lease terms, renewal & turnover policy) plus a free-text list of "sections" (pet policy, buzz code, etc.). Camellia has 9 sections today.
- For texts and emails the whole list is pasted into Clara's instructions on every turn (capped at ~4,500 characters — fees, specials and policies share that cap, so a long list can push fees out silently-ish; there's a "truncated" note but no alert). For phone calls it's pasted in when the call starts, with no cap and no filtering.
- The "look up property details" tool that Clara can call mid-conversation was used 3 times in 30 days across 250 Camellia conversations — the facts reach her via the pasted block, not the tool. Any redesign must change the pasted block, or it changes nothing.
- Maintenance, renewal, turnover and collections conversations get the same leasing-oriented block whether they need it or not.
What's missing in the data model
- No audience tag. Nothing says "this is for current residents" vs "for prospects" vs "for vendors." Clara is told who she's talking to, but the only guard is a sentence in the prompt asking her to use judgment.
- No sensitivity flag. The door code 5285 sits in two sections, styled the same as the pet policy, served to anyone who asks.
- No expiry. "1 Month Free" has no end date anywhere. A PM has to remember to delete it.
- Provenance Clara can't use. Source labels exist (lease / manual / PM / scraped) but are free text; the teaching loop's own "learned from staff" label appears on zero Camellia sections — every staff-sourced fact was typed in by hand. Only 1 of 9 sections has a date.
- No org-level layer. Every fact is per-property by design. "Fix once, ship everywhere" doesn't exist for knowledge — except one narrow case (turnover charge categories borrowed from a sibling property), which is a ready template.
- No usage visibility. Nothing records which facts Clara actually used in an answer, so we can't tell dead entries from load-bearing ones.
Bugs and conflicts found (Camellia, live)
| Finding | Why it matters | Fix size |
|---|---|---|
| BUG A section that was retired ("stop saying this") is still read aloud on phone calls. Texts/emails filter it correctly; the call-start path and the mid-call lookup tool don't. | The whole point of retiring a wrong answer is that Clara stops giving it. On voice she doesn't. | Small |
| BUG Two office phone numbers on file: the knowledge record says 303-861-1057, the property record says 720-936-2043. | Which one a prospect is told depends on which code path answers. | Small (needs Joanna/Erika to say which is right) |
| DRIFT The "1 Month Free" rules live in three places (specials list, lease policy, a standalone timing field). They agree today by luck. | Clara already paraphrases it inconsistently — told one prospect "select homes," another "all homes." | Medium |
| DRIFT A stale settings row from April still exists next to the current one, with a different auto-approve threshold ($300 vs $500). | If any code still reads the old row it's using a 4-month-old rule. | Small |
| GAP The "delete" button in the app permanently erases a section and its audit trail. The backend was built to retire-not-delete. | One click destroys the evidence of what Clara used to say and who decided it. | Small |
| GAP Camellia's 7 escalations in the last 60 days are all still open, including Hayley's. Two aren't real questions (a vendor sales call, a "yes thank you"). | The loop that turns answers into knowledge has no screen; and not every escalation is knowledge-shaped. | Medium (UI) |
| GAP The website scraper relabels a PM's hand-entered special as "scraped" on any run that finds nothing — known, unfixed. | Provenance labels can't be trusted until this is fixed. | Small |
| GAP Phone calls (166 of 250 conversations) mostly don't carry the "who is this" stamp that texts do. | Any audience filter is blind on the channel that carries most traffic until caller typing works on voice. | Medium |
| WORKS Jordan Miller asked about co-signers Aug 11 → escalated → Fede answered → Aug 13 Noa Bel Air asked the same thing and Clara answered directly. | The flywheel works when the loop closes. | — |
2 · What the industry does
- Audience tags are a shipped, named feature at the support-AI leaders. Intercom Fin "audiences" and Zendesk "user segments" restrict which articles the AI may use per viewer type; Ada targets knowledge by customer segment. This is the closest precedent to what we need. (No public equivalent from AppFolio Realm-X or Yardi Chat IQ — we'd be ahead of the PMS incumbents.)
- Access codes are never released on a plain ask. Every access-control vendor checked (Rently, ButterflyMX, Latch, Igloohome) verifies identity out-of-band first and issues scoped, time-boxed codes. A chat agent that lacks this gets talked into disclosures (the Chevrolet-dealership "$1 car" incident is the canonical example).
- The fair-housing precedent is real: Harbor Group / PERQ (2023, settled) — a leasing chatbot at 100+ properties gave one flat answer about vouchers to everyone. Whatever gate we build must apply identically to everyone who asks, and be logged, so it survives a tester audit.
- Provenance needs a precedence rule, not a blend. Intercom lets you pin a source to win; Guru marks every card verified/unverified with a 30-day re-verify clock; Vertex ranks by recency. Air Canada was held liable when its bot contradicted its own policy from stale content.
- Expiry is a first-class field everywhere else. Every CMS checked has publish/expire dates; Yardi RentCafe defines specials portfolio-wide with an expiry and per-property override.
- Inheritance is a solved pattern: portfolio → property → unit, "most specific wins," documented tie-break — same as feature flags and CSS.
- Nobody has published how "a staff answer becomes policy" is gated. That's our differentiator and a build-it-ourselves problem.
3 · Proposed design
Add four small things to every fact, then make every reader honor them. Each is one field plus one shared filter reused on text, email, voice and the lookup tool (the fair-housing screen already works this way — copy the pattern).
| Field | Values | What it does |
|---|---|---|
| Audience | everyone · prospects · residents · vendors · owners (multi-select) | Clara only sees facts matching who she's talking to. Unknown/unverified callers get "everyone" only. Default for new facts: everyone (nothing hides by accident). |
| Sensitivity | public · resident-only · restricted | Restricted (door/gate/lockbox codes, wifi, PM cell) is never in the prompt for an unverified counterparty; when it is disclosed, it's logged. Same rule for everyone — the fair-housing defense. |
| Source + verified date | website · onboarding · lease document · staff answer · PMS sync; verifiedAt | Fixed vocabulary (not free text). Precedence when two disagree: lease document > PMS sync > staff answer > onboarding > website. Staleness shown as "verified 14d ago" / "re-check"; website facts re-checked weekly by change-detection. |
| Expires | optional date | Specials, closures, temporary rules drop out of the prompt automatically and gray out in the UI. No more remembering to delete. |
Scope levels, later: org → property → unit, most specific wins. Start with org-level "policy templates" a property inherits and can override — that's the "fix once, ship everywhere" mechanism. Unit-level and person-level facts stay out of scope for now (person-specific answers are deliberately never taught today; keep it that way).
Voice caller typing has to be fixed alongside, or the audience filter is blind on the phone.
4 · UI recommendations (from the four-lens review)
Today: a collapsed accordion on the property overview, under six KPI tiles and above a 120-unit grid; one flat list with tiny source chips of equal weight; the door code styled like the pet policy; Edit/Delete are 10px hover-only text.
| # | Recommendation | Effort |
|---|---|---|
| 1 | Restricted facts get a lock icon and distinct treatment; excluded from unverified callers by default. | M |
| 2 | Audience as a real field with a filter, replacing the plain-prose "Not shown to residents" note on the renewal card. | M |
| 3 | A "Needs your answer" queue at the top of Knowledge: open escalated questions with Answer & Teach / Dismiss. The backend exists; it has no screen. | L |
| 4 | Search + "preview what Clara would say" as prospect / verified resident / unknown caller / vendor. | L |
| 5 | Expiry on specials and entries; auto-gray when past. | S |
| 6 | "Decided by X · date" shown as a metadata row on every staff-confirmed entry (today it's hand-typed into one entry's body and invisible on the rest). | S |
| 7 | Accessible hit targets; Edit/Retire always visible on focus. | S |
| 8 | Split the source chip into Origin (fixed colors) + Freshness ("verified 12d ago" / "stale"). | M |
| 9 | Knowledge gets its own page (/properties/[id]/knowledge) with a one-line summary left on Overview ("42 facts · 2 pending questions · 1 expiring"). | L |
| 10 | One row component for all groups (today: paragraphs, a label/value table, and tag clouds). | M |
| 11 | Replace Delete with Retire (keeps history); lightweight edit history per entry. | M |
| 12 | Bulk onboarding: auto-scrape prompt, multi-file upload, checklist of empty categories. | M |
┌─ Camellia Apartments › Knowledge ─────────────────────── [+ Add] [Upload] ─┐ │ 42 facts · synced 53m ago ⚠ 2 unanswered questions ⏳ 1 special expiring │ │ 🔍 Search / "what would Clara say about…" Audience [All▾] Sensitivity [All▾] │ ├────────────────────────────────────────────────────────────────────────────────┤ │ ⚠ NEEDS YOUR ANSWER (2) │ │ "How do I set up a buzz code?" via text · yesterday [Answer & Teach][Dismiss]│ ├────────────────────────────────────────────────────────────────────────────────┤ │ POLICIES & LEASE TERMS │ │ 🔒 Resident Buzz-In Code RESTRICTED · residents PM · verified today │ │ Pet Policy public · prospects+residents lease · verified 12d│ │ Co-signers & Guarantors ✓ learned · Decided by Fede · Aug 11 [History] │ │ PRICING & SPECIALS │ │ 1 Month Free ⏳ expires Sep 25 prospects [Edit] [Extend] │ ├────────────────────────────────────────────────────────────────────────────────┤ │ Preview — ask as: ○ Prospect ○ Unknown caller ● Verified resident [Run] │ └────────────────────────────────────────────────────────────────────────────────┘
5 · Decisions — pick a number per line
- Audience segmentation. (a) Recommended: audience + sensitivity fields, enforced by one shared filter on every channel; default "everyone." (b) Prompt-wording only ("for current residents: …") and rely on Clara's judgment. (c) Don't store audience-specific facts; keep escalating them.
- Restricted facts (door codes, wifi, PM cell). (a) Recommended: only to a verified resident (matched by phone/email to a lease) — logged; unknown callers get "the team will text you access instructions." (b) Same as (a) but also to prospects with a booked tour on tour day (today's behavior for 5285). (c) Never via Clara; humans only.
- Source precedence when facts disagree. (a) Recommended: lease document > PMS sync > staff answer > onboarding > website; conflicts flagged in the UI, never blended. (b) Newest wins. (c) Staff answer always wins.
- Org-level inheritance. (a) Recommended: later — after 1–3 ship; design it on the existing "borrow from sibling property" pattern. (b) Now, in the same build. (c) Never; keep strict per-property isolation.
- Escalation → knowledge screen. (a) Recommended: build the "Needs your answer" queue in the app; answering there relays to the person AND offers to remember, replacing the email-only loop. (b) Keep email-only; just add the reminder ladder. (c) Both.
- Knowledge page placement. (a) Recommended: its own page with a summary line on Overview. (b) Stay on Overview, moved above the unit grid. (c) Leave as is.
- Camellia phone number. Which is right — (a) 303-861-1057 (knowledge record) or (b) 720-936-2043 (property record)? I'll ask Joanna/Erika if you'd rather not guess.
6 · Do this week (no decision needed, all small)
- Fix the voice call-start and lookup-tool paths so retired sections are filtered like everywhere else.
- Replace Delete with Retire in the app; add a "retired" badge.
- Fix the scraper relabeling hand-entered specials as "scraped."
- Delete the stale April settings row (after confirming nothing reads it).
- Close Hayley's escalation (she was answered in person; the fact is stored).
7 · What's already done
- Stored the buzz-in fact on Camellia (Aug 26, source PM, worded "for current residents") — live in the app and in Clara's context.
- Hayley's "Something broke" mark explained: Clara's first hand-off attempt omitted a required field, was rejected, and retried successfully. Cosmetic; worth making the grader ignore a retried-and-succeeded tool call.
Sources: code audit of the knowledge write/read paths (Aug 26), read-only DynamoDB audit of Camellia (52k rows, 250 conversations, 61 escalation matters), 30+ web sources (Intercom, Zendesk, Ada, Guru, Rently, ButterflyMX, Latch, HUD 2024 AI guidance, WBEZ on Harbor Group/PERQ, Anthropic contextual retrieval), four-lens UX review of the live page.