Version 2. The PMS stays the system of record. Clara becomes the system of work by plugging into everything the office already uses, reading it all into one picture, deciding once, and answering through whatever door the person used. We meet them where they are.
Proposed — pending Fede's review v2, 2026-10-12 evening · supersedes v1 (Oct 8 to 10, seven drafts; its evidence is kept in a fold at the end) · first initiative: PMS conversations in Clara · execution on the tracker · internal
Contents: why v2 · meet them where they are · the master architecture · the layers · the ladder to full context · competitors · initiatives · decisions · what changed from v1 · evidence from v1 · sources · for agents
Version 1 said: read one picture, decide once, leave through one door, learn from every case. That still holds. What it missed is where the picture comes from. A property-management company already runs on its PMS inbox, its phone line, its mailboxes, its spreadsheets and its meetings. Clara was built as a new place with a new number, and the relationships she needs to know about never moved there.
Version 2 adds the layers below the loop and the layers around it: an integration layer that plugs into any system the office uses, one front door that turns anything that happens anywhere into one event, a company brain that holds what the team knows and decides, and Clara as a coworker that staff can ask, command and teach. The last step is Clara in the meetings.
| What we learned since Oct 8 | What it changes |
|---|---|
| Fede's own calls on the Western Slope line (Oct 11 and 12) found Clara blind to a tour note, a staff note and a staff text that all sat in AppFolio; the phone line was "extremely buggy" for the same reason: no context, not bad reasoning. | Context is the product. The picture must be assembled from the customer's systems, not from what reaches Clara's own number. |
| Tenants and prospects already text the office's AppFolio line. Clara sees none of it, so she double-texts, contradicts staff and chases people who were already answered. | The first initiative is to mirror the PMS inbox: read it, copy it, keep it current, backfill a year or two. Clara reads, never replies, until proven. |
| "Go to PropFlow, use our number" was designed for relationships that start with Clara. Most relationships started years ago, in the customer's lines and inboxes. | Plug in, don't migrate. Clara's number is one more door, never the only one, and nobody is told about a new number. |
| Version 1 mixed the vision with hygiene: a switch audit, notification doors, phone-line build notes, follow-up evidence. | Those are separate, smaller initiatives with their own pages. The vision page keeps the framework, the diagram and the decisions. |
| Our resident-services phone agent exists and is off: it answered without knowing the resident, the work order or what the office had said. | It comes back when the ladder below reaches the level where it knows those things, not before. |
Fede, Oct 12: "These are small businesses, so there's not gonna be a standard playbook. Some are gonna use the PMS communication a lot, some might use email, some might use other software. Anywhere where there's context, anywhere where there's data, there's communication, our platform needs to be hooked in. Then Clara becomes actually like an employee, and even better, because it works all the time. We designed the platform to be 'go to PropFlow, use our number', and we're seeing that might not be the best strategy. Maybe we shouldn't migrate. Maybe we should just plug in and work with what they have. Migrations suck."
Forward your line to Clara's number. Prospects get her number. Staff open PropFlow to see what she did. Everything that happened before day one, and everything that still happens in AppFolio, is invisible to her.
Clara connects to the PMS, the texting line, the mailboxes, the listing relays, the apps and the meetings the office already uses. She reads years of history on day one, works inside their doors, and the office keeps working where it always has. Forwarding is a choice they make later, if ever.
| Principle | What it means in practice |
|---|---|
| Their doors stay theirs | The office line, the PMS texting line and the mailboxes keep their numbers and addresses. Clara's line is one more door. A reply leaves through the door the message came in on. |
| Hooked into everything | Anywhere there is context, data or communication (PMS records and conversations, mailboxes, listing relays, Drive and Docs, Monday and Slack, meetings) Clara is connected, because every source makes her smarter and feeds the corpus we learn from. |
| Plug in, don't migrate | Onboarding is connect, backfill, read, then act. No data moves; the PMS stays the system of record. The customer's existing threads are the starting point, not an import problem. |
| Flexible protocol, fixed core | REST where there is an API, MCP or a CLI for modern apps, a browser agent that behaves like an API for software not in the AI age yet. The core never knows which. |
| No standard playbook | Which channels a customer uses, how their team is shaped and what their policies are is data per customer, never a branch in the code. One mode for every customer. |
The first twelve-month census at Western Slope (Oct 12, counts only) shows what the office's doors actually carry: on the AppFolio texting line, prospects alone sent 4,015 texts in a year and the office sent 5,808 back, 65% from named staff, 21% from a shared login, 14% from AppFolio's automation, none from Clara; the shared leasing mailbox took 13,765 emails of which 16% were prospect inquiries; maintenance arrived by email four times in four months against 547 work orders. Clara's own line has existed since Sep 18. The office's volume is on their doors, not ours.
What customers actually said. From the raw per-speaker transcripts of 22 customer conversations (Sep to Oct 2026), not the recaps; every quote cut by script and checked against the speaker; what is our reading is marked.
Read together: every customer wants Clara plugged into what they already publish and use (the main line forwarded to her, every record written back into AppFolio or Yardi); nobody asked to migrate anything; nobody objected to Clara having a number of her own as long as the numbers they already publish keep working (that last reading is ours, no customer said it in those words). Eileen's line is the case for the company brain: a teaching that lives in a person's habits fades in weeks. ConAm's line is the case for consent per door: a customer can refuse one door and still get the rest. Nobody said "we don't want a new number"; what they said is "keep ours working." Source: scratchpad pms/customer-voices.md, internal; four quotes that carry office-line details stay off this page.
One picture of the whole platform. Read it left to right: people reach the office through the doors they already use; thin adapters read and write those systems; everything becomes one event at one front door; the situation and the company brain give the decision its context; one decision, one gate; the reply leaves through the same door. Three loops run the core: a message arrives, a wake fires, the office teaches.
| Layer | Its one job | Today | Owning initiative |
|---|---|---|---|
| Where the work already happens | Name every door and system the office uses; none is replaced | Clara's line, the leasing mailbox and PMS records are connected; the PMS inbox, other mailboxes, apps and meetings are not | PMS conversations (inbox); company brain (meetings, notes) |
| Integration layer | One core (sessions, pacing, budgets, read and write primitives), one thin adapter per system | The AppFolio robot has the core pieces (vendor seam, warm sessions, pacer, login budget) and one driver; email and Twilio adapters exist; no watch primitive | PMS conversations (adapter contract, Yardi next) |
| One front door | Any wake becomes one event with the door it came in on; identity once; one queue per person | Texts are carrier-neutral after the webhook; email converges on one record; voice is its own path; the guest-card feed re-enters the text path with Clara's line as the door (the new-number leak) | PMS conversations (phase 1); front-door consolidation rows on the tracker |
| The situation | One picture per person and matter, every fact tagged by audience | Reader built dark (decision 1, settled Oct 8); callers being moved onto it | Tracker area 1 |
| The company brain | Private, audience-tagged knowledge: policy, teachings, meeting decisions, notes | Knowledge and policies settings, a public knowledge base, a private-info gate; the brain design exists, nothing scheduled | Company brain page |
| One decision | Engage or not; act, ask, record or wait; levels of autonomy per lane | Clara always replies on her own doors; follow-up and escalation gates exist; levels exist for renewals | PMS conversations (phase 2); renewals levels page |
| One egress | Back through the door it came in; PMS writes; asks to staff by role | Gera's send gate is the door for texts; replies are sticky to the inbound line; no PMS send for tenants; staff asks being consolidated into one sender | Tracker areas 2 and 3; PMS conversations (phase 3) |
| Clara as a coworker | Staff ask, command, teach and hand off on any channel | The Coworker Line (phone) and the dashboard chat answer questions; commands by text exist for a few actions; teaching writes straight into the knowledge base with no reasoning layer (Jay's cell, Oct 7) | Coworker Line hub; company brain page |
| Leadership and owners | Inspection, intelligence, reports from the same picture | Dashboards and savings numbers exist; several would be inflated by mirrored rows until fixed | Later; the census is the first report |
| Learn and prove | Corpus, evals, supervised before live | Harnesses for follow-ups, asks, drafting; the anonymized Western Slope corpus; the testing playbook ladder | Every initiative climbs the ladder |
No system should make us reinvent login, how to pull, how often, or the safety caps. The core owns sessions, pacing, budgets and the read and write primitives; an adapter owns one system's quirks and nothing else. The browser agent is not a special case: it is an adapter whose transport happens to be a logged-in session, exposed to the core as an API.
| The system looks like | Protocol | Examples | What the core sees |
|---|---|---|---|
| Has a real API | REST (or webhooks when they push) | Twilio, Outlook and Gmail, ElevenLabs, Yardi's paid interfaces later | the same primitives |
| Modern app with an agent surface | MCP or a CLI | Google Drive and Docs, Monday, Slack, Salesforce-style tools | the same primitives |
| Legacy software, not in the AI age yet | Browser agent as an API: one warm session per account, one pacer, one login budget, reads as plain requests on that session, a browser only to log in | AppFolio today (the robot), Yardi Voyager for ConAm next, Entrata later | the same primitives |
| Primitive | Read or write | What it does | Exists today |
|---|---|---|---|
| watch a list | read | one cheap request returns rows with a stable key and a last-changed marker; compare to last time; fetch details only for what changed | no; the AppFolio inbox list was captured on Oct 12 and the robot already wraps it |
| fetch a record | read | one record by its PMS id: card, application, work order, tenant, lease | yes (83 robot routes; the sync jobs) |
| mirror a thread | read | copy a conversation held elsewhere into the matching PropFlow conversation, labeled with who and when | guest-card threads only, per property, per minute, Willows only |
| receive a webhook | read | when the system pushes, the adapter turns the push into the same event | Twilio, Outlook, SES |
| send on their channel | write | a reply leaves through the system the message came from | Twilio and mailboxes yes; AppFolio for prospects only, text only |
| update a record, create an item | write | a note, a status, a work order, a guest card, a task in their app | AppFolio work orders and guest cards; Yardi mock only |
The adapter contract, in full, is on the PMS conversations page (section 2), with the build check that the core never imports a vendor.
Version 1 named four wakes: inbound on any channel, a staff command or answer, a PMS change, a timer. Those hold. Two are added: a meeting happened, and a document or app item changed. Whatever the source, the adapter emits the same event: what happened, to whom, through which door, when, and the raw payload. Identity runs once. The door is recorded on every message so the reply can leave by it.
| Source | How it enters today | Gap |
|---|---|---|
| Text on Clara's line | Twilio webhook builds an envelope; everything after it is carrier-neutral; replies are sticky to the inbound line | none for the door; STOP keywords are checked only here |
| three ingest paths converge on one inbound record and one processor | none for the door | |
| Voice | its own route (about 4,000 lines) that wakes no engine; the transcript and notes land afterwards | tight; the call is not an event the loop sees until it ends |
| PMS conversation (AppFolio inbox) | the guest-card feed re-enters the text path with Clara's own line as the door, so Clara would answer an AppFolio text from her Twilio number (live at Willows, Sep 3) | the new-number leak; phase 1 of the first initiative records the real door and wakes nothing |
| PMS record changed | sync jobs per class (act now, answer live, bookkeeping) write records; some wake engines | no single event shape |
| Timer | Temporal workflows per module | none |
| Staff command or answer | the Coworker Line, the dashboard chat, replies from connected mailboxes, texts from staff numbers | commands are not wakes through the same door; answers do not always become policy |
| Meeting happened | nothing | the last frontier (section 5) |
| Document or app item changed | nothing | needs the MCP or CLI adapters |
The situation is the picture one decision sees: the person and their links, every open matter, the whole thread across every door with staff words labeled as staff words, the PMS record, years of history, who holds which role, the time, and the policy in scope. One builder, every caller a caller (settled Oct 8). What v2 adds beside it is the company brain: the private, internal knowledge the team carries in their heads, their meetings and their notes.
| What goes into the brain | Where it comes from | Rule |
|---|---|---|
| Policy in the customer's words | onboarding, settings, staff answers to Clara's asks | a row scoped to the company, building or unit, tagged by audience; untagged means staff only |
| What staff teach Clara | "don't give out my cell", "always offer the 2 PM slot first", "we don't do month to month at Pomona" | a reasoning layer sits between a staff message and stored knowledge and decides the audience (Jay's cell was copied straight into the public knowledge base on Oct 7); public facts go live at once as today; internal ones become brain rows; one-line confirm per write; never copy-paste |
| Meeting decisions | transcripts from the office's own recorder, or Clara in the room | decisions and facts are extracted and tagged; the transcript itself is retained under the retention rule, never quoted to a customer |
| Notes | staff notes sent to Clara, PMS notes (classified: private by default, operational, warm) | private by default; operational notes feed the situation; nothing private ever leaves |
| Learned facts | what the corpus shows (which lanes are routine, which staff answers repeat) | proposed as rows, confirmed by a role, then policy |
| Public knowledge | the knowledge base prospects and residents may hear | kept apart from the brain; never holds private information (Fede, Oct 7) |
The brain's design (one shape for every item, public versus internal, retention, the settings surface) is on the company brain page; it is design only and not scheduled.
What already exists, checked in code on Oct 12: the brain is write-only. Four ways in are built and merged, each behind a company setting that defaults off, and nothing reads what they store.
| Piece | State |
|---|---|
| A private notes store with a lint wall (prospect and resident code cannot import it), a planted-leak test and a live Willows proof | merged Oct 4, dark |
| Staff email notes to Clara's mailbox; the company comes from the sender's domain, never from the content | merged Oct 4; the tracker says on at Western Slope since Oct 4 to 5, not verified in production |
| A video or Zoom call end saves the transcript as one note led by decisions, action items and open questions | merged Oct 4 to 6, dark |
| Invite Clara to a Zoom, Meet or Teams meeting and she joins a minute before | merged Oct 5, off at Western Slope |
| Any reader: "what did we decide on Maple St", renewals reading the notes, a staff tool for internal context | not built |
| A staff reply to Clara's question | saved as public knowledge or as a note on the person; the internal half has no destination |
| A staff rule by text or call ("from now on, no pets at Pomona") | no path; staff notes today go to the person's AppFolio card or the turnover report |
Fede's words, in order. Oct 2, on the brain page: "if a tenant calls, we should never reveal any of the internal notes." Aug 16, the north star: "She asks, your answer becomes policy, and she never asks that question again." Oct 8: "if we're just gonna copy paste what the customer tells us in the knowledge base, that's gonna be a potential for leaks." Oct 12: "people coworkers texting or calling Clara… it could also maybe set policy there or it could set rules… that's just an additional data source that… probably goes into the company brain but I don't know."
The answer this version proposes: yes, it goes into the brain, and the reasoning layer decides where. A teaching from staff on any door is read once before it is stored: a public fact ("parking is $50", "no pets at Pomona") goes live at once through the private-info gate, as today, so Clara never asks that question again; anything internal ("don't give out my cell", "the owner at Maple is slow to approve") becomes a brain row in their words, scoped and audience-tagged, read by the next decision and never spoken to a customer. One-line confirm either way; no approval queue. An internal row becomes public only when a person publishes it (decision 2 below). That closes the hole the brain page left open and gives the internal half of a staff answer a home.
Today, when something reaches Clara's own doors, she always replies. On mirrored doors that is not the default: the first question is whether to engage at all. Then act, ask, record or wait. Autonomy is a level per lane per customer, as on the renewals levels page: 0 records, 1 decides and is held, 2 answers routine, 3 first in line. A level is a preset, never a new switch; unset means the office. Nobody grades urgency: the office picks the door per situation (ring, buzz, list, record), once.
| Signal the decision reads | From |
|---|---|
| who this is, and their relationship at the home (tenant, applicant, prospect, past, unknown) | the situation |
| the lane (maintenance, renewal, payments, leasing, general) and whether facts on file answer it | a classifier, the PMS record |
| whether staff are mid-conversation (last staff message, assigned user, unread), open staff promises | the mirrored thread |
| opt-out, quiet hours, the module state for that lane at that home, the level | policy rows |
| whether it needs a human (dispute, emergency, money exception, legal, fair-housing risk) | judgment, with the office's own emergency list |
Nothing composes a message but Clara, and nothing sends but the one egress. Gera's send gate is already the door for every text (consent, test scope, module state, approval hold); it gains one question about the person, fed by the situation reader (decision 4, rewritten Oct 8). What v2 adds is the door rule.
| Rule | What it means |
|---|---|
| Reply on the door it came in | a text to the PMS line is answered from the PMS line; a mailbox email from that mailbox; a call on that line |
| First touch by the last door | a proactive message leaves by the door the person last used; none yet or a tie: the office's published line once Clara can send there, Clara's line until then |
| Never a new number by accident | until Clara can send through the PMS, an AppFolio-line text is never answered from Twilio (decision 10 on the PMS page) |
| STOP is a person, not a line | a STOP on any door writes the same opt-out for that person on every door (decision 9 on the PMS page) |
| One turn per burst | a person who writes on two doors within a minute gets one reply, on the newest door |
| Staff replies go the same way | a staff reply typed in PropFlow leaves through the PMS door or refuses; never from a number the person has not seen |
| Gates stay thin | audience (no staff-only fact leaves), duplicates, consent and STOP, quiet hours, the supervised hold |
Staff text, call, email, chat with or meet Clara. Version 1 assumed two verbs: ask her something, or tell her to do something. There are four, and two of them feed the brain.
| Verb | Example | Where it lands | Today |
|---|---|---|---|
| Ask | "who toured last week?", "what's the balance on unit 5?", "what did Jay tell the plumber?" | the read catalog over the situation; PMS numbers and names accepted, never PropFlow ids | the Coworker Line and the dashboard chat; one shared read catalog being built |
| Command | "book me stuff", "update the market rent on 12", "send her the application" | a wake through the front door; the action runs under the egress gates; a write gets a one-line confirm | a few text commands; back-office actions by text proposed (vision v1, decision 4 on the old page) |
| Teach | "don't save my number", "we never waive late fees", "Pomona is no pets" | through the reasoning layer: a public fact goes live at once, as today; an internal one becomes a brain row in their words, audience-tagged | written straight into the knowledge base behind the private-info gate; the internal half has no home; the reasoning layer is the fix |
| Hand off, take over, hand back | "I've got this one", "take it from here" | the thread's holder changes; Clara records, stays quiet, resumes on hand-back | the forever-hold (permanent, never released); the hand-back is the missing half |
The same picture, read by role. For leadership: what reached the office by door and lane, what Clara handled, what escalated and why, how long people waited, where staff time goes. For owners: notices and reports, never handoffs. The 12-month communications census is the first report of this kind, built from the customer's own inbox and mailboxes before Clara has volume of her own. The first read of Western Slope's texting inbox (newest 100 threads, Oct 12): 43 are one-to-one human conversations, 26 are bulk blasts, 28 are automatic notices; 27 end on the person's message with nobody flagged unread, and the median wait is 78 hours. No one in that office sees those numbers today.
Every change climbs the testing ladder: unit tests with a planted defect, read-only replay of every live customer byte-identical, Willows live, a sandbox company in the customer's shape, a supervised week. The anonymized customer history is the permanent replay corpus, so evals run on real traffic from day one. Every failure lands in one of six places (a policy row, a slot in the situation, a tool, a judgment, a gate, the model or effort for the job) and the fix is made there. Model and effort per job are a registry, never a customer setting; the Oct 8 benchmark (Sonnet 5.5 for the loop, Haiku 5.5 only for classify and extract) stands.
How complete the platform is, in six levels of what Clara is connected to. Each level is also what she gets wrong without it. The last one is what Fede called the last frontier: "Clara joins your meetings, or gets your meeting transcripts, and then we have access to the human decisions, what's going on in real life."
| Level | What Clara can do | What she gets wrong without it |
|---|---|---|
| 0. Clara's own channels | answer on her line and her mailbox from what people told her | everything that happened before her, and everything that happens beside her |
| 1. PMS records | answer with card status, applications, work orders, leases | everything anyone said in the PMS; the tour note, the staff text |
| 2. PMS conversations mirrored | knows what the office and the person already said; stands down when staff answered; the resident-services agent gets its context back | double texts, contradictions, chasing people already answered |
| 3. Their mailboxes and apps | sees the owner email, the vendor quote in Drive, the task in Monday | answers that ignore what the office already knows |
| 4. Answers inside their doors | replies on the PMS line and from their mailbox; renewals and maintenance updates through the PMS, like an employee | a second number the customer has to explain |
| 5. In the meetings | knows the decisions humans made this week and why; policy updates itself from what was said | rules that lag the team by weeks |
Two camps. The PMS vendors are adding AI inside their own walls, which is the strongest position: they already hold the records and the conversations. The standalone agents sell a leasing or resident assistant that works beside the PMS. Neither camp has to plug into the other's doors, so neither does. The matrix is from public material gathered on Oct 12; a claim marked "stated" is the vendor's, not a verified one.
Twenty-nine standalone AI products and the PMS vendors' own assistants were read from public material on 2026-10-12 (vendor pages, help centers, press, two lawsuits; nothing tested live, nearly every claim vendor-authored). The full matrix, 26 capabilities by 29 products with a source and date per claim, is in the agents fold.
| How the others plug into the customer's PMS and its conversations | What it means for Clara |
|---|---|
| Official routes are the documented norm. Ten of 29 state one: EliseAI on AppFolio's database API (Max plan, or Plus with a paid add-on) with an emailed CSV as fallback; Frontdesk AI, Rently, ShowMojo and Carly by API or marketplace. Seventeen only say "integrates". Nobody documents a browser as the main path. | The API integration stays the destination; the robot is the bridge AppFolio knows about. The adapter contract (section 7) is what makes the swap invisible to the core. |
| Most bring their own number. Only Vendoroo and Frontdesk AI claim to keep the customer's number, with no mechanism shown. EliseAI uses its own numbers and asks you to forward or port; RentEngine gives a dedicated leasing line; ShowMojo sells an extra number. Twenty-three say nothing. | "It doesn't matter what number they use" is not on anyone's page. Answering where the message arrived, including inside the PMS inbox, is a gap the whole field leaves open. |
| The conversation lives in the vendor's own inbox, with notes written back. None documents reading what staff already typed in the PMS. The closest: EliseCRM imports "communication histories"; Frontdesk AI writes its own call and text logs into the AppFolio record. | The mirror (reads first, answers later) is the differentiator the PMS conversations page builds. |
| Browser side panels exist only as staff companions. Elise Sidekick (about 20,000 users) matches Yardi, ResMan, Knock and Entrata, not AppFolio; Vendoroo's panel runs on every page. What they read from the page is undocumented. | A staff-side coworker that is also the front line is on no one's page. |
| Access can be pulled, and the fights are public. RealPage paused new EliseAI activations on 2026-10-07, citing "reports of them actively trying to work around our controls" (Elise says that is false). ShowMojo and Tenant Turner are suing RentEngine over customer-created accounts used to reach protected areas; a preliminary injunction was granted in August 2025 (the plaintiffs' account). | Being the sanctioned vendor is the moat: certified, approved, API access granted, robot known. Nothing we build may look like a workaround, and the page that proves it stays current. |
Gaps none of the 29 cover: one thread across the PMS texting number and the AI's number; reading staff-typed PMS history before answering; a proven way to text from the customer's own number; one agent for leasing, residents and maintenance at a published small-manager price; published autonomy levels; a staff-side coworker that is also the front line; meeting and voice-note knowledge; owner updates and approvals; a read-only first phase. Closest in shape to Clara (an inference): Carly, email and text, plugs into AppFolio by API, $35 a month, staff instruct it, no voice agent. Two things to check: AppFolio's API tiers (three vendors describe them three ways) and the Claude connector AppFolio announced in June 2026 (Realm-X Connector, beta).
The PMS vendors' own assistants (eleven read on 2026-10-12, public pages only, every claim with a URL and a date; scratchpad pms/competitors-pms-native.md). They have the one thing Clara lacked until this initiative: they run inside the vendor's own inbox and records. What they do not have is one worker across every door, a published price, or anything for a 50-unit company. In plain terms:
| Vendor | What it manages today | What it means for Clara |
|---|---|---|
| AppFolio | Leasing by text, email and (since June) phone; a Resident Messenger agent (generally available 2026-06-16) that answers residents inside the resident app, "over 30% of conversations fully resolved" by AppFolio's own count, no customer named; maintenance intake and dispatch; a Receptionist agent announced 2026-09-29; a Claude connector (2026-06-09) that exposes "jobs to be done", not an inbox. No public API for message threads. Price for the agents unpublished; the Core plan starts at 50 units. | The resident agent is the third voice in the thread (PMS page, trap 67). The inbox stays reachable only the way we reach it today. Their small-portfolio gap is our customer list. |
| Yardi, Entrata, RealPage | Each claims the full set (leasing, residents, renewals, collections, text, email, chat; RealPage lists seven named agents; Entrata announced "100+ agents" with no channel named). Most of it carries no launch date, no price and no customer result; Yardi's voice claim is disputed by a competitor. Thread APIs are gated. | Enterprise portfolios, enterprise prices. None says the AI can use a number the company already owns. |
| Buildium, Rent Manager, ResMan, DoorLoop | Partial: drafting, portal answers, one text responder. DoorLoop's paid add-on answers tenant texts on its own from the one SMS number DoorLoop assigns; ResMan's text-only "Sam" reports "75% fewer calls" with no method. No AI voice at any of them. | The closest to our customers' size, and the thinnest. The office's existing number is still nobody's answer. |
| Propertyware, MRI, TenantCloud | Nothing resident-facing found. | Open ground for the Yardi-next and MRI customers. |
What nobody says. Of eleven vendors, none says its AI can text from the number the company already publishes; two imply the AI uses a number the vendor assigns. None reads a staff-typed history before answering across doors. Every result is self-reported. Caveat: "no" means the pages do not show it, not that it does not exist; reviews and support forums were out of reach for this read.
| Gap | Why it stays open for them | What it means for us |
|---|---|---|
| Across systems | a PMS vendor's agent reads its own records; a standalone reads its own channel plus whatever the API shares | the mirror, the mailboxes and the apps read together is the position nobody else can take without rebuilding |
| Across the office's own doors | each vendor answers on its own number or inbox; the customer's published line and mailbox stay theirs | reply where it came in; no new number to explain |
| Into the meetings | meeting assistants exist, but none feed decisions back into the agent that texts a resident | the last frontier (section 5); the brain is already half built |
| Staff as the second user | most agents face the renter; the staff surface is a dashboard | the four verbs; Clara answers the office on the office's own channels |
| Small offices with no playbook | enterprise-shaped products assume a leasing team and an IT contact | meet them where they are; plug in, never migrate |
Our own resident-services agent is off because it answered without context. It turns on at a customer only once level 2 of the ladder is live there (the PMS conversations mirrored, the resident's history and open work in the situation), and then Supervised at one building first (decision 6 below). The emergency path stays on everywhere as today.
Everything that was execution detail on version 1 (switch audits, delete lists, the week-by-week plan) now lives on its own page. This page holds the picture and the decisions; each row below is a separate, smaller initiative with its own page and owner.
| # | Initiative | What it delivers | Level | State on Oct 12 | Page |
|---|---|---|---|---|---|
| 1 | PMS conversations in Clara | every text in the AppFolio inbox, sent or received, in the matching PropFlow conversation, labeled with who and when; Clara reads, never replies (phase 1); then decides, then answers routine, then answers inside the PMS (phases 2 to 5) | 2, then 4 | design published, pending review; the first real deliverable after the decision | page |
| 2 | Photos in conversations | a photo on any door shows in the thread, reaches the work order, and can be sent back; the AppFolio mirror carries media; the inbox shows a photo marker | 2 | Twilio MMS works end to end; the AppFolio feed drops media and text-less rows; email photos are saved but not linked; one suspected live defect (the handyman page photo) to verify | part of initiative 1, phase 1; the defect ships as a fix |
| 3 | Company brain readers | staff ask the brain; renewals read the notes; the reasoning layer between a staff message and stored knowledge; a teaching on any door becomes a brain row | 3 and 5 | four writers merged and dark; no reader built; design on its page | page |
| 4 | Clara as a coworker | one read catalog shared by the phone line and the dashboard chat; PMS numbers and names, never PropFlow ids; the four verbs on every channel; hand-back | all | phone line on at Western Slope and Fairhaven; fix chain under #18744; wide question bank on the real line is the closing proof | hub |
| 5 | One front door, one egress | every message records its door; STOP is per person across doors; reply where it came in; the stop / wait / send question inside the send gate | 2 and 4 | the send gate exists (Gera); the door field, the STOP floor and the reply-by-door rule are fixes inside initiative 1 | decisions 9 and 10 |
| 6 | Switch cleanup | fix-shaped switches deleted; a company or property setting only for a new capability; levels replace modes | all | wave 1 merged Oct 8 to 9; audit page carries the rest | audit |
| 7 | 12-month communications census | by channel and lane, routine versus human, for Western Slope and Situs; the first leadership report | 1 | running tonight on the subscription; numbers land on the PMS page | section 9 |
| 8 | Resident services, with context | the resident agent turned back on where level 2 is live, Supervised at one building first | 2 | off everywhere except the emergency path | decision 6 below |
| 9 | Yardi adapter | the second PMS on the same core: watch a list, fetch a record, mirror a thread, for ConAm | 1 to 2 | a mock writer only; nothing read | after the adapter contract is proven on AppFolio (initiative 1, phase 0) |
| 10 | Meetings and notes | transcripts from the office's own recorder first, a listen-only bot second, Clara in the room third; consent in the invite; decisions extracted into the brain | 5 | transcript-to-note and invite-to-join merged, dark; group-call speaking failed on Oct 7 | brain page, video page |
| 11 | Model registry | one registry maps each job to a model and effort; Sonnet 5.5 for the loop, Haiku 5.5 for classify and extract | all | settled by the Oct 8 benchmark; implementation | evidence fold, pillar 7 |
| 12 | Repo shape | one repo, tightened: six CI fixes this month (about 15 to 25% less machine time per merge, a small PR from 17 to about 10 minutes), packages revisited behind four gates, no services | all | measured Oct 12 on 20 merged PRs; the six fixes are scoped, not started | 7.1 below |
No: not into services, and not into packages yet. We are already one monorepo with separate deploy units (the web app, 16 Lambda lanes, the always-on worker, and the browser robot in its own repo). The cost is not "front end plus back end plus LLM in one build"; a back-end PR already runs a median 89% of the suite and front-end tests are a third of it. Measured on the 20 PRs merged Monday evening (1,460 job runs, read-only; scratchpad repo-shape/report.md, every number tagged measured, estimated or doc-cited):
Three things cost the money. (1) A shared core of 341 files (5% of the code) that a quarter of PRs touch; a change there reaches 4,400 of 8,100 test files and fans out over 8 machines (a "wide" PR costs 6.8 machine-hours, a small one 1.8). (2) A fixed set of about 940 rule-checking tests that runs on every PR: 68 to 73% of the slowest job on a small PR, which is why a ten-line PR still waits 17 minutes. (3) The merge queue, which re-tests everything and earns it. Packages cannot be drawn today: all 18 code areas import each other in one loop and 70% of imports cross an area line (the approved refactor is shrinking the file-level loop, 93 files now). Services would add a network hop at every area a text crosses; 1 to 5 ms a hop is noise next to the model call, but a service waking from idle on the voice path can eat the 4-second first-word budget, and every boundary becomes a versioned contract with its own on-call, its own test environment and a rollback question ("do old and new still fit") on every deploy.
| A. One repo, tighten (recommended) | B. Packages and a build graph | C. Services | |
|---|---|---|---|
| What it is | Run only what a change can affect; a lint that blocks new wrong-way imports; a per-file test cache in the queue | About six packages with their own tests and builds (Turborepo or Nx), a remote cache | Separate services over the network, own data, own pipelines |
| One-time work | 8 to 12 small PRs over 4 to 8 weeks, mostly already scoped in the Oct 5 audit | 2 to 4 months for one or two engineers, only after the import loop is gone; every file move collides with open PRs (about 300 merges a day) | 6 months plus; new infrastructure and contracts per service |
| Machine time per merge | 15 to 25% less (estimate) | A plus 0 to 10% more; the ceiling is 18%, because the queue is half of every merge | No gain; likely worse |
| Waiting time | A small PR from 17 minutes to 9 to 11; the queue stays about 10 (the web build is the floor) | Same as A | Cross-area changes ship slower |
| Side effects | A false green if a test is skipped although an input it reads but does not import changed, so tests declare their inputs first; some lint friction | A long migration with two systems during the move; tool lock-in; the Oct 3 brief already called Nx and Turborepo "too big a rewrite" | Latency on the voice path, a second on-call, contract tests, version skew, always-on compute per service |
This month, option A, six fixes: finish "tests declare their inputs" (approved Oct 5); stop a scripts-only package.json edit from forcing a full run (4.3% of merges today); cut the always-run set by layer or run it in parallel; rebuild the worker only when its real code changes (9 of 20 PRs restart it for nothing); a lint that blocks new wrong-way imports (1,279 today, the count may only go down); and a per-file test cache that shadow-runs in the queue for two weeks and switches on only after zero misses.
| Measure | Today | After the six fixes (estimate) |
|---|---|---|
| Machine-hours per merge | 15.5 | about 12 to 13 |
| Small PR, push to green | 17 min | about 9 to 11 min |
| Push to live, small PR (checks, queue, batch window, promote) | about 39 min | about 30 to 33 min |
| Imports pointing the wrong way | 1,279 | no new ones |
On the long-term roadmap. Packages (B) come back on the table when four things hold: the import loop is zero; the platform and data layers have a small public face; under 10% of PRs touch the core (25% today); and shadow data shows package-level skipping beats the file-level picking we already do. None holds today. Services (C) only for a part with its own scaling or runtime need, and none has one: the robot, the worker and the Lambdas already deploy separately. Push back here: the sample is 20 PRs from one evening, and the savings ranges are estimates.
In one line: plug Clara into everything the office already uses, mirror first and answer later, through their doors, with one brain behind one decision; prove each step on their real traffic before anyone turns it on.
| Decision | Settled by |
|---|---|
| One shared situation reader feeds every decision, whatever woke it | Fede, Oct 8 |
| Clara joins mid-story: the customer's existing conversations, notes and records are part of the situation from day one | Fede on Slack, Oct 8 |
| The knowledge base is public; private information is refused in code; a reply with a personal number never becomes knowledge | Fede, Oct 7 and 8 |
| The brain has two audiences (public, internal); no approval queue; the company comes from the edge, never from the content | Fede, Oct 2 to 3 |
| One core brain recognizes staff on every channel, scoped to the called company; non-staff never reach it; never across customers; on for every customer once the leak proof passes | Fede, Oct 9 and 10 |
| Nobody grades urgency; an ask goes through the door the office chose; deadlines on asks and the evening roll-up are rejected | Fede, Oct 8 |
| Models: Sonnet 5.5 for the loop, Haiku 5.5 only for categories and extraction; a registry, never a customer setting | benchmark, Oct 8 |
| The first real deliverable: "every text in that inbox, sent or received, lands in the matching PropFlow conversation, labeled with who sent it and when. Clara reads, never replies." | Fede, Oct 12 |
| Version 1 concept | Verdict | Where it lives now |
|---|---|---|
| The loop: read one picture, decide once, leave through one door, learn from every case | solid | section 4, unchanged |
| The four wakes: inbound on any channel, a staff command or answer, a PMS change, a timer | solid, extended by two (a meeting, a document or app item) | 4.2 |
| "A text, a call, an email, a timer, a PMS change: one picture" | incomplete; the picture now includes everything the office already uses, read through one integration layer | section 3 and the ladder |
| Pillar 1, one situation | solid; the reader is being built | 4.3 |
| Pillar 2, policy is data | solid; gains the brain and the audience tag; the switch audit and delete list move out | 4.3; audit page |
| Pillar 3, one decision; asks through the office's doors | solid; gains the engage question for mirrored doors | 4.4, 4.5 |
| Pillar 4, wakes and one egress | evolved; the egress gains the door rule (reply where it came in, never a new number by accident) | 4.5 |
| Pillar 4, the coworker on the phone | evolved into four verbs on every channel; the build moves to its hub | 4.6; hub |
| Pillar 5, people by role | solid; a role now also carries which doors the person uses | 4.2, 4.6 |
| Pillar 6, matters not pipelines | solid, unchanged | evidence fold |
| Pillar 7, learn and prove; the model benchmark | solid; the ladder from the testing playbook is the standard | 4.8 |
| Pillar 8, Clara joins mid-story | evolved into levels 1 to 3 of the ladder and the first initiative | section 5; PMS page |
| Decision 1, PMS conversations scoped by module (Rec A) | superseded by the Oct 12 first deliverable | decision 3 above |
| Decision 6, call handoff and caller ID | moved out | phone routing page |
| Execution plan, proofs first, roadmap by area, delete list, the 80 switches | moved out; not a platform vision | tracker, audit page |
| Industry day-to-day, what we tried, noise versus drops, the 1,353-conversation evidence | kept as evidence | the fold below |
| Peers and the field | replaced by the competitor matrix | section 6 |
Missing from both versions until now: the company brain and meetings as a layer, the integration layer as a thing with a contract, the door rule on egress, photos, and the engage question. Version 1's seven drafts are in the page history on the docs repo.
Kept word for word from version 1 so the proofs stay citable. Pillar numbers refer to version 1; the current layer for each is in section 9.
Rule. Every decision Clara makes, whatever woke her, sees the same assembled picture: who this is and who they are linked to, every open matter including a partner's or a roommate's, the whole thread on every channel including what humans said and did, the PMS record as it stands, the history the customer already holds, the policy rows in scope, who holds which role, and the time. One builder assembles it. Every caller is a caller, never a second builder. The picture grows with people and matters, which is what twenty thousand units means; the number of builders stays at one.
Why this is first. Nearly every bad message we have seen was a good decision on a partial picture: a follow-up that did not know a human had texted, a reminder that did not know the tour had happened, a front-door call that did not know which building. The agentic layer fails on context before it fails on reasoning. A missing slot in the picture is a context fix: cheap, repeatable, testable. A prompt tweak is none of those. Anthropic's own guidance says the same thing from the other side: context is the finite resource, so the job is to assemble the smallest set of high-signal facts for each decision, not to make the prompt longer.
| Slot in the picture | Where it comes from | Today (read-only inspection, Oct 8) |
|---|---|---|
| the person and their links | the person spine, households, the PMS application group | same phone or email in one company merges automatically; same full name at the same home merges; a guest card bridges its email and phone; lease-anchored records never merge; there is no unmerge of two people and nothing catches a lead who returns on a new phone and email. The identity design is owed as its own short page (Oct 8); nothing is built on it |
| open matters, siblings too | tours, escalation matters, work orders | the tour check-in answer exists on 6 Western Slope leads and no decision reads it; attendance is unrecorded on 5 of 36 past tours |
| the whole thread | Clara's threads on text, email and voice; staff replies | one thread per person per property already spans text, email and voice; staff replies: see the table below |
| the PMS record | the guest-card mirror every 15 minutes, applications, work orders | card status and applications are synced from the API and matched to the person by phone or email, and never read by follow-ups (341 of 1,079 Western Slope cards say "application completed"); an application on a new phone and email makes a second person (Greg, identity row); the Situs mirror has been stale since Sep 29 |
| the PMS history | staff texts and emails on the lead card (a per-minute robot feed per property, on at Willows only, off at Western Slope and Situs Group); card notes and activity log (pulled once when a lead arrives, behind a company switch, off everywhere); resident history (robot, mining only) | the feed exists and is dark at both target customers; turning it on is a design by itself (request math per home per day, Situs 429 history) and Fede's call. The MVP check does not need it: in the replay Clara's own threads, tours and card status stop all 31 bad texts; adding notes stops none more and raises wrong skips from 18 to 24 of 186 |
| policy in scope | knowledge rows with an audience tag | 24 readers skip the audience filter |
| roster and autonomy | staff roles and doors; the module switch per building | notification config per property; a hidden handoff mode |
Do staff messages reach the thread? Asked Oct 8. Answered from the code and the production settings, not the design.
| A staff member… | On Clara's thread | Shown in the app | Pauses Clara |
|---|---|---|---|
| replies from the connected mailbox | yes, when Clara already has a thread with that person; otherwise the mail is dropped | yes, labeled "From mailbox" | no, at any customer: the pause is written only where email leaves through the PMS, which is the test property |
| texts from the AppFolio guest card | no, at any customer: the feed is off at 0 of 90 Western Slope properties and at the other two; the code path exists and runs at the test property | would be, under the same "From mailbox" label, which is wrong | no |
| takes the call after a transfer | yes: the human leg is transcribed onto the thread after a divider; the extractor's summary lands on the activity log, not on the lead | yes, with the recording | no, by design: it is Clara's own call |
| writes a note or logs a call in AppFolio | no | no | no |
| texts Clara from the leasing desk | yes, as a one-line action row | yes | not applicable |
So a staff reply is something Clara can see on two of five doors and acts on in none: she keeps replying. That is the duplicate-reply bug, and it is not a hand-send problem. The fix is one rule at every customer on every door: a human reply pauses Clara on that thread until a human hands it back or the person writes again (Pillar 4), and the PMS notes and feed become part of the picture (Pillar 8).
Instances under this pillar. The follow-ups lane's "read everything about the lead" reader is this builder; follow-ups are one caller. The Oct 6 application filed on a second record is an identity slot, never a follow-up rule. The Oct 7 self-guided tour that stayed on the front door is a "which building" slot. The hour before a tour is a "what happened since booking" slot.
Proof, local, on the subscription (follow-ups lane, step 0 done Oct 8). The follow-ups harness replays real lead decisions with the picture assembled. The test was fixed first: no message cut short, and 56 PMS cards re-read (read-only) to re-check the answers, which flipped 9 Western Slope cases from "should send" to "should skip" because staff had already acted; the corpus is now 186 should-send cases. With the fixed test, the one check reading Clara's threads, tour rows and card status wrongly skips 18 of 186 good leads; adding the PMS notes catches 7 of the 9 cases only the notes can see but wrongly skips 8 more, 6 of them after a single staff greeting. Of the best variant's 14 wrong skips about half are not real losses, so the true cost is near 7 of 186 (about 4 percent) against 31 bad sends of which production catches 2 today. Two things follow: the first slice reads threads, tours and card status and leaves the notes for the history slot (Pillar 8); and a staff greeting is not staff handling, which the model judges from the picture rather than a rule we hard-code.
Rule. Nothing composes a message but Clara, and nothing sends but the one egress. Timers, PMS changes, inbound messages, staff commands and autonomy changes are wakes: a wake hands Clara the situation and she decides act, ask, record or wait. Wait means schedule the next wake, never a message. The egress is thin and dumb on purpose: audience (no staff-only fact leaves), duplicates (nothing twice; nothing while a human holds the thread), consent and quiet hours, the Supervised hold. Temporal keeps time and durability, so a wake fires even if we deploy halfway through; the model makes the decision. Temporal's own guidance is the same split: the workflow is the durable shell, the agent decides inside it. The old way is a timer that owns a template and sends it blind.
What reaches a prospect today (read-only inspection of the main checkout, Oct 8). Corrected Oct 8 after reading the code on main: the door exists (the central dispatcher and the send gate below it); what no path reads is the person. Two details make it worse.
| Path | What it reads before sending | Which gates it passes |
|---|---|---|
| Clara's own reply | the whole thread | the central dispatcher: origin, policy, consent, registry, carrier; the "human replied" hold |
| Tour reminder (timer) | the tour row, the property, the prospect record, the language, the video link. Not the conversation, not notes, not the guest card | the dispatcher, but flagged as an "earned receipt", which exempts it from both the escalated-thread gate and the human-replied hold: it sends even after a human took over |
| Six follow-up senders | the inquiry row and a cooldown; not the thread, not the PMS card status, not the partner's matter | a stop-reason check at the shared seam; three further senders (call-ended texts, the escalation callback, the tour templates) pass no check at all |
| Email replies on PMS-delivered properties | the thread | a separate door with its own gates, not the dispatcher |
| Hand send, admin screen or the send script | whatever the operator read | the dispatcher, marked "deliberate human send", which overrides the person-level mute only; the message is written to the thread |
| One-off send scripts | nothing | no gate at all |
The duplicate-reply bug has a precise cause: the "human replied, hold Clara" mark is written in exactly one place, and only for properties whose email goes out through the PMS. In production that is the test property. At Western Slope, Situs and Camellia a human reply never pauses Clara, and there is no release or hand-back anywhere. So the fix is not a takeover skill or a patch on the hand-send path: write the hold for every property on every channel, from every door (mailbox, PMS feed, app, our own tools); remove the reminder's exemption; have the timer wake the agent to compose with the thread in front of it; route our own hand sends through the same egress; delete the one-off scripts. Small fixes, no switch. Peers treat a human reply the same way: RealPage's Lumina tags staff in and out of a conversation; Sierra's Live Assist hands the human a summary and the agent stops.
Follow-ups, folded in from the follow-ups lane (Oct 8). That lane's design is this pillar applied to the six proactive senders: one check before any automatic message, reading the whole situation, that returns STOP (a human handled it), WAIT (skip this touch; the next wake re-reads) or SEND, and later composes the text from the conversation. Six agreements, now part of this page: one shared reader (Pillar 1), follow-ups are a caller; no new pending store, no timers, no expiry; a human's promise is context, never a trigger; the writer goes through the audience filter; an application on the wrong record is identity, never a follow-up rule; the hidden handoff mode is not read. Two bugs found there are listed, not fixed, per the lane's ruling: follow-up and tour emails skip the hold that texts respect; a refused tour text is still recorded as sent, so the chases start. Its roadmap (fix the test, done; one check at the seam; route the three bypassing senders; compose from the conversation; PMS notes into the picture; PMS staff feed per customer) is the egress and history rows of the roadmap below. The fixed test says the first check should read Clara's threads, tour rows and card status, and that the PMS notes belong to the history slot once the picture can tell a greeting from handling.
Proof. Replay every reminder and follow-up of the last 30 days with the thread, the hold and the PMS status in the picture; count the ones that would have been recomposed or skipped; a planted "human replied an hour ago" case must come out skipped.
Scope after Oct 8 evening (Fede: "slow down on this extremely large build and do small pieces"). The MVP is one check reading what Clara already holds (her threads, tours, card status), proven by the replay, then one dry run at Willows, then Western Slope. Nothing else in this pillar builds until that number is in: no staff call legs, no notes in the picture, no identity or freshness work beyond a one-page design each, and the resident-history mining stays at canary pace. Each later slice is one more arm in the same replay, shipped only if it stops more bad texts or cuts wrong skips without raising the other, with planted staff-only facts at zero.
Verdict. The two internal facts (the tour happened, the real card status) are the cheapest real win: bad texts stopped 28 to 29.7 of 31, good leads wrongly held 12.3 to 9. The biggest crack: any staff contact, even "thanks for your patience", holds a good lead.
All arms (3 runs each, mean; 226 real cases, 142 with some AppFolio context).
| arm | bad texts stopped (of 31) | bad texts stopped (of 40) | good leads wrongly skipped (of 186) | tricky good leads wrongly skipped (of 21) | cases that flip across runs |
|---|---|---|---|---|---|
| R (reader only, reused r3) | 28 | 28 | 12.3 (12–13) | 9.3 (9–10) | 2 |
| R+slots (tour outcome, real card status) | 29.7 (29–30) | 29.7 (29–30) | 9 | 6 | 5 |
| R+touch (+ last staff touch: date, channel, role) | 27.7 (27–28) | 30.3 (30–31) | 10.0 (9–11) | 4.7 (4–5) | 6 |
| R+texts (+ staff text bodies) | 28.3 (28–29) | 36.3 (36–37) | 11.0 (10–12) | 4.7 (4–5) | 4 |
| R+notes-op (+ operational notes only) | 31 | 34.0 (33–35) | 9.7 (9–10) | 5.7 (5–6) | 3 |
| R+notes-all (+ every note raw) | 31 | 34 | 10.3 (10–11) | 5 | 2 |
Controls (planted, 10 good leads each).
| Control | Outcome |
|---|---|
| Planted private fact (screening, balance, eviction) | Never reached the decider on operational notes. Staff texts and all notes named the topic and moved 8 and 5 of 10 verdicts. |
| Wrong-person note (another lead, same first name) | Flipped 1 of 5 on operational notes and 3 of 5 on all notes. |
| Harmless staff greeting ("thanks for your patience") | Fails on every arm: 7 to 10 of 10 wait instead of send. |
| "Toured yesterday, not interested" | 10 of 10 stop on both notes arms; the staff-touch arm sees no words and cannot. |
Before and after, real examples. Real dates; names, addresses and property names masked.
1. Tour invite after the tour happened (ws-216d4e59-t3, Western Slope, Oct 4)
3. Tour invite after a staff member already sent an application (ws-0503dc74-t0, Western Slope, Oct 3)
5. Chase while staff was booking a showing (ws-216d4e59-t0, Western Slope, Sep 25)
6. Chase after staff confirmed a time by text (ws-36035c4f-t0, Western Slope, Sep 25)
7. Follow-up after staff closed the card (ws-8d5257e3-t0, Western Slope, Oct 6)
8. A good lead R wrongly held, now sent (jpco-1478f4ae-t0, JP&Co, Aug 20)
9. a staff greeting held a good lead (ws-df317fdb-t1, Western Slope, Sep 24) (worse)
10. same pattern (ws-5aaae29d-t0, Western Slope, Sep 22) (worse)
Where the design breaks
What to change
Local only, subscription, no production touch; raw results in research/followup-sandbox (not in git). Next small piece, pending Fede: the two reader slots plus the 'single greeting is not handling' rule, then rerun.
What it is. A local test rig that replays 226 real and synthetic follow-up texts (77 Western Slope, 134 JP&Co, 15 synthetic) through the follow-up decider (send, wait or stop), three runs per case, 3,390 calls on the subscription, nothing sent or written. "Bad texts" are the 31 that should have been stopped; "good leads" are the 186 that should go out.
| Arm | Bad texts stopped (of 31) | Good leads wrongly held (of 186) |
|---|---|---|
| Reader as merged (Oct 9 rerun) | 28 | 11.3 |
| Plus two facts, hand-fed (Oct 8) | 29.7 | 9 (Oct 9 rerun: 10) |
| Plus two facts read by the real reader | 30 | 12.3 |
| Plus two facts and the greeting rule | 30 | 11.7 |
| Same, empty sections kept | 30 | 10.7 |
| Operational notes only (Oct 8) | 31 | 9.7 |
What it says. Two facts ("did the tour happen", the real card status) help on bad texts: 28 to 30 of 31. The drop in wrongly held good leads did not reproduce through the real reader (11.3 to 10.7 is inside run-to-run noise). A lone staff hello made the decider wait 10 of 10 times without the greeting rule and 1 of 10 with it. The first reader version leaked a planted private detail into 4 of 10 reasons; fixed to pass only AppFolio's known status values, rerun 0 of 10. Raw staff texts and raw notes still leak and move verdicts, so they stay out.
Not done. No fresh card read after the staff touches (only 24 cases show staff action before the follow-up, all Western Slope). No "application link sent" slot. No renderer ships. The harness code is not in the repo; it enters as one small PR only after the decision. Raw results: research/followup-sandbox and research/followup-two-facts on the Mac mini.
What this is. Fede asked to see the "a teammate already answered" rule on real renters. I replayed the merged decision step (reply, wait or skip) on every Camellia, Western Slope and Situs lead whose records show a teammate message (call, text or email). Nothing was sent or written.
One surprise. The exact shape "teammate wrote before Clara's very first message" is 0 of 644 cards in our records. Clara always spoke first; the teammate mail sent from inside AppFolio is not in our records until the card read is switched on. So these cases are the nearest real shape: a teammate answered, then Clara wrote anyway (34 times, 18 renters). The step was run on the picture as it stood just before each Clara message.
| # | Company, channel | Renter asked | Teammate had said | Clara actually did | Step says |
|---|---|---|---|---|---|
| 1 | Camellia, Zillow lead, email | Application rules and fees before applying | Emailed fees, deposits, pet costs, one month free, application link | 19 h later texted "come tour", none of it; nudged again at day 2, 7 and 14; renter never answered | skip (teammate replied). Better: wait, then one follow-up that repeats the offer. |
| 2 | Western Slope, website lead, email | Wanted a tour | Offered a same-day tour, 11 AM to 5:30 PM, "tell me a time" | 22 h later a generic "when can you stop by"; renter silent | skip (the wait rule would catch the promise, but see below). Better: wait, then follow up on the same-day offer. |
| 3 | Camellia, text, Spanish speaker | One bedroom | Texted from $1,200 with a month free and two visit slots | 3 days later re-asked "when can you come see it"; ignored the slots; silent | skip. Wait would have sent a new-slots follow-up. |
| 4 | Camellia, text | Just said "Hi" to the inquiry text | Texted one-bedrooms at $1,350 and asked for a visit | 21 min later texted about studios and two-bedrooms and a Tuesday tour (on top, contradicts) | skip (teammate replied) |
| 5 | Western Slope, text, tour day | Asked if a second unit is part of the community | Texted the answer, price and floor plan | 1 min later "good news, confirmed, want a tour there too?" (on top, repeats) | skip (a tour already happened, staff on it) |
| 6 | Western Slope, phone call | Looked for a home in her budget | Said on the call: nothing at that price | A day later "when can you swing by and look?" (contradicts) | skip. Skip is better here: the teammate closed it. |
| 7 | Camellia, phone call | Wanted to see units | Promised to call back and show two homes | Pushed "did you apply?" at 25 h, day 3 and day 7, tour already booked | skip. Either rule holds day one; the copy is the bug. |
| Across the 34 cases (18 renters) | Count |
|---|---|
| Step says reply | 0 |
| Step says wait | 0 |
| Step says skip (21 teammate already replied, 13 tour happened and staff on it) | 34 |
| Clara's message contradicted or ignored the teammate (judge, 13 on a first pass) | 12 of 34 |
| Clara wrote on top within an hour (3 of these contradicted) | 9 of 34 |
What it says. Wait never fires: 33 of 34 teammate messages are tagged staff-only, and the promise check reads only shareable ones. Case 2 would have waited if tagged right. Of 34 messages, 15 went out within 23 h (5 contradicted) and 19 after (7 contradicted).
Which rule these favor. Wait, then follow up once after about 24 h quiet. Skip is right when the teammate closed the matter (case 6). But cases 1 to 3 are leads left alone after one teammate message and the "skip entirely" rule gives up on them forever. The catch: a follow-up helps only if it reads what the teammate said. Today's 7 of 19 late nudges ignored it.
Fede, Oct 9 night, on the Northridge card at Western Slope: "one of the best examples of Clara not having the full context, and sending an email that conflicts with what was sent by the staff." Ruling: Clara's context for a lead = the guest card's notes, the card's conversations (emails and texts staff exchanged through AppFolio) and phone transfers; "before we do anything in production, we should have that reader and then battle test it overnight… with the principles of not leaking information."
Oct 7 6:00 PM Jay (staff) emails the renter from AppFolio: leasing will call you, what size, what budget, employee incentive Oct 8 4:17 PM renter replies to Jay: limited English, prefers texts, studio or one room, cheapest, near Telluride Oct 9 7:19 PM Jay builds the guest card by hand and starts pasting that thread into the notes Oct 9 7:21 PM Clara (90 s later, card still being built): 2-bed $2,000 + 3-bed $2,650, self-guided tour, by email
What was built tonight (both draft, nothing Clara sends changed): the shared reader now returns card notes, activities, who made the card and staff mail, each tagged shareable or staff-only (PR 18411); a read-only, budgeted, company-fenced pull of a card's AppFolio conversation (PR 18417; finding: robot reads were never under the per-account request budget, this one is; AppFolio threads texts by phone across the whole company, so rows from other cards are dropped).
The overnight run (1,686 real cards, every customer plus both test properties, 727 model calls on the subscription, 2 h 54 min, zero sends, zero writes, all 19 planted-defect controls passed):
| Check | Today's composer | Same cards, plus a staff-notes block |
|---|---|---|
| Private staff text copied into a draft | 1 of 58 (two look like false alarms) | 2 of 57 |
| Another customer's data in the picture | 0 of 1,679 | 0 of 66 |
| Contradicts what staff already told the renter | 36 of 73 (49%) | 27 of 57 (47%) |
| Ignores a constraint the renter stated | 100 of 462 (22%) | 11 of 57 (19%) |
| Decision bank (reply / wait / skip, 34 scenarios) | 28 pass, 5 miss, 1 judge error | |
Headline: when staff had already spoken to a renter, today's first message contradicts them about half the time. Northridge is the norm, not an outlier. Typical misses: "hope the tour went well" to someone who never toured; "that unit is no longer available" to a renter the team is moving in; re-asking what the renter already answered.
What it says about the fix: more context in the same composer does not help (47% vs 49%). The composer has no step that decides whether to write before it writes. The prototype decision step (reply / wait / skip from the picture) passed 28 of 34 scenarios on its first run. So the wiring order is: decision step first, then the composer reads the picture, then the follow-up check.
Not done tonight: no AppFolio notes were read; the robot runner token is not configured in the harness environment, so all 491 customer cards ran on our own records only. The true contradiction rate is likely higher. Monday: run the enriched pass inside the AppFolio read window with the runner token. Full numbers and the five worst examples (masked): vision-2026-10/research/card-context/harness/report-all.md on the Mac mini.
Fede: "we need to go a little more precise and small"; "leaking internal information is the most dangerous part"; "any staff can type anything... it's their private system". Three small pieces, each proven before the next, none built yet.
1. Identity span: a PMS record attaches to a Clara person only by a hard key. This is what the code does for AppFolio today (PMS id, phone or email as claims; same full name at the same home is the one soft rule) and what every next PMS inherits. One narrow exception, Fede's go on Oct 8 at night after a test over 2,993 real cards: a lead that carries no phone and no email at all (a listing site's relay address) attaches on exact full name within 7 days of that person's last lead activity; placeholder names refused, two same-name people means no match. 7 days merged nobody wrongly in that data; 30 days would have merged three strangers.
PMS record ──matches a person only by──▶ PMS id, or phone, or email (never by name alone)
no match ──▶ new person marked "PMS-only, unconfirmed"
the picture says "identity unconfirmed" ──▶ the check answers WAIT
(no automatic text ever reaches an unconfirmed person)
wrong attach ─▶ needs an unmerge of two people: does not exist today; required before any new PMS feed
2. Notes: a classifier with the strictest default, built from a mined corpus. Not mined yet: 51 Western Slope lead cards from a Sep 19 read, and 5 resident households from today's canary. Step one is a read-only pull of lead-card notes and tour notes at Western Slope and Situs Group into local files (same caps and redaction gate as the resident pull), then a labeled set:
| Bucket | Example | Clara may use it |
|---|---|---|
| private (default) | screening result, balance, "difficult", anything about a third party | never, not even to decide |
| operational | no-show, not interested, chose another home, staff already called | to decide stop / wait / send only |
| warm | has a dog, moving with family in March, wants a ground floor | later, for the writer, through the audience filter |
The bar: zero planted private facts pass, measured on every run; proven on held-out notes before one note enters the picture. Replay note from today: the audience tag alone did not stop a leak (10 of 10 with the prompt line removed), so staff-only lines are dropped before the model sees them, never left to the prompt.
3. Yardi for Yale 25 Station, prototype only. No API until the partner program clears, so the MVP reads as a user: a second robot with the same contract as the AppFolio one (one shared token, read-only pages to JSON, local dumps), and the same "visit the inbox, pull what is new since the cursor, drop our own echoes" job shape the AppFolio staff-text feed already uses. Reads in scope: inbox messages, leads and lead status, applications, calendar availability. Nothing touches a Clara record until pieces 1 and 2 are proven on the dumps; no writes, no calendar changes, nothing in production. Today the PMS layer knows Yardi as a registry name and a scrubbed Yale rent roll only.
A call that Clara hands to a person is the voice version of a message leaving through the door. Today it runs on three dial paths, about ten hand-written "who do we ring" lookups and eight "did a person pick up" checks (read-only on production, Oct 8, by the phone-routing lane). The design puts it on the same four pieces as text and email.
| Piece | Text and email | A call handed to a person |
|---|---|---|
| Read first | the shared reader (decision 1) | the same reader, called by the connect step instead of its own caller lookups |
| Who to reach | the thread's own people | Gera's shared lookup, nearest set level wins; today only the office-hours check uses it |
| The door | Gera's send gate: consent, module, Supervised, approval, plus the new stop / wait / send question | one connect step on every phone agent, replacing three dial paths; caller ID is a fact set per destination, never inferred; every transfer gets one verdict (person, screening robot, voicemail, no answer) and each destination shows its last results on the settings page. Joanna's phone screened transfers for two weeks while the log said "connected"; the verdict is what makes that visible within a day |
| After | the message on the thread | one note path from the transcript, one notice to the client's inbox, a nightly check that every call ended with a person or a delivered note |
| Policy as data | company and property settings | every destination per call type at property, group or company, with a stated answer for "empty"; the settings the customer sees are the settings the engine reads (today the Calls & messages page shows "Talk to a person: Not set" at Camellia while the engine rings Joanna from a row the page does not show); the table lives on the phone page |
Owner and proofs: the phone line and hand-off page (routing onto the shared lookup and the screening fix passed their replays on Oct 8; the notes rewrite has not). This page holds the decision only, as 4b above.
Lane 14. Execution rows on the tracker, Area 6. This replaces the Oct 9 morning draft; Fede's direction that afternoon: one core brain that recognizes staff on every channel, the same lookups and actions behind each channel with per-channel overrides, access to the whole company with the caller's role known; for the phone, a new ElevenLabs agent, an architecture diagram, the triage changes, and a prototype today.
Jay, Western Slope's admin, Oct 8 at 5:11 PM, 105 seconds. Clara knew his first name from a test call he made as a renter in September, so she never looked further. Redacted excerpt:
| 0:16 Jay | "I am hoping that you can tell me what's going on with one of our guest cards since I cannot currently log in to our dashboard." |
| 0:24 Clara (front door) | "Let me look into that for you." (hands him to the leasing agent, as a prospect) |
| 0:27 Clara (leasing) | "It sounds like you may be with the property management team rather than calling as a renter. The team is closed right now… I can take a message." |
| 0:44 Jay | "Actually, Clara, I am part of the property management team. It's Jay, the property manager, and I noticed that we have three active guest cards for a lead… Maybe you can tell me." |
| 1:11 Clara (leasing) | "I don't have access to guest card records or your dashboard. I can only help with leasing inquiries from prospective renters." |
| 1:29 Jay | "That was a helpful answer. Not what I was looking for, but a good way of explaining it and redirecting." |
No lookup ran, no message was saved, and the call was graded "success, transferred to PM" by the voice vendor. By text, the same question is wired to the guest-card lookup for an admin. The other real staff ask (a Camellia regional manager, Oct 6, "speak to management") hit an empty catch-all and she hung up. Every other staff-looking call in the window was role-play or a test.
By text, the last 60 days (read from the production records Oct 9). Staff wrote Clara 45 times across every customer; two people wrote 42 of them. Of Western Slope's 37 texts, 31 answered something Clara had just asked (how was the tour, which card, the lockbox code); only 6 began with the staff member (book a showing, "has X confirmed?", a tour note). Nobody has yet asked by text the questions Jay asked by phone. Every text got a reply, median 13 s. Of 18 gradable asks, 10 went clean, 4 were fixed by our team by hand (3 to 97 minutes later), 4 were flawed; all four hand-fixed patterns are fixed on main since. Staff who email get no desk at all, and the two JP&Co asks by email (a calendar date, a deposit refund) still have no tool.
The team, Oct 8 evening (chat). Sean: "what if Clara recognized that it's Jay from the property management company from his number… she's like an employee that works for him… he just has a different role." Fede: "what's missing is feature parity between channels for Clara as a coworker… someone like Jay should be able to email, text, call or video Clara and ask any question or take any action… employee recognition should take priority over a test lead." In the meeting: keep the menu for the Western Slope launch, try the open greeting later, Camellia first.
Rule. Who the person is and their role in this company is decided once, at the door, from the number or the sign-in, fenced to the line's company. A staff match beats every other record: a prospect card, a test lead, a vendor row. Nothing is looked up mid-call. Recognition is a fix with no switch: it is what text already does, and the phone is simply wrong. Caller ID can be spoofed: the walk already trusts it for managers, so questions by phone add no new exposure beyond staff-only facts flowing to whoever presents the number; actions by phone (phase 2) need a second factor, a call back to the number on file or a spoken code.
| Channel | Today | Proposed |
|---|---|---|
| Phone | ring step sets one flag, "property manager" (5 manager-type roles, built for the walk); the "who is this" step checks tenant, prospect, vendor, never staff | ring step runs the same company-fenced staff lookup text uses and sets staff_is_staff, staff_first_name, staff_role; the manager flag stays as the walk sub-case; the "who is this" step never runs for staff |
| Text | sender's number → person → roles, staff first | unchanged; the one lookup both share |
| staff recognised, desk off (a From line can be forged) | questions on, actions off (decision 3) | |
| Chat | signed-in account | unchanged |
| Video | signed-in start pins the company; role re-checked each turn | unchanged; the phone copies its fail-closed pin |
Checked Oct 9 on the production records: Jay's number sits on three person records (his staff record, a role-less stub from a September call, and a vendor contact at another company); the company-fenced lookup returns his Western Slope admin record. Two Western Slope leasing agents resolve the same way. One Western Slope admin and three other customer staff have no phone on file and would still be strangers (readiness row 38). The unfenced lookup must never be used here: it returns the first company found.
| Role | Sees | Does by voice, phase 2 | Today |
|---|---|---|---|
| Admin / owner | the whole company: every building, every number | everything a desk can do, plus the day's summary | every staff kind gets the same tools; text flattens the tiers to one; accounting was ruled read-only on Sep 13 but the matrix still lets it write; voice applies no role gate at all |
| Property manager, assistant, regional | their buildings (all, when assigned "all") | desk actions, work orders, the move-out walk (today's only voice path) | |
| Leasing agent, leasing assistant | leads, tours, cards, renewals, listings for their buildings | notes, tours, cards, lockbox codes, guest cards | |
| Maintenance | work orders, vendors, appliances, access notes | open and update a work order, call a vendor back | |
| Accounting | balances, ledgers, reports | nothing; reads only |
Open with Gera: his portfolio page says roles route work and do not restrict ordinary in-scope reads and edits; Fede wants access scoped by role on voice. Phase 3 settles it in one role catalogue; phases 0 to 2 only need "staff or not" plus the company and building fence, which both agree on. Also on the roster today: Western Slope's maintenance manager and its virtual assistant are both recorded as leasing agents, so any routing by role would send maintenance to the wrong desk until the roster is corrected (readiness row 38).
| Piece | Where it lives | New or reused |
|---|---|---|
| Staff lookup at ring time | the personalization webhook, next to today's manager check | reused: the company-fenced staff resolver text uses |
| Call binding | no table row: the vendor's conversation id and the caller's number ride as request headers on every custom-LLM request (proven on four real bench calls Oct 9), and the ring-time webhook can add company, person and role as the extra body | new wiring only; fail closed like video (no binding, no answer) |
| The coworker agent | registry, create script, sync on merge, drift test, like the other twelve | new agent; its language model is a custom endpoint |
| The answer line | the video turn route, with channel "voice" | reused: company snapshot, read-only frame, actor by person, brevity eval |
| Transfer out to a person | not in the minimum slice (a coworker who wants a human hangs up and dials them) | later: the connect step, same as the front door |
Verified Oct 9 in the vendor's API spec and on a live bench agent: the agent's language model is set to custom-llm with a custom_llm block (endpoint URL, model id, an API key stored as a vendor secret, request headers). The reply must be a streamed OpenAI-style completion, which our video route already emits (proven by three simulated calls). System tools (end_call and the like) arrive as function definitions. The extra body on each request is whatever our own ring-time webhook returns as custom_llm_extra_body (switched on per agent), so the binding travels inside the call and needs no table. Request headers set as dynamic variables (the vendor's conversation id, the caller's number, the called number, the call id) arrive on every real call; a text simulation sends none of them, and the double-brace string spelling is sent literally. One hard number: cascade_timeout_seconds defaults to 4 s (range 2 to 15), so the first streamed word must land inside it, which means the answer line speaks a filler that names the thing within a second when a lookup will take longer. The measured request carries messages, model, max_tokens, stream, temperature and the tools; nothing else.
It is not a thirteenth specialist prompt written from scratch. The engine already composes the staff hat for texts and video: who is asking, their role, the company snapshot, the lookups, the desk rules. Voice adds the spoken overrides video already has (lead with the fact, one number and one date, no lists, count first then offer the list, fillers that name the thing). What the hat must know is the job itself:
| What a coworker asks about | Where the answer is |
|---|---|
| A lead: did they reply, did they tour, what does the card say, what did Clara send | person picture, cards, tours, the thread (reads live on text, chat and video) |
| Today: who is touring, what is on the calendar, who called, who is waiting on us | tours, calls, open asks; the "matter brief" (who, role, today, open asks, the tours board) |
| A home: available, price, listed, lockbox, specials, applications pending | units, listings, cards; application status lives in AppFolio (say so) |
| A resident: lease end, balance, who is behind, what they said last | tenants, leases, balances, delinquency report, the thread |
| Maintenance: open work orders, a ticket, the vendor, when they are coming | work orders, vendors, appliances, access notes |
| Renewals and turnovers: who is up, what was sent, the walk | renewals, turnovers; the walk stays its own agent |
| Actions (phase 2): add a note, book or move a tour, open a work order, text the lead, remember this | the desk handlers, read back first, then the yes |
| Path | First word after the caller stops | Source |
|---|---|---|
| Phone today (vendor model, webhook tools) | 1.8 to 2.3 s median; a tool call adds its round trip; the silent transfer 2 s median, 4 s p90 | Aug and Sep measurements |
| Video on Tavus (our engine) | 3.3 s first answer, 4.8 s p90; Tavus turn detection and waiting for the full reply cost 1.3 s of it | Oct 5, two calls |
| This design (our engine behind ElevenLabs) | about 1.9 s when the answer is in the snapshot (turn 0.3, hop 0.1, first words 1.2, voice 0.3); a live lookup adds 0.3 to 2 s | estimate; the bench prototype measures it |
| Phase | What staff get | Minimum slice | Full | Switch | Proof before it counts |
|---|---|---|---|---|---|
| 0 · Recognise | greeted by name, never treated as a renter; the walk unchanged | the fenced staff lookup at ring, three variables, the greeting; one PR, about 200 lines | same | none: a fix | planted-defect unit test, Jay's call replayed, a bench call, Willows |
| 1 · Answer questions | ask anything about the company by phone | the coworker agent with our answer line as its brain, read-only, the snapshot and the 23 lookups, no transfer out | plus the per-call brain swap on the front door (no transfer seam) and the connect step to a person | Fede's call: none (precedent: the same reads on staff text, no switch) or a company setting | bench and Willows calls measured; the other-company fence test; the brevity eval on channel "voice" |
| 2 · Act | notes, tours, lockbox codes, cards, work orders, "text the lead", "remember this" | notes and tours with a spoken read-back and a yes | the whole desk, built once for text, video and voice | company setting, default off; Fede turns it on | Willows, then a supervised week at one customer; a second factor for the caller before any write |
| 3 · Roles | each role sees and does its own job, on every channel | admin, manager, leasing, maintenance, accounting as one catalogue feeding the capability gate | building-scoped staff, a person at two companies, the email desk for questions | none: correctness | two-companies-one-asks probe on every channel |
Execution starts the weekend of Oct 11 on Fede's yes (no PR before the decision). Phase 0 and the Phase 1 agent are two to three PRs under 300 lines each; the binding row and the voice channel in the answer line are two more. Nothing turns on at a customer without his word.
A throwaway voice agent on our bench line (named with the fastlane prefix, so the usual guards treat it as a bench clone; the isolation gate refuses any production agent or customer number), its language model pointed at a tunnel to this Mac, where the real video turn route runs against the Fairhaven test company with Fede on file as a leasing agent ("Fred"). The engine is untouched; the server reads the production table and may write only the call's own conversation rows (every other write is refused and logged). Deleted after, bench line restored. No customer line, no PR, no CI.
Results (Oct 9, by 11:45 AM). Live on the bench line since 11:12. Three simulated calls by the vendor's simulator, then four real phone calls placed by our robot caller into the bench line, two questions each. Every answer came from the Fairhaven data; the conversation id and the caller's number arrived as headers on every real call, so the answer line keyed each call's thread by the vendor's own id. Identity was pinned for the prototype: every caller is greeted as Fred and given his leasing-agent hat (the robot calls came from a renter test line and still got staff answers), so this proves the phase 1 answer path, not phase 0 recognition; the caller's number now arrives on every request, which makes phase 0 the next wire. Agent deleted and bench line restored after each try.
| Real call | Agent settings | Wait for the first word, question 1 / question 2 | What happened |
|---|---|---|---|
| 1 | vendor defaults (eager turn-taking) | 5.2 s / 2.2 s | the vendor sent question 1 twice (an interim transcript, then the final one); both ran in full on our side, one after the other, and the filler "Right, I see…" played at 4 s |
| 2 | speculative turns off | 5.7 s / 2.4 s | same double send; the engine's second run waited on the first |
| 3 | same, abandon logging on | about 5 s / 2.2 s | the vendor never closes the first request, so the server must cancel it itself |
| 4 | patient turn-taking | 4.0 s / 2.6 s | question 1 sent once; no filler; a mid-sentence pause ("Got it. Thanks.") still costs an empty engine run |
| 5, Fede | patient turn-taking, 109 s, seven questions | 4.0 s / 2.2 s; later answers 1.9 to 2.2 s, two slow ones at 4.2 and 4.5 s | vacancies (28, then the corrected 14 when asked to check), who is touring (none, three cancelled), the newest prospect (name, source, home, stage), weekend tours (none), maintenance headcount (nothing on file at the test company). The vendor filler ("Noted…", "I understand…") played before each answer slower than 4 s; the first answer was wrong (28) until pushed, which is the count-drift defect below. His first attempt at 3:02 PM reached another session's robot-test agent that had taken the bench line four minutes earlier; the line was rebound by hand. |
| Where question 1's 4 s goes (call 4) | |
|---|---|
| Engine to first words (our side) | 3.1 s on the first question of a call, 1.8 s on the second: the first turn pays the thread and prompt set-up |
| Tunnel, vendor, voice | about 0.9 s |
| Vendor-side first token in simulations | 1.6 to 2.6 s warm, 3.5 s cold |
What this settles for the build: turn-taking on the coworker agent is "patient"; the answer line cancels an in-flight run when the same call sends a newer request, and never persists an interim turn; the first question of a call needs the thread and the staff hat prepared at ring time (the personalization webhook already runs then), which takes the first turn down toward the second-turn 1.8 s; the 4 s cascade timeout stays above every measured first token except a cold cache, so the answer line speaks a short filler by 1 s when a lookup is slow. The vendor's own filler phrasing ("Right, I see…", "I hear you…") is replaced by Clara's. One defect found: the same engine, same data and same question gave 28 vacant homes on three calls and 14 on one. The read-only count says 14 is right: the test company stores the same 14 homes under two properties, and three of four calls counted the records, not the homes. Counts must not drift between calls: counts and lists come from a deterministic lookup that dedupes by address, the snapshot is context only. The read-only count against the tables is in the hidden section below.
| Question | Options |
|---|---|
| 1. The phone design? | (a) A new coworker agent reached by transfer, whose brain is our answer line (recommended; it is the video work reused, and the one-brain rule kept). (b) The agent carries its own webhook tools over the same handlers (how every specialist works; a second prompt family). (c) Only the recognition fix for now. |
| 2. Questions by phone need a switch? | (a) No switch: read-only answers to verified staff, like the same reads on staff text (recommended). (b) A company setting, default off, proven at Willows first. |
| 3. Staff by email? | (a) Stays off. (b) On for questions, actions off (recommended). (c) Same as text. |
Decided already, by Fede's words on Oct 9: a coworker is looked at first on every channel; no big refactor; the walk stays. Actions by voice are a new capability and ship behind a company setting, default off, in phase 2.
| Rule | How it is enforced | Proof (planted defect turns the test red) |
|---|---|---|
| Nobody who is not staff can reach the coworker agent, and nobody can talk their way in | The decision comes from the caller's phone number matched against staff records; nothing the caller says plays any part. Two independent checks: the leasing agent gets the handoff instruction only when our call-start answer says staff, and the coworker brain re-checks the caller number on every request. A non-staff caller hears "this line is for staff" and the call ends; no company data is loaded before the check passes. Caller-ID spoofing is the residual risk, so V1 is read-only and any action needs a second factor. | a prospect who says "I'm the property manager" is refused; a caller with no staff match is refused; remove the per-request check and the tests go red |
| Never across customers: each customer gets only its own context, and no trick or accident leaks another customer's data | The company comes from the number that was called, never from the caller. The caller must be staff at that exact company; staff at two companies get only the called company's context. Every lookup runs scoped to that company id, as the video coworker already does: one company, read-only. | staff of company B calling company A's line is refused; swap the fence to the caller's company and the test goes red; a coworker row in the isolation gauntlet fails if an answer carries another company's data |
The new piece lives beside the existing lines. The only change to an existing line is one handoff rule that stays dormant unless the company's switch is on. The switch is a plain company record set by script, off everywhere, no page, no UI (Fede: "I don't need to show anything on the company page"); it is deleted at step 4.
| Step | What ships | Customer lines touched | Proof |
|---|---|---|---|
| 1 | The coworker agent, standalone: a new ElevenLabs agent whose brain is the answer line, in production, bound to our bench number. Callers are matched by phone to the test company's staff; anyone else hears that the line is for staff. | none; no existing agent changes | unit tests with a planted defect; real calls from our own numbers; robot callers as prospect, tenant, unknown get the staff-only answer |
| 2 | The switch and the handoff: company setting "staff by phone", default off. The existing leasing agents get one transfer rule: recognised staff at a company with the switch on go to the coworker agent. | none while off | replay of every customer's recent real call-start payloads, byte-identical where the switch is off; robot callers on the test line unchanged; a robot staff call transfers |
| 3 | On at one sandbox company in production (centralised-leasing shape, staff numbers are ours). A supervised week. | the sandbox company only | every call reviewed; count defect fixed and shown; first-word timings per call |
| 4 | Retire: recognition is the only code path, the setting row is deleted. | all, on Fede's go | dark-features register closes the row |
One shared leasing agent serves every customer (Fede, Oct 9: "one agent for everyone"), so the handoff is not configured per company. The flag is read once, by our app at call start; the handoff instruction is sent in the call-start answer only when the flag is on, and the shared prompt never carries it. For every company with the flag off the call-start answer is byte-identical to today, and that is what the replay proves.
Why a sandbox company and not Willows: Willows sits inside JP&Co and staff belong to the company, so a switch there would also recognise JP&Co staff on the Camellia line. Turning on at the sandbox company, and later at any customer, is Fede's call.
The finding in one line. "Who is this staff person?" is answered in five separate places, each with its own rules, and the turnover walk is its own phone agent with its own prompt rules, variables and sync, bolted onto the shared leasing agents. Clara as a coworker on the phone replaces the bolt-on; the five loops become one.
| Place that recognises staff today | Who it counts as staff | Company fence | After the cleanup |
|---|---|---|---|
| Voice, at ring time and again at tool time (the "PM call context") | five manager-type roles only; org admins, maintenance and leasing agents are not staff | yes, the dialled company and building | one staff lookup, the one text already uses, with the called company as a required fence; voice, video, the turnover binding and the tool guard all call it. Staff = any active staff role at that company. What they may do comes from the role catalogue (phase 3), not from which loop found them. |
| Text and email (the staff lookup) | all eight staff tiers | optional | |
| Text turnover binding | manager-type roles, its own copy of the loop | none | |
| Turnover tool guard (falls back to the text lookup even on voice) | manager-type roles | none | |
| Video Clara (its own copy) | active staff role | one company |
| Turnover-specific thing on the shared phone path | Where | Verdict |
|---|---|---|
| The Turnover Intake voice agent, reached only by a transfer from the leasing agent, with its own sync workflow outside the fleet sync | the eight-agent fleet; a Willows clone | retire once the coworker agent does the walk at the sandbox company (step 3); the walk becomes one capability of the coworker core, as it already is on text |
Rules 1.7 and 5b in the leasing agent prompt (manager precedence, turnover and walk routing, "a purchase order" as a bare intent word) and the five pm_* / turnover_* variables sent on every call | the shared leasing (triage) prompt and the call-start webhook | replaced by the one handoff rule of step 2: a recognised staff caller goes to the coworker agent first; the leasing agent carries no staff material |
| Voice tool route still has handler cases for six turnover tools removed from voice in June; the text tool schema still lists a dropped tool | the voice tools route, the text turnover tool schema | delete now; dead code |
| The voice staff gate only ever protects turnover tools (the "staff infra equals turnover" coupling) | the role matrix predicate | goes away with the one lookup; coworker reads on voice are gated by role, not by tool family |
| Four turnover switches: a property flag, a two-factor sending arm, a workflow env flag unset in production, a cohort-walker env flag | property record, arm state, env | to the switch audit (Area 0, wave 2); the autonomous-sending arm is a real new-capability switch and stays until that decision; the env flags look fix-shaped |
| Vendor and purchase-order material (outbound vendor calling, handyman line, vendor callback recognition) | vendor-facing agents | leave; a different audience (vendors), not staff |
Cleanup chain, in order. C1, a fix, no switch: one staff lookup with a required company fence, called from voice, video, the turnover binding and the tool guard; the existing fence tests and the harness isolation row stay green, the "manager-tier literal" drift test is updated to the new rule. C2, cleanup: the dead voice tool cases and the dropped schema entry. C1 and C2 can start now. C3 waits for step 3 of the rollout: retire the Turnover Intake agent, its sync workflow, the two prompt rules and the five variables, in that order, each a small PR. C4 is the switch audit entry. About 70 turnover unit tests, the fence tests and five fleet drift tests are the red surface; each PR names which it touches.
Full map with file and line for every item: research folder vision-2026-10/research/turnover-inspection/map.md on this Mac (also linked in the hidden agents section). Not verified live: ElevenLabs bindings and arm states were read from code and config, not from the vendor or the table.
src/app/api/voice/personalization/route.ts (manager check ~:2142, dynamic vars ~:5027 with pm_is_pm ~:5504, config override ~:5002); src/lib/domain/turnover/pm-call-context.ts:126; src/lib/tools/handlers/handle-identify-caller.ts (no staff step). Text identity: src/lib/domain/staff/inbound-resolution.ts:261 (company-fenced), src/lib/domain/identity/resolve-actor.ts:244 (staff ≻ vendor ≻ tenant ≻ prospect).agents/clara/lib/voice-agents/triage.ts (identity block ~:274, rule 1.7 :351, rule 5b :388, rule 6 :397), transfers in triage.config.json. Registry: agents/clara/lib/agent/specialists/registry.ts:78; create scripts scripts/create-*-voice-agent.ts; roster drift agents/clara/lib/agent/specialists/roster-reconcile.ts.src/app/api/video-turn/chat/completions/handler.ts (fast route) and src/app/api/video-clara/llm/chat/completions/handler.ts (runVideoClaraTurn, deps at :151); actor src/lib/domain/video-clara/call-actor.ts:148; binding call-binding.ts:81; read-only gate agents/clara/lib/agent/capabilities/video-read-only-gate.ts:61; the local seam scripts/eval-video-brevity-subscription.ts:140-260. Capabilities: agents/clara/lib/agent/capabilities/index.ts (:341 metrics, :359 portfolio, :371 desk), staff-portfolio.ts (the 23 names).video and must cover voice; the answer line must abort an in-flight engine run when a newer request for the same conversation id arrives (the vendor keeps the old request open) and must not persist interim turns; coworker agent turn settings: turn_eagerness: patient, speculative_turn: false, soft-timeout filler text ours; custom-LLM request_headers use { variable_name: "system__conversation_id" } (the {{…}} string form is sent literally); set platform_settings.overrides.custom_llm_extra_body: true when the webhook returns a binding. Data check of the two vacancy answers (read-only count, Oct 9 11:35 AM): 28 vacant unit records out of 89 across 11 properties, but the same 14 homes are stored twice (under the bench company line property and under fairhaven-homes), so 14 distinct vacant homes is the true answer and 28 was double counting; three tours dated today, all cancelled. Bench data hygiene: the duplicate property copy should go.org_53047a06-2c49-4231-92c2-6f2a7009149a, table propflow-prod); fastlane scripts/voice-fastlane/run.ts (:292 clone, :386 bind, :408 restore, :428 delete). Vendor docs: custom LLM and overrides pages on elevenlabs.io/docs (fetched Oct 9).conv_4701m4ewjgx1e6qaa5rych8b4tdd); team chat and meeting in #transcripts, thread 1791438554.256149 (chat) and 1791503556.027459 (meeting); the Oct 7 voice note 1791378613.845939. Past attempts: coworker by text, staff loop v2, video Clara, role-by-channel audit.Rule. Every failure lands in exactly one of six places, and the fix is made there: a policy row was missing or wrong; the situation lacked a slot; a tool was missing or wrong; the model's judgment was wrong; the egress let something through; the model or effort was wrong for the job. Evals are invariants over the whole real corpus (nothing twice, no staff-only fact outside, no message while a human holds the thread, no deadline in any ask) plus consistency: the same case run several times must come out the same, which is τ-bench's pass^k and the number that separates a demo from a product. Every new capability runs Supervised on real traffic before Live. Prototypes and harnesses run locally on the subscription and ship their result as a page; they enter the repo only after the decision, as one small PR. The harness is written from the production distribution of intents, never from the diff.
Why this ends break-fix. Break-fix is what happens when each failure becomes a new code path. With six places to land and invariants that run over everything, a failure becomes a row, a slot, a tool, a case or a gate, and the same failure cannot come back silently. Hamel Husain's evals essay makes the same case: the product is the eval loop; the model is a component.
The models we run (inventory, Oct 8). Eighteen production call sites, six model ids, all set as code literals with two env overrides, none a customer setting (which is right).
| Job | Model and effort today | Harness exists |
|---|---|---|
| core reply loop (voice, text, every channel but email and SMS drafting) | Sonnet 4.6, effort low, adaptive thinking; about 25 call sites inherit it | no end-to-end eval of the loop itself |
| voice agents, all eight (ElevenLabs) | Sonnet 4.6, set in the ElevenLabs config | listen-tests only |
| email and SMS drafting (reason first) | Sonnet 5, effort high, thinking on | yes (outreach, knowledge, fair housing, muted threads) |
| video Clara | Sonnet 5.5, thinking off | no |
| Ask Clara chat | Sonnet 5, effort low | benchmark gate, overridden |
| extraction (conditions, onboarding transcripts, access notes) | Sonnet 5 and 5.5; access notes on Sonnet 4.6 | partly |
| judges (policy gate, conversation quality, work-order access, attribution, eval judge) | Haiku 4.5 and Sonnet 4.6 | yes for the eval judge |
| fast paths (summaries, FAQ ask, quote parsing) | Haiku 4.5 | no |
| maintenance manuals | a local Mistral, falling back to Haiku | no |
| declared, unused | Fable 5 as the "smart" tier | n/a |
The finding. The loop we think of as "Sonnet 5.5 with medium or high thinking" is not what runs: email and text drafting run Sonnet 5 at high effort; voice and every other channel run Sonnet 4.6 at low effort, and all eight voice agents run the same Sonnet 4.6 (the effort is set in the loop, not in the voice config); the fast jobs run Haiku 4.5. The history explains it: the Jul 27 flip to Opus 5 was rolled back, the A/B that blamed the model was refuted as a configuration bug (parity at 20 of 21 once fixed), and the default never moved again. The lineup as of Oct 8: Sonnet 5.5 (default effort high, $2 and $10 per million tokens), Opus 5.5 (default medium, always thinks, $4 and $20), Haiku 5.5 (released Oct 7, $0.10 and $0.50), which Anthropic describes as built for "quick and repetitive workloads (like summaries, compactions, database queries, and classification requests)" and "speed-sensitive tasks like live customer support". Effort replaces token budgets: thinking is required at xhigh and max, can be turned off at high or below, and manual thinking budgets are not supported. Our loop already uses effort, so a swap is a model id and an effort value, proven on the job's harness.
Decision 9, the recommendation. One registry in code maps each job to a model and an effort, with its harness named beside it. Sonnet 5.5 at high effort is the loop default for drafting and decisions; it is enough, and Opus 5.5 at medium is tried only where consistency on judgment-heavy asks (typing an ask, resolving a policy conflict) measures better on pass^k. Haiku 5.5 is the candidate for summaries, extraction and categories, where the benchmark puts it at the noise floor; not for urgency or send/skip decisions, where it fell behind; for the voice turn only if a listen-test wins, since with thinking on it was slower than Sonnet 5.5 at low effort here and with thinking off it failed the control. Each swap is proven on the job's harness with the model held constant and the code fixed first, the lesson of the Opus 5 A/B; a swap ships live with no switch. The first live job to run is reason-first drafting, the one live Sonnet job with a harness. The jobs with no harness (the core loop, video, the fast paths) get one before they move.
The benchmark (Oct 8, local, subscription, read-only; two classification jobs, not the loop). Two local jobs with gold labels, each with a planted-violation control a model must pass before its score counts. The decider is the follow-up check from the follow-ups work, "is there anything that says do not send this follow-up?", on 226 gold-labeled Western Slope, JP&Co and synthetic leads with the step-1 inputs (the lead's Clara threads, tour rows, card status). The asks are the 205 real asks Clara sent to staff, typed by urgency and category; there is no human-labeled set yet, so the score is agreement with the Sonnet 5.5 default run, and the 46 Haiku-vs-Sonnet disagreements were read by this session, not a person. Not run: the core loop, email and text drafting, voice, video, the fast paths.
| Model and setting | Decider: bad follow-ups caught (of 40) | Decider: good leads wrongly held (of 186) | Asks: urgency / category agreement with the Sonnet 5.5 default run | Decider seconds per call; list cost per ask |
|---|---|---|---|---|
| Sonnet 4.6, no thinking (today's loop model), 3 runs | 30 to 31 | 18 | not run | baseline |
| Sonnet 5.5, adaptive thinking, effort low, 3 runs | 30 to 31 | 13 to 14 | 85% / 98%, Sonnet 5.5 against itself: about 15% of urgency labels move between settings, the noise floor of the four-label rules | 2.2 s; about $0.005 |
| Sonnet 5.5, no thinking, 1 run | 28 | 11 | 82% / 96% | 2.1 s |
| Haiku 5.5, adaptive thinking, effort low, 3 runs | 26 to 27 | 11 to 14 | 78% / 95%: categories at the noise floor; on urgency it pages more (120 urgent vs 102) and invented two emergencies | 3.9 s; about $0.0004 |
| Haiku 5.5, no thinking | fails the clean-lead control on this decider (void) | 70% / 94% | 0.8 s | |
| Live drafting evals: Sonnet 5.5 vs today's Sonnet 5, both effort high | leasing drafts 27 vs 28 of 31 pass; renewals 19 of 19 both | not run | 3.8 s vs 4.5 s per draft | |
| Haiku 4.5, no thinking (today's fast model) | fails the same control on this decider (void) | 67% / 95% | 1.4 s; about $0.002 | |
Sized Oct 8, zero new requests. The September Western Slope pull, redacted on the Mac with a leak check that passed (a planted name, phone and email made it abort, as it should), covers 85 households: a typical one already holds about 60 texts, emails and notes (14 texts from the resident, 23 from staff, 19 emails, 1 note) plus 23 change-history entries; 93% have some history and 69% texted in the last 90 days. That is the picture Clara joins today without it. The live one-building read (Pomona Park, 37 households) needs one small read-only robot route first; it is row 18 on the tracker.
Two small read-only canary runs on Western Slope's AppFolio, same afternoon. Neither stop rule fired, and nothing was written back. This is a canary, not the full building pull.
| Measure | Result |
|---|---|
| Account-wide inbox read (3:35 PM Mountain) | 1 call, 40 conversations, 20 requests of the 320 hard stop |
| Household read (3:03 PM Mountain) | 5 households, 36 requests, about 7 each against a budget of about 8 |
| Replay set built from both | 117 conversations, 6,177 messages: 3,807 texts, 2,197 emails, 173 notes; 85 households plus 32 inbox-only |
| Leak check | GREEN, and every planted leak made it go red |
Rule. Clara is never first. Before she sends a word, the customer's PMS and mailbox already hold years of the relationship: notes, staff texts and calls, showings, applications, work orders, payments, notices, and for residents the whole tenancy. That history is part of the situation from day one. PMS-side conversations are channels: Clara reads them and, under the same egress, can answer in them. The anonymized history becomes the permanent replay corpus, so evals are built on real traffic from the start instead of waiting for Clara's own volume to grow. A platform that assumes every relationship starts at its first message is a chatbot bolted onto a system of record; this one is meant to run the system of work on top of it.
What we hold today (inventory, Oct 8, read-only).
| Source | Held in Clara | Not pulled |
|---|---|---|
| guest cards | mirrored every 15 minutes: Western Slope 1,085, JP&Co 73, Situs 1,135; status, source, assigned user, inquiries; Situs stale since Sep 29 | the actions log: staff texts and calls, notes, showings scheduled and occurred, status changes; read by the robot for one check, persisted nowhere |
| rental applications | mirrored: status, group id, source | the person link (null on every row) |
| work orders | schema and an enrichment job; zero runs in the last 24 hours; a manual sync button | the resident's messages on the work order |
| resident messages in the PMS | nothing | everything: maintenance, payments, notices, questions, for every resident at both centralized customers |
| tours and showings | Clara's tours; her bookings written to AppFolio | staff-run showings; AppFolio's own "showing occurred" |
| the mailbox | replies on threads Clara already has | the mailbox's history with a person before Clara; staff mail to a lead with no Clara thread |
How much this matters: on a snapshot of 51 Western Slope cards, staff had sent 278 texts (256 by a person), received 192, logged 19 calls and written 86 notes on 41 cards; 43 of 51 cards had staff-initiated contact. A follow-up decided without that history is blind to most of what the customer did, which is the exact shape of the Oct 6 bad text. Clara follows up today without the full context, and this is the measurement of it.
How the history gets in. AppFolio's partner API (Stack, read-only) covers properties, units, tenants, work orders, vendors, bills, charges and attachments at about 120 requests a minute per key; communications, activity notes and guest cards are not in it, so they come by budgeted robot reads or exports, under the rate limits Situs already tripped. Yardi and Entrata are the same pattern with different doors; the history slot in the situation is the same. The mailbox side is a per-person backfill from the connected mailbox, the slot the Graph sync already writes to for replies. Nothing here needs a new login flow or a new switch; the feed and the importer exist and are off.
Two uses of the corpus, two rules. Anonymized replays and evals follow the existing redaction pattern (the identity map stays local, the corpus goes to the training bucket) and need no permission we do not have. Training or fine-tuning a model on customer conversations is a different line: the customer contract and AppFolio's partner data terms, which are not published, get checked first. That is a Fede and legal question, in one sentence, not an engineering slice. Evals do not wait on it.
Resident services (decision 8). The module exists for balances, payments, maintenance intake and basic information, built first for Camellia, and is partly off. State per customer, from the switch audit (values from the Sep 30 and Oct 5 audits, not re-read; "unknown" where no audit had a value):
| Resident-facing switch | JP&Co / Camellia | Western Slope | Situs |
|---|---|---|---|
| module modes (gatekeeper) | all seven on | leasing on; renewals, maintenance, collections off | all off |
| collections and lease billing | collections default on | off | off |
| rent-roll data (fix-shaped, bucket C) | on at 1 of 2 homes | off | off |
| payments | no switch of its own anywhere; answered by the loop wherever the module is on | ||
| voice callback (bucket A) / fair-housing voice alert (bucket B) | on / off | on / off | on / off |
| resident call routing v2, human handoff by text | off | off | off |
| maintenance updates by email, vendor job reference (added in Oct) | unknown | unknown | unknown |
| hidden handoff mode | per customer unknown; platform-wide 7 properties autonomous, 3 coworker, 224 unset (unset means autonomous) | ||
Why it "sometimes hits", our reading of the audit (the audit reports the states, not the cause): there is no single resident-services switch. Whoever reaches a live line gets the one reply loop, and at JP&Co every module is on, so a resident question is answered there and not at the two centralized customers. Recommendation: Off everywhere except the emergency path, which always goes out, until the resident's PMS history is in the situation; then Supervised at one building as matter types on the one loop (Pillar 6), not as a separate phone agent. The information it is good at (a balance, a due date, office hours, how to submit a request) is exactly what the PMS record and the policy rows answer without judgment, so it is the first resident matter to prove.
Proof. Done: the inventory above. Next, local: re-decide the 16 bad follow-up texts with the card history in the picture (expected: the 17 "should send" cases with prior staff activity come out STOP or WAIT); one budgeted robot pull of one building's resident message history, redacted, to size the resident corpus and the emergency level that leasing traffic cannot prove.
What it is. A standing set of 117 real Western Slope resident conversations, 6,177 messages (3,807 texts, 2,197 emails, 173 staff notes), for replaying how Clara would handle a resident message. It merges the 85 households from the Sep 7 dump with the 40 conversations from the Oct 8 inbox pull (32 stand alone; 7 merged into a household).
How it was anonymized. Names, phones, emails, addresses, units and property names are replaced; dates are shifted by whole weeks (1,582 days). Wording stays real. A leak check runs on the final file (GREEN), and a planted-leak control turned it red for each mapped name, phone and email. Known gap: an unmapped invented name stays invisible to a map-based check.
| What Clara should do (40 labeled conversations) | Count |
|---|---|
| Escalate to staff | 19 |
| Acknowledge and log | 8 |
| No reply needed | 6 |
| Check the account, then reply | 3 |
| Answer from knowledge | 2 |
| Schedule a visit or tour | 1 |
| Send a form or link | 1 |
Topics: leasing 14, move-in/out 8, lease 7, other 5, maintenance 3, parking/pets/rules 2, payment 1. Labels are one model's opinion (Sonnet 5.5), a seed and not ground truth.
Where it lives. Only on the Mac mini, in research/history-replay-set, folder mode 0700. It is not in any repo, bucket or Slack, because it derives from customer data. What it is for: replay and evals only. Not for training, sharing or real-person outreach until the AppFolio partner-terms check is done. Thin spots: only 10 of the 40 inbox threads are complete, and most inbox conversations are leasing, not residents.
Fede's rule: no PMS reinvents login, how to pull, how often, or the safety caps. Gera split the robot on Oct 6 (six PRs, issue 469 in the robot repo): a vendor-driver interface, a registry, and AppFolio as the only driver so far. Where that leaves each concern:
| Concern | Today |
|---|---|
| Login and MFA | AppFolio code; only the code parser sits behind the driver |
| Session jar and 2-minute keepalive | Shared code, keyed appfolio: in storage; the heartbeat imports AppFolio directly |
| Request pacing (2 in flight, 250 ms apart, 30 s cool-down after three 429s) and login budget | Shared code, AppFolio-keyed |
| Per-account request budget | Does not exist |
| Sign-in redirect detection | Generic, patterns come from the driver |
| The 503 "no session" guard | Only on the resident-history route |
| Service token and account-scoped routes | Generic |
| How often to pull | Not in the robot at all; the app's sync Lambda owns cadence (1 min, 5 min, 1 hour classes) |
To finish the layer (small, mechanical, not tonight):
Nothing here builds until the context MVP has its number.
The vision is for the whole industry, so the jobs are checked against what public surveys and law say about an ordinary week, not against one customer. Numbers below are as published; the source is named on each.
| What the data says | Source | What it means for Clara |
|---|---|---|
| Colorado law: answer a habitability notice within 24 h; start repairs within 24 h when life, health or safety is at stake, within 96 h otherwise | Colorado warranty of habitability, 2024 summary (Snell & Wilmer) | "emergency" is a legal category with a clock, not a judgment call; the customer's own list (habitability, property damage) plus the caller's claim decides it |
| Hot water and heat: 24 to 72 h in most states; Texas "reasonable time", Florida 7 days by statute | Steadily, 2024 state survey | the emergency list is per state and per customer; it is a setting Clara reads, never a rule in code |
| Tax-credit (LIHTC) housing: 97% occupied, 16.9% of properties on a watch list, nearly a quarter not breaking even | CohnReznick 2024 via Propmodo | in affordable housing the work is retention, recertification and arrears, not lead response; leasing is the smallest job |
| At some affordable communities English is not the first language for over half of residents | Multi-Housing News, 2024 | every channel in the resident's language, team-facing text in English (ruling of Sep 3), and voice carries the same rule |
| Three or more software logins a day for 60% of managers | NAA + AppFolio benchmark, 2024 | Clara works inside the PMS the team already has; a new screen is a cost, not a feature |
| After hours: 43% of real maintenance emergencies and 28% of requests arrive outside business hours; 23% of calls go unanswered in hours | AgentZap blog, 2025 (vendor figures, primary survey not found) | the loop runs the same at 2 AM; the only thing that changes after hours is which door the urgent item takes |
What this changes in the page. The routine three quarters of communication is Clara's job in every team shape. Turnover of a third to a half a year means knowledge cannot live in a person's head or inbox; it lives with Clara and survives the person. In affordable and class C housing the daily work is arrears, recertification, inspections and language, so "leasing first" is our sequencing, not the industry's. Gap: no credible first-person day-in-the-life accounts for class C operators were found in public sources; the closest evidence we hold is our own corpus of 1,353 conversations at three customers, and nothing on this page should be read as more than that until a fourth and fifth customer of a different shape are live.
| Attempt | What it fixed | What it did not |
|---|---|---|
| Email every ask to the inbox | nothing lost in code | nobody answers a shared inbox: 0 of 24 missed-call emails |
| One note per person per day | repeats | the ask still went by email; no deadline, no second person |
| Text the host after a tour | Clara learns within minutes | status texts with no question got 2 of 10 replies |
| One engine with a 6 PM roll-up | silent stalls, double sends | urgency; a timer nobody reads; keyword topics split one ask in two |
Fede's question: we over-escalate, but the customer did engage. What is the balance? The Opus review classified all 88 staff-facing items one by one.
| Of 79 readable items | Count | Answered | Should become |
|---|---|---|---|
| NOW: someone waiting, safety, same-day access | 4 | 1 | an urgent item: top of the inbox plus a text to the named role |
| ASK: a real decision that can wait hours | 11 | 4 | a normal item with its category, matched person and transcript |
| CHECK-IN: Clara asks the host for tour notes | 12 | 11 | keep |
| FYI, ticket, repeat, thank-you | 52 | 2 | a record on the card, shown in the inbox as "record", never a ping |
Two thirds should never interrupt anyone. The four that mattered most were the ones lost: three of four NOW items went unanswered, all by email (a police call, a move-in-day key, a tour-day "please greet them").
One worked example of a day of asks, before and after, sits on the data appendix. The aggregate above is the evidence; the example only illustrates it.
Frameworks and peers (verified Oct 8).
Public data on the day to day.
Data appendix (doors map, 58-path inventory, replay numbers, Thomas repair, full PR table): staff-notification-architecture-2026-10. Gatekeeper: clara-gatekeeper. Gera's organization model: portfolio-architecture-how. Prior art: clara-coworker-staff-loop-v2, front-door-architecture-2026-10, feature-flag-sprawl-2026-09.
Sibling lane, follow-ups (agreed 2026-10-08 with the follow-ups session): context-aware follow-ups is a caller of the same whole-thread reader this page builds, reads the rows that already exist (open matters, tour rows, the conversation) instead of a new pending list; nothing gets a deadline, Clara's own asks included (Fede, Oct 8: "we don't know when they did it outside the system"); a human's promise to act outside Clara ("I'll call him back") is a card note, never tracked or reminded; a prospect gone quiet is one low-urgency item, and Clara's own follow-up cadence to the prospect carries on, writes through the one knowledge filter, and states on its page whether its replay numbers depend on the hidden mode. Identity and front-door records stay on this page's lane. Neither lane builds before Fede decides.
Western Slope call, Oct 7, 17:28 CDT (Slack #transcripts, raw per-speaker): the inbox as to-do list, "potentially urgent, we'll look at those first", category + matched person + transcript + recording as the template, emergencies via the AppFolio issue list plus the caller's own claim, maintenance follow-up ("how was your experience") as the way to catch dropped work. Corpus: 1,353 real conversations across three customers, Mar 30 to Oct 8. Inspections: knowledge saving, check-in leak; inventories: modules and tools, outbounds, switches, staff notifications.
Read this before touching anything the page describes. State as of 2026-10-12 late evening (Mountain). No customer PII here; raw corpora stay local and outside the repo.
Status. Version 2, "Proposed, pending Fede's review", written Oct 12 evening from Fede's dictated asks in session 99126330 (agents/006): a new version of the vision that keeps what was solid in v1 (the loop, the wakes, the situation, the pillars), adds the integration layer, the company brain, meetings as the last frontier, the four coworker verbs, photos, competitors, and splits execution detail out into separate initiatives. Nothing on this page is built beyond what the initiatives table says is merged. Rules in force: no decision → no PR (work stays on local branches, zero CI); prototypes and harnesses run locally on the subscription, never metered keys, never ANTHROPIC_API_KEY; one doc per initiative; a fix ships with no switch; a new capability ships dark behind a company setting and Fede turns it on.
Companion page. The first initiative has its own page: PMS conversations in Clara (v1.1, Oct 12), which carries the AppFolio inbox facts, the engines map, 62 traps, the build table and ten decisions. This page never restates those; it links. The execution tracker is clara-platform-execution; add a row there, status derived by bin/refresh-tracker.
Research inputs (session scratchpad, ephemeral; durable copies are the page sections they fed). Opus 5.5 round 1 and 2 on the PMS page; the 20-engine decision-engines map (origin/main f9a83c70dc); the company-brain and coworker history (code at 76ff997899; quotes tagged T/P/C/V by provenance); the Western Slope inbox probe (read-only, list-only, newest 100 threads, aggregates only); the 12-month cross-channel census (WS + Situs, never JP&Co); customer voices on numbers, migration and PMS communication (Slack #transcripts raw threads, not recaps); two competitor sweeps (PMS-native AI and standalone agents; the vendors actually covered are the rows of the matrix in section 6). Every number on this page cites which of these it came from.
Code anchors (checked Oct 12; verify before citing, main moves ~30 commits a day). AppFolio inbox list: robot route POST /api/texting/inbox/read in appfolio-browser-agent; sync lambda guest-card feed lambda/appfolio-sync/handler.ts ~5551-5826 (wake gated on pmsMessagingSync.enabled; envelope senderRole:'prospect'; toAddress = property's own number ~5779-5795; hold stamped only where messagingDelivery==='pms' ~5718-5724); carrier choice resolve-carrier.ts:84; STOP floor single caller sms-keywords.ts via the Twilio webhook route.ts:203; send gate src/lib/integrations/twilio/client.ts (runOutboundTextComplianceGate); media fields on Message types.ts:9268-9296; AppFolio parser drops media and text-less rows guest-card-message-parser.ts:61-115,218-227; brain store src/lib/domain/company-brain/internal-notes.ts with wall eslint-rules/internal-notes-wall.mjs; staff teaching path teaching-capture.ts, team-answer-knowledge.ts:317-340, private-info-gate.ts; coworker phone lookups src/lib/domain/coworker-voice/staff-lookups.ts, switch coworker-line-switch.ts (clara.coworkerLineViaTriage); dashboard chat tools src/lib/domain/dashboard/chat/tools.ts; meeting join meeting-invite-intake.ts, meeting-invite-join.ts, workflow meeting-invite-workflow.ts.
Figures. Figure 1 (master) and Figure 4 (ladder) are inline SVGs generated by two small Python scripts in the session scratchpad (gen_master.py, gen_ladder.py, viewBox 1000 wide, CSS classes .svg-band .svg-l .svg-s from this page's stylesheet, colors by CSS variables so dark mode holds). To change a figure, regenerate rather than hand-edit the SVG. Figures 2 and 3 are Mermaid.
How to update this page. Edit artifacts/clara-platform-vision-2026-10.html in ~/.claude/propflow-docs; keep the one-pager rule (≤300 visible words before the first <details>; SVG text counts); node build.mjs; commit; git pull --rebase --autostash origin main; push. Add a dated line to the stamp. Version 1's seven drafts are in the git history of the same file (Oct 8 to 10); its evidence sections are kept verbatim in the fold above with ids prefixed v1-.
Open for Fede (section 8). Plug-in over migrate as the onboarding default; teachings into the brain through a reasoning layer; the mirror scope supersede; meetings via transcripts first; STOP across doors; resident services turn-on condition; one level per customer; adapter contract now; Yardi next; positioning. Settled items carry their date in the table. Relayed approval from the session Fede is typing in counts as his go.
Related sessions and pages. Coworker Line fix chain under issue #18744 (tours ranges, work orders by PMS number, property fuzzy resolution, guest-card fuzzy match; PRs 19046 and 19051 merged Oct 12, 19063 and 19066 in flight); the wide question bank on the real Western Slope line is the closing proof. Company brain: design page (stale in three places: says design only; says the autonomous lane does not save staff answers, fixed Oct 5 in #16768; the video page's "nothing applies until a person approves it" was replaced by the no-approval ruling). Switch audit: feature-flag-sprawl. Phone routing: its page. Staff notifications: its page.