The most-asked question in real estate FP&A right now is: “Can an AI write our variance commentary?” The honest answer is yes — with a very specific architecture. This is the playbook we use in production for Yardi Voyager operators, including what the prompt looks like, what retrieval strategy grounds the model, and the three guardrails that separate a usable output from a fabricated one.
The job, stated precisely
A variance memo, at its best, answers four questions for a finance or asset-management reader:
- How did we do vs. budget? (One sentence, with the NOI variance number.)
- What explained it? (The concentration analysis — which 2–3 properties and which 2–3 GL accounts account for most of the variance.)
- What should I worry about? (The watch items — things trending in the wrong direction that aren’t yet catastrophic but will be if ignored.)
- What should I do? (The recommendation — a tangible next action.)
That’s it. A great variance memo is four paragraphs. The mistake most AI-commentary attempts make is trying to be exhaustive. The model rattles off every property, every GL, every number, and the human reader tunes out by paragraph two.
The retrieval architecture
The memo is grounded in your warehouse, not pasted into the prompt. Here is the retrieval structure we use in production:
For each portfolio × period:
Step 1 — compute the analytical layer (SQL)
- NOI variance by property (deterministic aggregation)
- Driver decomposition by GL category per property
- Concentration metrics (top-N contribution)
- AR aging trend (3-month rolling)
- Occupancy trend (3-month rolling)
Step 2 — compute the prompt context (structured)
- Top 3 favorable properties with top GL driver each
- Top 3 unfavorable properties with top GL driver each
- Portfolio total, concentration ratios
- Flagged watch items (trend-direction triggers)
- Prior-period commentary (for tone anchoring)
Step 3 — prompt the model with the context (JSON)
- System: role = senior FP&A analyst for mid-market multifamily
- Tool: SQL query tool, scoped to this portfolio + period
- User: "Draft a four-paragraph variance memo for {portfolio}
covering {period}. Use the analytical context below.
Cite specific properties and GL accounts. Do not invent
numbers. If a driver is ambiguous, say so."
- Context: the JSON payload from Step 2
Step 4 — validate the output
- Every $ number in the draft must reconcile to the analytical
context within rounding tolerance
- Every property name must exist in the warehouse
- Every GL account named must exist in the portfolio
- Any number that fails validation triggers a regeneration with
a "you referenced a number not in the context" instruction
Three design choices drive everything:
-
Deterministic analysis first, language last. The model does not compute anything. SQL computes everything. The model narrates. This is the single most important rule for finance-grade output.
-
Tight context, no bulk upload. We do not dump the full GL into the prompt. We dump the analytical summary — maybe 2–4K tokens total — so the model has exactly what it needs to narrate the top drivers without being distracted by noise.
-
Tone anchoring from your prior memos. We pass the last 2–4 variance memos the operator has actually written (or quarterly letters, if commentary is new). This teaches the model the operator’s voice — short, long, adjectival, spreadsheet-dry — without having to specify it explicitly.
The prompt we ship
Roughly (omitting the structured JSON context block and the tool definition):
System: You are a senior FP&A analyst for a mid-market multifamily operator on
Yardi Voyager. You write variance commentary for the CFO and VP of Asset
Management. You are precise. You name properties and GL accounts. You do not
invent numbers. You call out concentration when two or three properties drive
most of the variance. You flag items that are trending in the wrong direction
before they become crises. You write in the operator’s prior-memo tone.
User: Draft the April 2026 variance memo for {portfolio}. Four paragraphs:
1. Portfolio headline — NOI variance vs budget, one sentence.
2. Concentration — which properties drove it, with the top GL driver for each.
3. Drags — which properties dragged, with the top GL driver for each.
4. Watch items or recommendation — what the reader should do next.
Analytical context (authoritative — do not contradict these numbers):
{structured JSON payload from retrieval step}
Prior memos (for tone anchoring only — do not reuse their facts):
{last 2 memos}
This prompt, paired with the retrieval layer above, produces first drafts our clients forward to ownership without edits in ~60% of cases, with minor human editing in the remaining 40%. That ratio has held across pilots.
The three guardrails that keep the model from fabricating
An unguarded LLM will confidently tell your CFO that the pool heater at “Magnolia Pointe” blew a gasket if you give it an opening to invent a cause. Three guardrails keep this from happening:
Guardrail 1: Reconciliation against the deterministic layer
Every dollar-amount mentioned in the output is extracted from the text and cross-checked against the analytical context. If the model writes “Waverly Peaks was +$61K” and the warehouse says +$58K, the output is rejected and re-generated with a tighter instruction. This is unglamorous engineering and it is the single largest reason our output is usable.
Guardrail 2: Entity whitelist
Every property name, GL account, and category in the output is checked against the warehouse. If the model invents a property (“The Grove at Ridgeview”) we reject. If it invents a GL account (“6298 — fountain chemistry”) we reject. This catches the confabulation class of error.
Guardrail 3: Causal language throttle
Variance commentary has a natural tendency toward “X caused Y” language. For an AI output, causality is claims-you-can-support territory. We filter for causal verbs and soften them toward “was driven by” or “coincided with” unless the analytical layer itself has surfaced the cause (a specific R&M line item tying to a specific property, for example). This makes the prose slightly more hedged than a human analyst would write, but it stops the model from confidently narrating causes it doesn’t have evidence for.
Why Yardi Virtuoso won’t ship this in 2026
Yardi Virtuoso, and its Anthropic Claude connector that went live in late 2025 / early 2026, is going to answer many Voyager questions. It will not, in 2026, ship production-quality variance commentary. Three reasons:
-
Yardi’s buyer for Virtuoso is IT, not finance. Virtuoso’s roadmap prioritizes operations — leasing chatbots, invoice approvals, document abstraction. The finance-narrative use case is real, but not where Virtuoso product is staffing.
-
The grounding architecture is different. Virtuoso grounds in Voyager through the sanctioned connector. That’s perfect for operational answers. For finance-grade narrative, you want retrieval over a dbt-modeled warehouse — because GL normalization, budget-vs-actual at the GL level, and concession-accrual accounting all live in the modeling layer, not in raw Voyager tables.
-
Tone anchoring is a per-operator concern. The narrative your operator ships sounds like your operator. A platform-level Virtuoso feature won’t hit that in the first two years — they’ll ship a reasonable default, and your CFO will want it to sound more like them, and there won’t be a clean knob to turn.
We expect Yardi to solve (1) and (2) over the next 2–3 years. That is the window Memowright is built for.
How to start
If you want to try AI variance commentary on your own Voyager data:
- Run the Memowright live demo on a sample or your own CSV (60 seconds, no signup).
- Read the Yardi Data Warehouse Architecture Guide to understand the retrieval layer.
- Book a 30-minute gap review if you want an honest read on whether your reporting stack is ready for this.
And if you build this in-house, don’t skip the three guardrails. The difference between “our AI writes variance memos” and “our AI writes variance memos we actually send to ownership” is almost entirely in the validation layer.
Related reading