One place for everything Clara knows about a customer, with every piece labeled by who may hear it.
Proposed — pending review. Design only; not scheduled for build. Fede's vision, 2026-10-02. Revised that evening into a general framework for every kind of company information. Names and patterns are copied from shipped products, each cited (Fede: "follow industry best practices"). Renewals is worked example 1. Revised again after Fede's review: two levels for v1 (Public and Internal), and connectors added to the long-term vision.
Removed 2026-11-03 (Fede): the email notes intake (staff emailing meeting notes to clara@) is deleted in #24977. Fede: "delete". The meeting bot now captures meetings directly, nobody used the email path, and the Nov 3 isolation audit found it was the one door through which meeting words could reach a prospect. The setting, the Customers-page card, the writer and its tests are gone; notes already saved by email stay. The meeting bot is gated on "Clara joins meetings" (clara.meetingInviteJoin) alone.
The idea. Clara is one assistant working with many teammates at a customer. Everything she knows carries an audience, in the industry's own words: Public (anyone she talks to) or Internal (that company's staff). Tenant- and prospect-facing Clara cannot reach Internal at all: not in her prompt, not in her tools, not in any search. Over time, connectors feed in what the customer already keeps in Notion, Google Drive, SharePoint and similar tools.
Fede's most important rule: "if a tenant calls, we should never reveal any of the internal notes."
Contents
Approved Oct 3 night: notes store (proven at Willows with an end-to-end test), email intake (removed 2026-11-03, Fede), and meeting transcripts → notes. Building overnight. Nothing turns on at Western Slope until Fede says so.
Fede, 2026-10-03: "the whole point of this program is to actually deploy it in that customer… renewals… capture the notes in their company brain… nothing will be shown to prospects… make a plan first."
Goal: Western Slope's meeting notes land in their Internal brain, staff can ask Clara about them, and renewals use them. Prospects and residents never see any of it.
| Track | What | Blocked on |
|---|---|---|
| A. Renewals on, current rules | Turn renewals on at Western Slope with today's engine, Supervised mode for week one. | (1) Where to record one real AppFolio renewal offer, so the robot can create Western Slope's offers (175 of 179 leases had none on 09-28) — Fede's call. (2) Company renewal policy: term, month-to-month fee, rent strategy (their AppFolio default is "$0 change"; 10 of 19 recent renewals stayed flat). (3) One clean run of the nightly eligibility job. (4) Renewal switches on about 70 buildings. From the 09-28 renewals page; not re-checked in production today. |
| B. Notes → brain → renewals | The phases below. | Fede's scope confirmation; Gera's acceptance of a new note row on the company record (via Smith). |
| Phase | What Western Slope gets | Size | Turn-on |
|---|---|---|---|
| 1. Internal notes store | A place for notes on Western Slope's company record: text, source, date, and an optional property, unit, lease or tenant. One reader module; a lint rule stops prospect/resident prompts from importing it; planted-leak test. | 1 PR | Nothing visible |
| 2. Email intake (removed 2026-11-03, Fede) | Staff email notes to clara@propflowai.co. Clara knows the company from the sender's email domain (Western Slope already emails Clara), checks the mail is authenticated, and saves the body and text/PDF attachments as a note. Each company lists its own domains; free-mail domains (Gmail, Outlook…) never count, and a domain belongs to one company only. | 2 PRs | New capability: company setting, default off; Fede turns it on |
| 3. Staff can ask | "What did we decide on Maple St?" answered on the staff text desk and Ask Clara, from notes only. | 1 PR | Same setting |
| 4. Renewals use notes | A meeting decision ("hold unit 12 flat", "+3% on Maple St", "move unit 4 to month-to-month") becomes a per-lease or per-building override the pricing step reads before the rent is frozen. | 2 PRs | Same setting |
| Later: meeting join | Clara joins their Zoom and listens; the transcript becomes notes. | 4–5 PRs | Building now: the transcript-drop fix and transcript → note. Proven on Fede's next Zoom test. |
Today it's all fixed rules, no AI on the money: renewal switches, a 90-day window, eligibility (balance over 2 months of rent or more than 2 late payments → a person), gates (declined, notice given, opted out, transfer, signer email), rent strategy (market, current + %, current + $), terms and month-to-month fee, Supervised mode. The rent is frozen on the renewal and the AppFolio robot writes that number. Nobody can override rent on a single lease today — that per-lease override is the one new piece.
| Stage | How notes count |
|---|---|
| 1 (pilot) | Clara reads the note, quotes the line, and turns it into a structured override using the strategies that already exist ("flat" = current + $0, "+3%" = current + 3%). Design to be confirmed after notes are flowing; no auto-apply step. |
| 2 | Notes become context Clara can use in tenant negotiations, never quoted to the tenant. |
| 3 | Patterns across notes suggest policy changes ("7 of 9 Maple St calls were flat"); a person says yes. |
When a note and a rule disagree: gates win (a declined or noticed tenant is never offered), then the meeting note, then building policy, then company policy. A note that asks for rent below current, or that can't be matched to one lease, goes to a person.
We ran today's renewal engine on Camellia's 27 leases ending Jul 31 – Sep 30. Then we ran it again with notes pulled from five team meetings where the property manager went through renewals lease by lease. Both runs were graded against what actually happened. Local test only, nothing merged, nothing written to production.
| Today's engine | With notes known at the time | With all notes, incl. later ones | |
|---|---|---|---|
| Called it right | 19 | 20 | 23 |
| Wrong | 6 | 6 | 3 |
| Sent to a person | 1 | 0 | 0 |
| Decision changed | — | 9 | 11 |
What it means: notes barely move the final outcome. The real gain is in how leases get handled. A lease going to a lawyer is held, a tenant moving out isn't chased, and a paper renewal isn't texted and auto-switched to month-to-month. One note made things worse: a casual "he'll just go month to month" was read as a decision, and that tenant renewed.
Where it breaks:
Eight labeled synthetic notes (wrong unit, conflicting rent, below-current rent, a note against a notice to vacate) were all handled by the rules. One rule changed during the run: a notice to vacate always beats a meeting note.
Sources: renewal engine and intake paths read from the propflowai repo on 2026-10-03 (renewal-auto-start.ts, renewal-rent.ts, eligibility/engine.ts, process-inbound-email.ts, calls/ended/handler.ts); Western Slope renewals state from the 09-28 renewals page.
Context only, no decision yet
What exists, what Fede has said, and what is open, before any design for where Clara stores what she learns from staff replies.
| When | Words |
|---|---|
| Oct 3, night | A staff reply to one of Clara's emails or texts should save to the right place in the knowledge base; the six-month-lease case is a common example; use the company brain architecture; he is unsure paragraphs scale. |
| Oct 3, evening | A note is saved to the sender's company brain; nothing in it is ever shown to prospects. |
| Oct 3 | In the middle of three outcomes for a team reply, the reply gets saved to the knowledge base / company brain — and he doubts the reply loop works at all. |
| Oct 2, evening | Wants one general framework for every kind of company information; a tenant caller must never hear an internal note. |
| Oct 2, midday | Company brain spans the knowledge base, listings, fees, rules and notes; "we're not going to build any of this" yet. |
| Sep 29 | The knowledge base is the authority; company-wide rules live at the company level, a property holds only its own exceptions. |
| Sep 28 | A policy question goes to staff, then the answer is saved to the knowledge base. |
| Aug 20 / Aug 13 | A one-off answer is not a policy; a staff reply IS policy, live immediately, in the same store Clara reads, with no review step. |
| Coworker lane | Autonomous lane | |
|---|---|---|
| Trigger | Reply on the matter's email thread | Reply to the team note |
| Relay to renter | Yes | Yes |
| Saved to the knowledge base | Yes — cleaned, checked for invented numbers, written at the property level; an exact repeat corrects the old entry, "no longer true" retires it | No — the reply is relayed to the renter but never saved |
Western Slope runs on the autonomous lane, so its staff answers (including the six-month-lease case) take the path that does not save today.
"14:32 — Twelve, let's just do month-to-month, he's selling in the spring."
renewal.term = month_to_month (optional; from the consuming workflow's fixed list)| Input | Source | Scope | Audience | Effect |
|---|---|---|---|---|
| Public policy | onboarding answers | company, property | Public | – |
| Listing, fee | AppFolio sync | unit, property | Public | – |
| Meeting content | transcript | lease, person | Internal | only when a decision |
| a mailbox Clara is copied on | person | Internal | – | |
| PMS note | AppFolio note | person, unit | Internal | – |
| System signal ("3 late payments") | computed job | lease | Internal | – |
| Staff judgment ("problem tenant") | staff message | person | Internal | – |
| Decision ("12 is month-to-month only") | transcript or email | lease | Internal | renewal.term = mtm |
| A teammate's chat with Clara | staff text desk, Ask Clara | person, lease, unit | Internal | – |
| Outside tool (Notion page, Drive doc) | a connector (section 4) | company, property | Internal | – |
Fede: "it is a very different mental model from the knowledge base that's meant to be public facing." And for v1: "Start with only two levels… Everything is internal, to simplify, because there's no privacy right now in the system, so everyone should see all the conversations." The two words are the ones shipped products use (research).
| Public | Internal | |
|---|---|---|
| Who can hear it | Anyone Clara talks to: prospects, tenants, staff | Every staff member of that company. Never tenants, prospects or another company |
| Examples | Pet policy, fees, parking, listings, office hours | Renewal terms the team agreed, a concession for one tenant, late-payment history, "owner selling in spring", a teammate's chat with Clara |
| Default for | Onboarding answers, the AppFolio sync | Everything else: meetings, emails, AppFolio notes, signals, staff chats with Clara, connectors |
| How Clara uses it | Quotes it | Decides with it; tells staff; never quotes it to a tenant |
| Becomes Public by | – | A person publishing it to Knowledge & policies |
| Shipped precedent | "Public" articles (Intercom), public comment (Zendesk) | "Internal" articles and notes (Intercom, Zendesk, Salesforce, Front) |
Private is reserved, not built. The audience field has room for a third value, Private (one teammate only, as in Notion, Claude Projects and Help Scout). Nothing writes it until a customer asks for it.
Invented example: Maria texts Clara "Unit 9 is on a payment plan" or forwards meeting notes; both land as Internal and every teammate's Clara sees them. "Pet deposit is $400 everywhere now" reaches prospects only once someone publishes it to Knowledge & policies; the quote stays Internal.
Also proposed: Clara reads the notes managers already keep on each property and home record, on the same 6-hour pull. Numbers and decisions: onboarding playbook, section 4b.
| Path | Cost | What it needs | When |
|---|---|---|---|
| (a) cc or forward Clara | Nothing new for the customer | Clara's mailbox per company (exists); a sender check; the extractor | First slice |
| (b) Listen-only join | Bot vendors charge flat, e.g. Recall.ai $0.50 per recording hour, no audio-only discount (Recall.ai). Audio saves mostly when we capture it ourselves: Zoom puts its no-bot feed at about $0.012/h to run versus $0.042–0.090 for a bot (Zoom). | A bot vendor or Zoom's feed; a consent notice when Clara joins | Decision 3 |
| (c) Video join | Tavus video minutes (video Clara page) | Keep the end-of-call transcript instead of dropping it | When staff want to ask Clara things live |
| (d) Paste or upload | Nothing | An upload box on the Internal page | Right after (a); same extractor |
Fede: "We serve small and medium businesses that already have their tools: Notion, Monday, Google Drive/Docs, Microsoft SharePoint/OneDrive… Connectors feed data into the company brain at the right privacy level." A connector is one more source in the framework above: it writes items, stamped with where they came from and an audience.
| Product | Word in the UI | Who connects | Sync or live | Audience |
|---|---|---|---|---|
| Glean | Connectors (docs) | Admin, company-wide | Indexed | Copies source permissions; a connector can be hidden from groups |
| Intercom Fin | Knowledge sources (docs) | Admin | Synced; some read live | Audience per source: internal vs the customer-facing agent |
| Microsoft 365 Copilot | Connectors, formerly Graph connectors (docs) | Admin | Scheduled crawls | "Only people with access" or "everyone in the organization" |
| Dust | Connections, placed in Spaces (docs) | Admin | Synced | Open or restricted space |
| Claude | Connectors, built on MCP (docs) | Org owner adds; users enable | Live | Whole-connector access |
| Notion AI | Connectors (Slack, Google Drive, SharePoint and more) | Workspace | Synced | Unverified (secondary source only) |
Common pattern: an admin connects a tool once for the whole company; most products sync and index, while MCP-based ones read live; the customer-facing bot only sees sources an admin marks for it. Sierra and Decagon document "integrations" but not their permission model (unverified). Our app already has Settings → Connections (AppFolio today); outside tools go on that same page.
| Framework | License, language | Notion / Monday / Drive / SharePoint / OneDrive | Keeps permissions | Self-hosted in our AWS |
|---|---|---|---|---|
| Airbyte connectors | Connectors MIT, platform ELv2; Python (low-code YAML) | All five (Monday, SharePoint, OneDrive, Notion, Drive); 600+ in all | Google Drive syncs file permissions and users and groups; SharePoint docs don't say (unverified) | Yes. Each connector is a container; the full platform needs Kubernetes and Postgres; connectors also run without it via PyAirbyte |
| Nango | ELv2; TypeScript | OAuth for 1,000+ APIs; you write each sync | No | Free self-hosting covers sign-in and proxy only; syncs need the paid Enterprise plan (docs) |
| Onyx (formerly Danswer) | MIT core plus paid Enterprise; Python | Notion, Drive, SharePoint and OneDrive; no Monday; 51 in all (docs) | Enterprise only: "Permission-syncing connectors are an Enterprise Edition feature" | Yes, but it brings its own search stack (Postgres, Redis, OpenSearch) |
| LlamaIndex readers | MIT; Python | Notion and Drive; others community | No | Library only; no scheduling or sign-in |
| Unstructured | Apache-2.0; Python | Four of five, no Monday | No | Yes; best as a document parser |
| MCP servers | Mostly MIT; mixed | Official Monday and Notion servers; Microsoft's are in its catalog; Drive is community-built | Reads as the signed-in account | Live reads only, not a sync |
Recommendation: Airbyte's open-source connectors, run in our AWS, for sync. MCP later for live lookups. They are the only option that covers all five tools Fede named under an open license, run entirely on our infrastructure, and already sync Google Drive permissions, which a future Private level could use. Nango is TypeScript, but self-hosted syncs need its paid plan, so we would still write every sync. Onyx lacks Monday and charges for permission sync. We run the connectors as containers from a Temporal job, not the whole Airbyte platform, and translate their output into items. That last step is ours to write.
get_internal_context.Each connection belongs to one company, under its org node, like lines, calendars and mailboxes in Gera's model. Turning a connector on at a customer is a new capability: a company setting, off by default, that Fede turns on.
The wall is structural, not a prompt instruction. Three layers, each enough on its own to stop a leak.
| Layer | Shipped precedent |
|---|---|
| ① Separate store | "A namespace per tenant avoids query-layer leaks; metadata filters are application-side only" (AWS); one namespace per tenant (Pinecone); cross-tenant leakage is OWASP's LLM08 (OWASP). |
| ② The customer-facing AI only gets the public audience | Intercom: an internal article has "Share with Fin" off, so Fin cannot answer with it (Intercom). Salesforce Agentforce grounds only on the channels it is allowed (Salesforce). Filter on the server from the verified caller, never the model (Cerbos, Auth0). |
| ③ Send check | From late January to mid-February 2026, one Copilot Chat bug summarized emails that sensitivity labels and data-loss rules should have blocked: one bug beat all three (The Register). |
remember command defaulted to shared regardless of settings (issue).Read from propflowai origin/main at 6ed1cbe8cf, 2026-10-02. Fede thought role-gated staff tools already exist: they do.
| Layer | Today | Change |
|---|---|---|
| ① Store | Company knowledge (knowledge.section.<id> on the org node) loads through loadOrgKnowledgeSectionsSafe → buildLeasingKnowledgeBlock into email and SMS (conversation-manager.ts, clara-unified.ts), voice (property_policies in api/voice/personalization/route.ts) and the get_property_details tool. No audience filter on any of these paths. | Internal items never become knowledge sections. They get their own key space and reader module, and an import boundary (a lint rule) stops the three knowledge paths from importing that reader. This is why a label on a knowledge row is not enough. |
| ② Door | composeCapabilities (agents/clara/lib/agent/capabilities/index.ts) composes tools from the caller. Staff capabilities exist: STAFF_METRICS (any staff sender), STAFF_LEASING_DESK and STAFF_PORTFOLIO (when deskGranted: staff line of the sender's own company plus a desk tier), MASS_COMMS (manager tier). Staff are verified in src/lib/domain/staff/inbound-resolution.ts. The dispatcher (tools/index.ts) refuses staff tool names without that context; handleStaffPortfolioTool re-checks the role on every call. Tenant and prospect turns never compose these. | A new capability with one tool, get_internal_context(scope), composed under the same staff check, added to the dispatcher's staff-only list, re-checking the role on every call. |
| ③ Send | No send-side check for knowledge. Data-layer precedent: isInternalAudienceRow strips internal rows (such as imported AppFolio guest-card notes) from Clara's conversation context (context-message-filter.ts, buildClaudeMessages). | Before any tenant- or prospect-bound send, compare the text against the Internal items for that scope (quote overlap); on a match, hold and alert. |
| Staff surfaces | Ask Clara: src/app/api/dashboard/chat/route.ts, scoped by getUserOrgScope and getUserPropertyScope. Staff text desk: staffLeasingDesk. | Both get get_internal_context. |
| Gap: staff → Public | escalation/teaching-capture.ts writes staff replies into knowledge.section.*, which is Public. | A staff reply about a named person or lease becomes an Internal item. Publishing stays an explicit act. |
| Gap: email from staff | A known staff email sender (senderIsKnownStaff) only suppresses leasing; it unlocks no staff tool. | The forwarding connector accepts a write only from an active staff sender of that company; otherwise anyone who learns the address could write Internal items. |
| What reads or copies the notes | Who sees the result | What keeps it in | Verdict |
|---|---|---|---|
| Notes store readers | Nobody in production (one sandbox test script) | Lint wall + planted-leak test | SAFE |
| Tenant, prospect and vendor prompts (email, text, voice, AppFolio relay, knowledge loaders) | Outsiders | No code reads notes or meeting transcripts; the planted-leak test goes red if the reader is wired in | SAFE |
| Digests, call list, team notices, reports | Customer staff | None of them read notes | SAFE |
| Where notes are stored (company record; no search index holds them; no page or API returns them) | – | Only the platform-admin delete tool reads the whole company record | SAFE |
| Clara's staff turn on the same email (it runs right after the note saves) | Prospects (texts, application links, tour changes), renters, staff | Sender must be verified staff; the “was Clara asked?” check is skipped when only Clara is on the email | RISK: transcript words can reach a prospect, and only Clara's own judgment stops them. Closed 2026-11-03: Fede said "delete"; the email intake is removed, so no email saves a note |
| Staff answer saved as public knowledge | Prospects later | The private-info check catches phones, emails and “confidential” only, not names, rents or court records | RISK (narrow) |
| Renewal decision from a staff reply | Tenant offer text | The concession is free text with no length cap. This route is fed by a staff reply, not by notes | RISK |
| Stage copy of production | Anyone with stage or preview access | Only known names, phones and emails were scrubbed | RISK → fixed in #24964; rows already on stage need a one-time purge |
| Video call thread, Langfuse traces, Tavus | Staff inbox; Propflow; vendors | Company only; vendor retention not checked | RISK, internal or vendor only |
| Clara speaking in an outside meeting | Anyone in the call | Only the organizer is checked; she can read company records out loud (records, not notes) | RISK (adjacent) |
| Lint wall | – | Caught plain imports only; a planted dynamic import and require() went through | Gap → fixed in #24961 |
Anthropic's guidance: "If your knowledge base is smaller than 200,000 tokens (about 500 pages of material), you can just include the entire knowledge base in the prompt" (Anthropic). Cached prompt reads cost a tenth of normal input (prompt caching). A company's Public knowledge is roughly 10k tokens (our estimate), so it stays in the prompt.
| When | Public | Internal | PMS records |
|---|---|---|---|
| Now | Whole, in the prompt, cached | Keyed lookup by scope through get_internal_context; the audience rule is in the tool layer, which tenant-facing Clara cannot bypass | Behind tools, never embedded |
| Next: meetings and emails pile up | Same | A staff-only search over free text: one index per company, never shared with any Public index, in our AWS account (S3 Vectors or Bedrock Knowledge Bases). Keyword plus meaning search with context added to each chunk if recall is weak; Anthropic measured a 67% drop in retrieval failures from that combination. Measured with Ragas-style recall plus the planted-leak test before it ships. | Behind tools |
| At 10k units | Same | Move to OpenSearch only if measured volume needs it; add reranking only if measured recall is low | Behind tools |
On a live call, free-text search stays off the critical path: the caller's own facts load at call start, as video Clara's snapshot already does (our inference, not a cited figure).
Checked against Gera's design. No conflict, with one gap.
Property.ownerId) grants no read access. Matches.Web research, 2026-10-02, two passes. Vendor docs linked inline; anything not confirmed from a primary page is marked unverified.
Same pattern everywhere: one library, an audience on each item, and the customer-facing AI limited to the public audience. Nobody says "staff only"; they say "internal".
| Product | Words | How it shows |
|---|---|---|
| Intercom Fin | "internal articles" vs "public articles"; a separate "Fin audience"; toggle "Share with Fin" (docs) | Audience setting per article |
| Zendesk | "internal note" vs "public comment"; article segment "Agents and managers" (docs, docs) | Internal notes on a yellow background; cannot be made private again once public |
| Salesforce | Publish channels: Internal, Customer, Partner, Public (docs) | Channel checkboxes per article |
| Front | "public" vs "internal" knowledge base (docs) | Internal needs a Front login |
| Help Scout | "Private" collections; Notes vs Replies (docs) | Lock icon on private collections |
Kept for when Private is built. v1 has no Private level.
| Product | Personal | Shared | Becomes shared by |
|---|---|---|---|
| ChatGPT | Saved memories | Projects, with project-only memory | Putting it in a shared project (docs) |
| Claude | Memory summary; "Private" projects | Projects visible to "Everyone at your organization" | Adding it to a shared project (docs, memory) |
| Notion | Private pages | Teamspaces: Open, Closed, Private | Moving the page to a teamspace (docs) |
| Glean | Memory, per user only | Company knowledge, permissions copied from each source | Never: memory does not cross users (docs) |
| Microsoft 365 Copilot | Saved memory | Copilot Pages and Notebooks | Saving to a page (docs) |
| Dust | Unpublished agent | Spaces, open or restricted; "Company Data" | Publishing, or placing it in a space (docs) |
| GBrain | private | world; team brains mounted beside a personal one | Writing to the team brain or marking it world (docs) |
One database per data owner, holding typed pages (person, company, meeting, email, deal and more). Each page has a rewritable "compiled truth" over an append-only timeline where "every claim cites its source". Pages and facts are world or private; remote agents get read, write or admin scopes; derived pages are treated as private by default (issue). Its people pages include an "Assessment" section, the same kind of staff judgment we keep Internal (schema). Young (April 2026), single author, active leak fixes.
Rent recommendations: RealPage's rent-pricing settlement (Federal Register, 2026-01-21) makes pooled rent advice sensitive. Here every increase comes from that client's own team, and the per-company wall means one client's decisions never inform another's rent.
Recommendation: copy patterns; adopt no framework now. None gives an audience wall or hard per-company isolation; most are Python, while we run TypeScript on DynamoDB, S3 and Temporal; and Zep needs its own cloud, so customer data would leave our infrastructure.
| Project | Runs on our infra? | Audience wall? | What we borrow |
|---|---|---|---|
| GBrain | Yes (Postgres); the Supabase option is a third party | Per-page private flag; has leaked through links and counts | Pages per entity, compiled truth over a cited timeline, private-by-default derived pages |
| Graphiti | Yes, with a graph database we don't run | None | Valid-from / valid-until on facts. Optional later layer if supersession gets hard |
| Zep | No: needs Zep Cloud | Unverified | Nothing |
| mem0 | Yes as a library; hosted by default | None (user/agent ids only) | Nothing beyond scope ids |
| Onyx | Yes | Permission-aware connectors (paid tier) | Considered for connectors in section 4 |
| GraphRAG, LightRAG | Yes | None | Nothing: built for themes across a whole corpus, not "what did we decide about 4B" |
Letta, Cognee, Supermemory, Basic Memory and Memori were also reviewed; none adds an audience wall. Letta's details are unverified.
Rejected (Fede, Oct 4): "I didn't like the options… I don't want to build a UI yet." No notes screen for now; notes are checked by the team on request. Kept below for the record.
Design only; no UI is built. Fede, Oct 4: "give me a prototype doc of where these notes would fit in and how they will look." The mockups copy real screens on origin/main: Gera's Settings area (left menu, the Company | Property header row, Knowledge & policies), the tenant page and the renewal page.
The transcript keeps speech-to-text slips ("you need" for "unit", "release" for "lease"), so the collapsed view shows Clara's own recap. Who sees it: everyone on the company's team (Settings › Team) in v1. Property owners are not staff and need their own grant (section 7). Prospects and residents never. Notes sit on the company's own record, the wall in Gera's model. Remove works like on the Company knowledge cards (a note is never rewritten); nothing to approve.
For: one page for everything Clara knows. Against: breaks this page's own rule, "a screen shows one audience." A Public entry and an Internal note one scroll apart invites pasting into the wrong one.
For: one audience per screen; sits in Gera's menu, where the customer's team already looks; works with today's one-piece notes. Property tab hidden, as Gera does on Company-only pages. Against: one more menu row, and notes are records, not settings (Knowledge & policies already sets that precedent).
The same card fits the tenant page's right column, under "Also on file." For: staff see it where they act. Against: it needs each meeting split into one line per lease. Today's note is one piece with no unit, and the Camellia test could not tie 1 in 6 notes to one lease. So C is a later view on top of A or B, not a home.
B now, C later. One audience per screen, in the menu the customer's team already uses, and it works with notes as they are stored today.
Static mockups, modeled on the app's real Settings screens and labels. The chips copy Intercom's internal-vs-public audience. People see and edit what Clara knows; there is nothing to approve (Fede, 2026-09-08: the engine decides, humans fix the engine).
"Knowledge & policies", "Connections", the subtitle and the menu order are today's real ones.
renewal.term = month_to_monthThe panel's summary line over the item list is GBrain's compiled truth over its timeline. Today's AppFolio note row in conversations says "Only your team sees this; Clara never does." Under this design staff-facing Clara does read it, so that line becomes the Internal chip: "Internal · Clara uses it to decide, never shares it with tenants."
Fede's pilot (2026-10-02): basic leasing questions plus renewals. Basic leasing questions are answered from Public, as today. Renewals are the first workflow that reads Internal.
Dana pays on time, so both renewal checks pass and Clara sends the standard 12-month offer. On Tuesday the team had agreed: "Pine Court 12, the owner is selling in spring, month-to-month only." Nobody told Clara. Staff walk the offer back.
Before the first letter, the renewal workflow reads the Internal items on Dana's lease, home and building. It finds Maria's decision from Tuesday, with the quote and minute, and offers month-to-month instead. The letter says nothing about why. Had the note been unclear, Clara would hold that one step and ask Maria.
In client meetings Clara gathers which tenants to renew, how much to increase, whether to offer a renewal at all, and who moves to month-to-month. Each becomes an Internal item with a renewal effect.
| Field | Example (invented) |
|---|---|
| What was decided | Offer Pine Court 12 month-to-month only this cycle; the owner is selling in spring. |
| Effect | renewal.term = month_to_month, from the renewal workflow's fixed list (below). |
| Scope | Lease: Pine Court 12, current lease. |
| Audience | Internal. |
| Who decided | Maria, property manager, matched to her staff record at that company. |
| Source | Renewals meeting notes, Tue 2026-09-29, 14:32. Quote: "Twelve, let's just do month-to-month, he's selling in the spring." |
| Validity | Ends with this renewal cycle. A later item on the same lease and topic replaces it; the old one is marked superseded and kept for audit. |
| Confidence | High: stated as a decision, not a question; scope matched exactly one lease. |
An item whose effect is not on the list is still context, but at that step Clara asks the team instead of improvising. Every other workflow declares its own list the same way.
A keyed lookup, not a search. At a check point the workflow asks for active items on this lease, the people on it, the unit, the building and the company. A handful of items, one or two database reads. Each workflow declares its own check points; these are the renewal workflow's.
pre_first_contact, already a declared check point). The first slice reads only here.at_offer_acceptance).| Where | Latency budget |
|---|---|
| Background work (renewals) | Up to 1 s added per check. Nobody is waiting. |
| Live staff call or text | Loaded once when the conversation starts; under 50 ms per turn after that. |
Each check writes down which items it used, so a later replay shows why Clara did what she did. When unsure (two items contradict, an effect not on the list, a scope that didn't match), Clara holds that one step and asks the person who made the decision, with both quotes. Everything else keeps moving.
Luis pastes owner call notes: "No new pets at Willow Row from November." It lands as an Internal item on the building, and Clara uses it at once with staff. Prospects hear it only once Luis publishes it to Knowledge & policies (Intercom's audience toggle is the model). Until then, if it contradicts a Public entry, Clara tells Luis the public policy is out of date.
A nightly job sees four leak work orders on Unit 7 in 60 days and writes an Internal signal on the unit. The next time the tenant reports a leak, maintenance triage reads it and routes the call to the property manager instead of booking another routine visit. The tenant hears "I'm getting your manager involved today," never the count.
What nobody ships for us (everything else has a product or pattern to copy):
First slice (Fede: "I'm not saying go build the whole thing"):
pre_first_contact, with the effect list above.get_internal_context(scope) on the staff text desk and Ask Clara.Emails, AppFolio notes, signals, meetings and outside-tool connectors come later as new connectors, not a redesign.
TL;DR: a person publishes Internal to Public (recommended); connectors run on Airbyte's open-source connectors in our AWS (recommended); listen-only joining waits for v2 (recommended); raw evidence lives 13 months (recommended).
1. How does an Internal item become Public?
A) Only when a person publishes it to Knowledge & policies, as Intercom, Zendesk and Salesforce do. B) Clara publishes it herself when a staff member states a company-wide rule ("pet deposit is $400 everywhere"). No shipped product does this.
Recommend A. Nothing reaches tenants by accident. It needs no approval buttons: publishing is one plain request to Clara or one toggle on the item.
2. Which connector framework?
A) Airbyte's open-source connectors (MIT), run as containers in our AWS from a Temporal job; MCP later for live lookups. B) Nango (TypeScript), but self-hosted syncs need its paid Enterprise plan. C) Onyx, which brings its own search stack, has no Monday connector and charges for permission sync. D) Write each connector ourselves.
Recommend A. It covers Notion, Monday, Google Drive, SharePoint and OneDrive today, customer data never leaves our AWS, and Drive permissions come with it for a later Private level.
3. Listen-only meeting join: v1 or v2?
A) v1, alongside forwarded notes. B) v2, after forwarded notes prove the extractor. C) Skip it; use video join only.
Recommend B. Forwarded notes cost nothing and prove extraction first. Bot vendors charge the same for audio as for video, so listen-only saves money only if we capture audio ourselves.
4. How long does raw evidence live?
A) 90 days. B) 13 months. C) As long as the customer is with us.
Recommend B. It covers a full lease cycle, so a renewal item can be traced to its quote. Items keep their quote after the evidence is gone.
Proposed: raw evidence for 13 months; items while valid plus 13 months for audit. A customer can delete a source, and its items go with it. See decision 4.
| Risk | Answer |
|---|---|
| An Internal item reaching a tenant | Three layers: separate store, no tool on tenant turns, a send check. Plus the planted-leak test. No prompt rule carries weight. |
| Leaks through derived things (summaries, counts, links) | Derived things inherit the most restricted audience of their inputs (GBrain's lesson). |
| Staff replies becoming Public (today's teaching capture) | Person- and lease-specific replies become Internal items; publishing stays an explicit act. |
| Acting on a misheard or half-made decision | Quote required; questions and what-ifs skipped; scope must match exactly one record; recap to attendees; hold and ask when unsure. |
| Fair housing | A reason resting on a protected class never becomes an action. That screen is code, not a prompt instruction. |
| Colorado non-renewal law | Not renewing needs cause (HB 24-1098). The statute floor already computed on every renewal stays in charge; "don't renew" holds the renewal for the team rather than sending a notice. |
| Rent advice across clients | Increases come from each client's own team; nothing is pooled across companies. |
| One company's items reaching another | A P0 leak. Prevented by the company wall in storage and at the edge, not by instructions to the model. |
| Someone emailing Clara's mailbox to plant items | Only active staff senders of that company can write; items are data, never instructions; effects come from a fixed list and rent stays within policy. |
| Stale items | Default lifetimes; superseded items kept for audit but never read as active. |
| Recording consent | Some states require everyone's consent. Clara says she is taking notes when she joins. Meetings with outsiders are out of scope in v1. |
| Sliding back into a review queue | The recap is meeting notes, not an inbox. No buttons. |
Read from propflowai origin/main at 3887385435 and 6ed1cbe8cf, 2026-10-02. The wall's code locations are in section 5.
| Piece | Today | Brain impact |
|---|---|---|
| Company knowledge | Org-node settings knowledge.section.<id>, composed with the property's sections (property wins by title) through loadOrgKnowledgeSectionsSafe into the leasing knowledge block every turn. | Public, read through the item contract. |
| Building facts | PropertyKnowledge.pricingDetails rendered by property-knowledge-block.ts. | Public, unchanged. |
| Listings and availability | AppFolio vacancy report by id; listing price for prospects. | Public, unchanged. |
| Renewal rules | RenewalPolicy rows per property, append-only: thresholds (maxBalanceMonths 2.0, maxLatePayments 2, lateGraceDays 10 by default) and facts (rent strategy, term options, month-to-month premium). | Items override offer facts per lease and cycle; thresholds untouched. |
| Renewal decision | evaluateRenewalPolicy: pure, two gates, AUTO_RENEW or HITL_REVIEW. Colorado statute floor computed alongside. | Engine stays pure. Effects become inputs: "hold" maps to held_review; "renew anyway" is an explicit input with its item id, recorded on the verdict. |
| Renewal workflow (Temporal) | Pins {organizationId, propertyId} at start; declared check points pre_first_contact and at_offer_acceptance. | The first slice reads at pre_first_contact. |
| Notes on leases | No notes field on Tenant, Lease, Renewal, RenewalSaga or RenewalSnapshot. | Lease-scoped Internal items fill this. |
| AppFolio guest-card notes | Imported as internal conversation rows; filtered out of Clara's context by isInternalAudienceRow. | A later connector: imported as Internal items. |
| Tavus end of call | /api/video-clara/calls/ended treats application.transcription_ready as an end signal only; the body is never stored. | With the setting on, keep the transcript as evidence under the call's company. |
| Ask Clara and the staff text desk | Dashboard chat tools scoped by org and property; staff desk tools gated by deskGranted. | Both get get_internal_context. |
Proposed storage, for review: PK = ORGINT#<orgId>, SK = ITEM#<scopeLevel>#<scopeId>#<validFrom>#<itemId>, plus a lookup by (orgId, scopeId). The audience attribute leaves room for a reserved Private value keyed by person id; not built. Raw evidence in S3 under a company prefix, referenced by id from each item.