Building the First Tool in an AI Portfolio Management System
Translating one step of quarterly investor reporting into a repeatable technical workflow.
1. Why I did it
Leading a company sometimes requires getting close to the work—not to replace the specialists, but to understand the process well enough to lead it thoughtfully.
In my work at Front Office Labs, our Head of AI and technical team build the AI systems. My background is in institutional real estate. I undertook this exercise to understand firsthand how a real portfolio-management workflow becomes a functioning AI/technical tool. I worked with the AI team on this - starting with: what must be defined, translated, tested, and refined along the way.
My result is a real portfolio-management task translated into technical instructions and built into a working tool for one our family office clients. The work below represents one of 40+ tools that were implemented and are still in-use for this family.
2. Mapping the full portfolio management function first
We’d already mapped the portfolio-management function—the recurring work, what it runs on, the judgment calls it involves, and what investment committees, family principals, and senior management expect to see. From that map I picked one recurring workflow: the quarterly investor report.
3. Break the workflow into steps
Like all workflows in institutional real estate, producing a high-quality quarterly report is a chain of many small tasks and subtasks, each with its own inputs, controls, and stakes:
- Gather the current-quarter materialsBring together rent rolls, Yardi financials, loan documents, current valuations, and other reporting-period evidence.
- Identify and categorize the filesDetermine what each file is so the system can route it to the correct extraction rules, validation checks, and downstream steps.Selected for this build
- Extract the relevant informationRead the defined fields needed from each document type to support the quarterly report.
- Validate against other sourcesCompare overlapping facts across documents and surface differences for review.
- Investigate inconsistenciesThe portfolio manager resolves discrepancies with the property or asset manager and documents the answer.
- Populate the quarterly reportMove approved current-quarter figures into the appropriate report fields.
- Draft commentaryDevelop clear explanations of performance, material changes, and emerging risks.
- Review and approveThe portfolio manager reviews the complete report from top to bottom before it is issued.
Why this matters: To a portfolio manager, labeling a rent roll as a rent roll can feel almost pointless—the document is recognizable at a glance. A computer does not begin with that context. It must first know what kind of document it is looking at before it can know which information to extract, what to compare it against, or where that information belongs in the report.
That classification tells the computer how to treat the file from that point forward and determines every subsequent step. A folder with all of the files needed for a quarterly report may contain hundreds of files, with each property or asset manager using different naming conventions for all of their submissions.
In many cases, "what" the file is cannot be identified from its name or format alone; it has to be opened and read. That takes time a mental bandwidth away from a portfolio manager who is digging around in the folder looking for a loan agreement at a particular property.
Classifying the files at the outset saves that manual effort later and gives every downstream tool the instructions it needs to process each file correctly.
4. Build the first tool
The tool reviews the current-quarter folder and categorizes its contents. Those contents may include:
Even this simple-looking step involves real judgment. File names aren’t consistent, and formats vary across property managers, operating partners, assets, and reporting periods—a spreadsheet might have half a dozen tabs, a PDF might be scanned, an email screenshot might carry a real update with no useful metadata attached to it at all.
So the system can’t rely on filenames—it has to look inside the file and recognize what a document actually looks like. A portfolio manager can spot a rent roll almost on sight. But without categorizing and re-naming files, a portfolio manager might need to open a lot of different files before they find the rent roll they specically need.
Making that recognition repeatable means spelling out what the code (or in this case, AI harness) is actually looking for: tenant or unit identifiers, lease dates, square footage, rental amounts, and how those fields relate to each other. This info is used to determine the most liekly file type and property type.
5. The actual build
Here is the working version, reduced only to remove internal paths and client information. The sequence is straightforward: validate the file, convert its contents to Markdown, combine that content with a tightly bounded system prompt, and send both to the model at temperature zero.
Security note. The API key never appears in the script. It is stored as an environment variable named GROQ_API_KEY. The public example also uses a generic filename rather than an internal folder structure.
from pathlib import Path
from markitdown import MarkItDown
SUPPORTED = {".pdf", ".xlsx", ".pptx", ".docx", ".md"}
def convert_to_markdown(file_path: str) -> str:
path = Path(file_path)
if not path.is_file():
raise FileNotFoundError(path)
if path.suffix.lower() not in SUPPORTED:
raise ValueError(f"Unsupported file type: {path.suffix}")
if path.suffix.lower() == ".md":
return path.read_text(encoding="utf-8")
return MarkItDown().convert(str(path)).text_contentThe conversion step gives the model the document’s actual contents, not just its filename. For a spreadsheet, that means labels, tabular fields, values, and sheet context become readable text.
Categorize the following content into one of the following file categories:
A) Rent Roll
B) Prior Q rent roll
C) Signed Loan Agreement
D) Mortgage Statement
E) Fixed property data
F) Valuation file
G) Prior Q valuation file
H) Financial statement
I) Prior Q financial statement
J) Last quarter’s report
K) Email
L) Brokerage report
M) Other
Return only the file category and nothing else.This was the complete prompt for the first prototype. Its job was deliberately narrow: force the model to choose one label from a fixed list. It did not yet produce confidence scores, supporting evidence, or exception flags.
import os
from groq import Groq
def classify(markdown: str, prompt_path: str) -> str:
api_key = os.environ["GROQ_API_KEY"]
system_prompt = Path(prompt_path).read_text(encoding="utf-8")
client = Groq(api_key=api_key)
response = client.chat.completions.create(
model=os.getenv("GROQ_MODEL", "openai/gpt-oss-120b"),
temperature=0,
messages=[
{"role": "system", "content": system_prompt},
{"role": "user", "content": markdown},
],
)
return response.choices[0].message.contentpython test.py sample_rent_roll.xlsx \
--prompt fol_file_categorizer.mdFor an illustrative office rent roll, the response looks like this:
A) Rent RollThis is intentionally not “upload a folder and ask AI to write the report.” It is one inspectable component with a defined input and constrained output. The limitations are equally visible: the first version does not explain its answer or identify uncertainty. A production version should add structured output, evidence, an exception path, source-file and prompt-version logging, and tests against a labeled document set before downstream use.
6. Where it fits
The file-classification tool is one small component of a larger system:
This first tool isn’t producing the quarterly report itself. It’s setting up an organized, traceable input layer that later tools can build on—the layer that ties every extracted fact, and eventually every conclusion, back to a specific source.
7. What I learned
The exercise made several principles of institutional AI implementation more concrete:
The hardest part is defining the work precisely. Coding doesn’t start until the objective, the evidence, the classifications, the edge cases, and what counts as an acceptable output are all spelled out.
A workflow that looks obvious is full of implicit decisions. Experienced portfolio managers resolve inconsistencies without even noticing; a system needs those judgment calls pulled out into the open.
File classification establishes provenance—it’s not paperwork, it’s the foundation. Every extraction, variance, and written conclusion downstream should trace back to an identifiable source.
Reliable automation depends on narrow, testable components. A bounded tool can be checked, corrected, and supervised in a way an open-ended request never can.
Domain experts and engineers need a shared way of describing the process. Workflow maps, classification rules, expected fields, and exception paths are what give them a common language.
Executive leaders need real technical fluency. Not enough to build every tool themselves, but enough to tell a demo apart from something that can actually run as an institutional operating system.
If there’s one lesson that keeps showing up, it’s that reliability comes less from the model and more from what’s built around it: narrow scope, explicit rules, traceable evidence, visible uncertainty, human approval.
8. What comes next
- The next tool extracts defined information from each file.
- Later components validate and reconcile the extracted information across conflicting sources.
- Approved data can eventually populate defined fields within the quarterly report.
- The portfolio manager remains responsible for interpretation, materiality, and final communication.
The system gets built from the function outward, one narrow and accountable piece at a time.