CLO Dashboard Copilot — Compliance AI
Context
A CLO (collateralized loan obligation) compliance and portfolio-management SaaS, built on Laravel, React and MySQL, wanted a Dashboard Copilot: a conversational layer that answers questions about the portfolio directly from the data already in the platform. This is an ongoing engagement.
The Hard Part
In a compliance context a confidently wrong answer is worse than no answer at all, so retrieval is restricted to approved database data and every response has to be grounded in what was actually retrieved rather than generated from the model's own recall.
What I Built
- Azure OpenAI Dashboard Copilot over the existing Laravel, React and MySQL platform
- RAG-style retrieval architecture scoped to approved database data only
- Structured context payloads assembled per question before the model sees them
- Grounded answers constrained to retrieved data, so the copilot does not hallucinate
- AI guardrails bounding what the copilot will attempt to answer
- Token and cost control on every request
The Build
The answers already exist; asking is the expensive part
A compliance and portfolio-management platform is not short of information. Everything a user wants to know about the portfolio is already in the database, rendered across dashboards built by people who knew exactly which questions mattered when they designed them.
The cost is in asking anything else. A question the dashboard did not anticipate means knowing which screen holds the relevant figure, how to filter it, and how it relates to another number on a different screen — a skill that lives with the people closest to the system. Everyone else either learns to navigate it, asks a colleague, or does without the answer. A conversational layer over the same data lowers that cost to typing a sentence.
What makes this hard is the asymmetry underneath it. In most products a wrong answer is a defect to be fixed in the next release. In a compliance context a confidently wrong answer is worse than no answer at all, because it is acted upon — an unanswered question costs somebody a few minutes, while a plausible wrong one enters a decision and is not questioned again. That single fact determines the entire architecture, and it is the reason this is not simply a chatbot pointed at a database.
Why "grounded" has to mean something specific here
Retrieval is restricted to approved database data, and every response has to be grounded in what was actually retrieved rather than generated from the model's own recall. That second half is the stricter requirement and the easier one to underestimate.
A capable model knows a great deal about the domain in general. It can describe how these instruments typically behave and what such portfolios usually contain — and all of that plausible general knowledge is exactly what must never appear in an answer about this portfolio. The failure mode is not the model inventing something absurd, which anyone would catch. It is the model supplying a reasonable industry-standard figure where the platform's own data says something different, phrased with the same confidence as everything else it says.
The retrieval problem is also unlike the usual document case. The source is a relational database rather than a corpus of prose, so relevance is not a similarity question but a query question: answering correctly means knowing which tables and which filters bear on what was asked. That has to be decided by code that understands the schema, not inferred by a model reading text.
Two further constraints shape the work. This is a copilot retrofitted onto an existing Laravel, React and MySQL platform rather than a greenfield build, so it has to work against a schema designed for dashboards rather than for retrieval. And a conversational surface has unbounded usage by construction — every user can ask anything, at any length, as often as they like — which makes cost a design concern rather than something to review at the end of the month.
Deciding what the model is allowed to see
The architectural centre of this is that structured context payloads are assembled per question before the model sees them. The copilot does not have access to the database. It receives a curated payload, and everything outside that payload does not exist as far as the answer is concerned.
That inversion is what makes the grounding requirement enforceable rather than aspirational. Instructing a model to answer only from provided context is a request it can fail to honour; giving it nothing else to draw on is a property of the system. It also means the retrieval decision — which data is relevant to this question — stays in deterministic code that can be read, tested, and reasoned about, rather than being delegated to the least predictable component in the stack.
The guardrails bounding what the copilot will attempt are the same principle applied to scope. A system that answers everything will eventually answer something it should have declined, so the set of questions it takes on is defined rather than open-ended. Declining is a designed outcome here, not a failure state — which follows directly from the premise that no answer beats a wrong one.
Token and cost control on every request closes the loop. Bounding the assembled payload limits spend, and it also improves answers: a smaller, well-chosen context is easier for a model to use correctly than a large one where the relevant fact competes with everything shipped alongside it. The two goals point the same way, which is unusual and worth taking advantage of.
Why there are no numbers on this one
This case study carries no metrics, for two honest reasons. It is an ongoing engagement rather than a completed one, so any figure quoted now would describe a moment rather than an outcome. And the result this system is built for is negative in form: the confidently wrong answer that never reached a compliance decision, the question it declined instead of guessing at, the industry-standard number that never got substituted for the portfolio's actual one. None of that produces a measurement, and manufacturing one would contradict the discipline the project is about.
What can be stated is what the system refuses to do. It does not answer from the model's own knowledge, it does not reach data outside the approved set, it does not attempt questions outside its defined scope, and it does not run without a bound on what each request costs. For a copilot in a compliance setting, that list of refusals is a more meaningful description of the work than any throughput figure would be.
Tech Stack
More Case Studies
Have a similar project?
I would love to help you build something great. Let's discuss your requirements.