How to build a customer context graph
A customer context graph joins what customers said to who said it and what their account is worth, and the concept guide covers why that beats a tagged list. This guide covers the construction itself, from the first connected source to the point where building your own stops making sense.
We build Modem, which maintains a customer context graph as a product, so treat the build-vs-buy section below as a vendor describing their own aisle. The rest is schema and pipeline mechanics you can use with or without us.
Start with a source inventory
Coverage gets decided here, before any pipeline exists. Four buckets cover most B2B teams.
Support and community. Zendesk or Intercom tickets, the shared Slack channels, Discord, support email. This is where the raw customer words live, and where the volume is.
Sales and success. Call transcripts, CRM notes. Requests raised on calls rarely make it into the ticket queue, so a graph without this bucket undercounts what enterprise customers say out loud.
Engineering. GitHub issues, Linear or Jira tickets, Sentry errors. These are the internal echoes of customer problems, and linking them is what connects "customers keep hitting rate limits" to "the fix shipped Tuesday."
Revenue and account data. Plan, spend, renewal date, open opportunities, from billing and the CRM. This bucket contains no feedback at all, and it makes the rest worth querying. A count of nine reads differently once you can see the renewal dates behind it.
You don't need all four on day one. Support and community first, then account data. The other two multiply what's already there.
Four entities, four edges
Keep the model small. The questions agents ask in practice resolve against four node types and the edges between them.
- Customer (a person, with every identifier they show up as)
- Company (the account: plan, ARR, renewal state)
- Topic (one issue or request, merged across channels)
- Source item (a ticket, thread, call excerpt, or issue, quote preserved)
The edges carry the meaning. A customer raised a source item, a source item belongs to a topic, a customer works at a company, a topic is tracked by an engineering ticket. In Postgres terms that's four tables plus an edges table, with the customer row holding an array of identifiers (emails, Slack IDs, Discord handles) that identity resolution appends to. Chain the edges and hard questions become walks. "Which accounts asked for audit logs, and how much renewal revenue is riding on it" goes topic to source items to customers to companies to contract values.
Resist adding node types until a live question needs one. Every entity you add is another join your pipeline has to maintain.
The three jobs that keep it true
A context graph is a pipeline that never stops running. Every incoming message passes through three jobs.
Topic merge. Decide whether "webhook retries are broken" is the same issue as "events arrive twice." The common recipe has three stages. Embedding similarity proposes candidate pairs above a threshold (0.8 cosine is a usual starting point, tightened whenever a bad merge gets through), an LLM pass confirms or rejects each pair with the quotes in front of it, and low-confidence calls go to a human review queue instead of being guessed. Skip the third stage and a wrong merge silently poisons the count in both directions.
Identity resolution. Match the sender to a known customer across email addresses, Slack handles, and Discord usernames. Exact email match does most of the work; the rest is a mapping table from chat handles to people, with unknowns landing in the same review queue. Without it, the same person counts three times, or their history splits into fragments no query finds.
Account linking. Attach the resolved person to their company and pull the current plan and renewal state from the CRM or billing. Stale account data is worse than missing data, because the graph keeps answering confidently from last quarter.
These jobs are why hand-built graphs go stale. Each one is easy for one message and unbounded in aggregate, and once a team falls behind on them, the counts drift wrong with nothing to flag it.
Build it yourself
The DIY stack has settled into a recognizable shape. Connectors pull from each source, an embedding model plus a clustering step propose topic candidates, an LLM pass makes merge decisions and extracts entities, a store holds the result, and a query layer your agents can reach sits on top, often an MCP server you write. The store doesn't have to be a dedicated graph database. Plenty of working builds are Postgres with an edges table, and purpose-built options are covered in the tools guide alongside the rest of the field.
Budget for the whole life of the thing, not the prototype. Graphing one Slack channel is a weekend. The version your team trusts is an ongoing service, and a fair planning number is months of a senior engineer up front plus a permanent share of someone's week after that, covering connector auth breaking, merge quality drifting, identity edge cases, and schema migrations. Teams that succeed here tend to have a platform team, an unusual domain the off-the-shelf graphs don't model, or data that can't leave their infrastructure. Those are legitimate reasons, and if none apply, the maintenance is the product you'd be rebuilding.
Buy it
Feedback tooling that clusters and counts is a crowded category. A maintained graph, where the joins stay current and agents can query the result, is the narrower thing this guide is about, and it's what Modem sells. You connect the channels you already use, and the three jobs above run continuously. Topics merge across sources and keep the original wording. People resolve across identities, and their accounts carry plan and revenue data from the Stripe and Salesforce integrations. Your agents reach the result over MCP, and scripts can use the @modem-dev/cli package on npm. It's free to start (pricing). The tradeoff is scope. Modem builds the customer graph only, so if you need a graph of your logistics network, you're back in the section above.
Point your agents at it
However the graph exists, agents need to reach it mid-task, and they need to know it's there. That part is wiring rather than graph construction. Interactive agents connect over MCP, and pipelines hit a CLI or API. The knowing part is a line in your agent instructions, because a graph the agent was never told about doesn't get queried. The guide on giving agents customer context covers the mechanics, including a worked Claude Code example, and context engineering covers why pull beats paste.
An acceptance test before you scale it
If you build, start with one source, one week of data, and the four-entity schema above, and check whether merge quality survives contact with production duplicates before you write another connector. If you buy, connect two channels and ask your agent a question you already know the answer to. Pass or fail is the same in both cases. The graph should return names, quotes, and numbers you'd defend in a roadmap meeting, and it should still do that in a month without anyone having touched it.
