The build
What You’d Have to Build
Here’s what it takes to build a good, accurate, reliable customer knowledge graph. We know because we built one.
| The problem | How we handle it | Why it matters |
|---|---|---|
| Phase 1Getting the data in clean | ||
| Making every source legibleCalls, emails, tickets, Slack, and docs all arrive bloated — HTML, quoted replies, signatures, large attachments, and duplicate copies of the same message or meeting. Fed to a model raw, all of that inflates token cost and blows past context windows. | We clean and compress every source on ingest: strip noise, spot exact and near-duplicate records across sources, extract what matters from attachments, and shrink transcripts, all without losing meaning. | It’s the difference between a query that costs cents and one that costs dollars, on every call. |
| Taming messy sourcesEvery source we ingest has its own version of this mess, and each one needed its own fix. Email brings HTML bleeding into plain text, bounce tags wrapping real addresses, and the same attachment reprocessed on every reply. Slack brings edited messages and threads buried inside threads. Call transcripts bring crosstalk and speakers attributed to the wrong person. Support tickets bring merged conversations and canned replies logged as if they were real answers. | We built fixes for each source, one at a time, and we keep tuning them as new edge cases show up. This work has been going on for years and it doesn’t fully stop. | Get one source wrong and that mistake shows up in every answer that touches it. Email is usually the worst offender, but the same risk exists in every source we pull from. |
| Knowing who is whoThe same person or account shows up under different names, emails, and IDs across your CRM, calls, and email. A meeting host matches no one in your system. The same call, recorded by two different tools, becomes two separate meetings instead of one. | We match people and accounts across every source, catch near-duplicate records, and flag any mismatch instead of guessing. When something can’t be matched with confidence, we surface it for a person to review instead of silently dropping it or filing it under the wrong account. | We tested what happens without this kind of matching: a tool working from raw data flagged 11 accounts as gone quiet, and 9 of those 11 were wrong. That same tool also missed 5 of the 7 accounts that had actually gone quiet. |
| Phase 2Making it usable by a model | ||
| Making answers reproduciblePoint a model at raw data and it samples differently each run. The same prompt can produce a good answer one day and a wrong one the next. | We pre-join and pre-process the data into stable, reusable results, so the same question returns the same answer every time. | People stop trusting a tool the moment they can’t reproduce their own results. |
| Giving raw data structureRaw data is an undifferentiated pile. To answer a question like “what’s urgent this week” or “show me product feedback,” something has to label each item as it comes in. | We categorize and score every item for type and urgency on ingest, so a model can filter for what it needs instead of re-reading everything. | Without that labeling, every question re-scans everything. That’s slow, expensive, and it gives inconsistent answers. |
| Letting the model reach for dataYou can’t just hand a model your entire dataset. A model needs a way to ask for exactly what it needs — by account, person, topic, or time. Without that, a model pulls a random sample and makes up the rest of the answer. | We give the model scoped, tuned ways to reach for exactly the data it needs, so it asks correctly instead of grabbing everything at once. | Done poorly, a model either can’t find what it needs or drowns trying to sort through too much. |
| Keeping answers honestLeft unmanaged, a model can log your own team’s internal chatter as a customer “win,” wrap a real answer in formatting junk, call a working feature broken because of one offhand word, or drop valid data because of a small parsing error. | We continuously tune how the model pulls out, sorts, and formats information, and we’ve built in checks so the model doesn’t invent an answer when there’s nothing there to support one. | We ran this test too: we asked a model without these checks who a customer’s biggest competitor was. The model named the wrong company with full confidence, and dismissed the real competitor as “just a data source.” |
| Phase 3Answering the question | ||
| Turning clean data into an answer you can trustEven with clean, well-structured data behind it, most tools still make you write a new prompt from scratch every time, and they never explain how they landed on an answer. If you can’t see the method behind an answer, you can’t tell if it’s right, and you can’t reuse it next time. | We match your question to a proven, repeatable method. That method runs the same way every time, and it shows you exactly what data it used and how it reached the answer. Ask a similar question later, and you’re building on that same method instead of starting over. | An answer you can’t check and can’t reuse isn’t much better than doing the research yourself. This is the step that turns clean data into something people actually trust and come back to. |
| Phase 4Running it for real | ||
| Surviving productionA model call times out and the job queue jams. A large backfill starves every other job waiting behind it. Oversized inputs simply fail. Scheduled jobs break across time zones and when clocks change for daylight saving, and a job can be orphaned when the record it depends on gets deleted. | We built our pipeline to recover from failures on its own, retry safely, and keep jobs running correctly no matter the time zone or the size of the load. | A pipeline that jams on the first timeout, or a recurring job that silently stops firing, isn’t something a team can rely on. |
| Answering to securityA model plugged straight into your tools sees everything the connected user can see, including anything that was never properly locked down. The same inbox can be useful signal for one role and a liability for another. | We built one place to control what a model can read and do, based on each person’s role. | This is usually the first question your security team asks, and raw connectors don’t have a clean answer for it. |
| Explaining what happenedWhen a model takes an action, or gives an answer that looks off, someone needs to know what the model read, what the model changed, and how to undo that change. | We keep an audit trail across the whole system, one that persists even after the underlying records are deleted. | Without that trail, you can’t pass a security review or explain what the model actually did. |
| Keeping the connections aliveVendors change their APIs without notice. OAuth tokens expire. A recorder sends bad data. A customer’s meetings just stop showing up one day, for no obvious reason. | We maintain live connectors for tools like Zoom, Slack, HubSpot, and Salesforce, and we do the ongoing work of keeping each one working as the vendor changes things on their end. | This work never finishes. Someone has to own every vendor’s changes, permanently. |
What it adds up to
Any single row on this page is a sprint on its own. The pieces overlap, the failures are quiet, and the work never really ends. It becomes a job someone on your team owns permanently.
And the hardest parts are things like knowing who’s who across your systems, controlling what each person can see, showing what the AI actually looked at, and keeping all of that correct as your data keeps changing. That work has no end date. It’s something you’d own forever — which means spending your time and your team’s time building it, instead of building your own product.
We’re live in days, and the maintenance stays on our side.
See what it looks like for your team.
Demo →