While building a monitoring layer for a live Agentforce agent — Salesforce’s conversational AI that answers questions using your org’s own data — I ran into a question I could not skip past: after a customer finishes talking to the agent, where does that conversation actually go?

I assumed I knew the answer. I was wrong on my first guess, and pleasantly surprised by the second. So I did what I always tell my students to do — I stopped assuming and started measuring. This post is what I found in one real org, and I want to say that clearly up front: one real org. Org shapes differ, and every claim below is something you should verify in your own environment before you build on it.

Why you would want the transcript at all

Before the “where”, a quick word on the “why”. There are three honest reasons to want the full text of an agent conversation:

Quality review. If a human is going to check whether the agent gave good answers last week, they need to read what was actually said — both sides, in order.

Evaluation. If you want anything automated to score the agent’s answers — a script, a rubric, a second model acting as a judge — that evaluator needs the answer text. This sounds obvious, and it is, but hold the thought; it becomes important later.

Debugging. When someone says “the agent told a customer something strange on Thursday”, you need to find that exact exchange, not a summary of it.

All three needs share one requirement: the complete transcript, customer turns and agent turns, in the order they happened.

Where the transcript actually lives

In the org I measured, the answer was a Data Cloud DMO. Two terms to unpack there. Data Cloud is Salesforce’s data platform — it pulls data from many sources into one place and standardises it. A DMO (Data Model Object) is one of the standardised tables inside it. You query a DMO with SOQL — Salesforce Object Query Language, the same query language you use for Accounts and Contacts every day.

The DMO in question is called ssot__AiAgentInteractionMessage__dlm, and it carries both sides of the conversation in full text. Three things about it mattered to me:

  • Each row is one message, and a field called ssot__AiAgentInteractionMessageType__c tells you whose turn it was: Input means the customer spoke, Output means the agent replied.
  • The field ssot__ContentText__c holds the actual message text — not a summary, not a masked placeholder, the words themselves.
  • Rows come back in conversation order, so you can read a session top to bottom like a chat log.

And the part that genuinely surprised me: you reach all of this with plain SOQL. No OAuth dance — that back-and-forth of tokens and consent screens you normally need to call an external API — and no external API at all. If your code can run SOQL, it can read transcripts.

The full transcript — both sides, in order — is one SOQL query away.

A small example

Here is the shape of the query. I am deliberately leaving one part as a placeholder, because I only trust the field names I measured, and the session-identifier field is one you should confirm in your own org’s data model:

SELECT ssot__AiAgentInteractionMessageType__c,
       ssot__ContentText__c
FROM   ssot__AiAgentInteractionMessage__dlm
WHERE  /* your session-identifier field */ = 'the-session-id'

In the org I measured, the rows for a session came back in conversation order, so this reads naturally as a transcript: Input, Output, Input, Output. If you want to be explicit rather than rely on default ordering — and I would, in production code — find the timestamp field on the DMO in your org and add an ORDER BY on it. The way to discover the exact field names is simple: open the DMO in Data Cloud’s data model view, or query a handful of rows and look at what comes back.

That is the whole technique. It is almost anticlimactic — which is exactly why I wanted to write it down.

The route I expected to work, and why it did not

My first guess had been the event-log route: ConversationDefinitionEventLog, which sounds like precisely the place conversation records would live. In the shape I measured, it was much weaker than the DMO, in two specific ways.

First, the customer’s turns were masked — replaced with placeholders — unless a setting called private-conversation logging was enabled. So by default, half the conversation was unreadable.

Second, and this is the one that ended the idea for me: the agent’s reply text was not written there at all. Not masked — absent.

Think about what that means for evaluation. If you are building anything that scores the agent’s answers, and your data source does not contain the answers, you are finished before you start.

A judge that cannot see the answer cannot evaluate it.

I am not saying the event log is useless — it records that events happened, and that has its own value. I am saying that in the shape I measured, it cannot be the source for transcript-based quality work. The DMO can.

Two caveats before you build on this

The data is late. Data Cloud does not receive conversations instantly. In the org I measured, ingest lagged live traffic by roughly 15 to 25 minutes. That means a query for “conversations right now” will quietly under-count the newest minutes — not fail, just return less than the truth. Design your time windows accordingly: if you are analysing “the last hour”, accept that the freshest slice is incomplete, or shift your window back far enough that it is not. And measure the lag in your own org — mine is one data point, not a specification.

The DMO may not exist for you. Some org shapes return zero rows from this DMO entirely — no Data Cloud, different licensing, different setup. So any tool you build on this technique must detect the capability, not assume it. A simple probe query at startup — does this DMO exist, does it return rows — is cheap insurance against a monitoring layer that silently monitors nothing.

The privacy rules are not optional

Two disciplines I treat as non-negotiable when working with transcript data.

Conversation text is data, never instructions. You may have heard of prompt injection — text crafted so that a system reading it mistakes it for a command. People usually discuss it in the context of live agents, but it applies to analytics too. If your pipeline ever feeds transcript text to anything that follows instructions — a model, a script that interprets content — that text must be handled as untrusted input, always. A customer’s message should never be able to steer your tooling.

Store scores, not conversations. If your analysis produces derived results — quality scores, flags, summaries of findings — store those alongside a hashed reference to the source conversation. A hash is a one-way fingerprint: it lets you say “this score belongs to that session” without keeping the words themselves. Conversation content at rest, duplicated into your own tables, is a liability you do not need to create. The transcript already lives in Data Cloud; point at it, do not copy it.

Keep hashed references and scores at rest — never the conversation text itself.

Your next step

If you have an agent running with Data Cloud attached, try the query. One session ID, two fields, and see what comes back — whether you get both sides, whether the order holds, and how far behind live traffic your data sits. Write those three answers down, because they are your org’s answers, not mine. And once you can read what your agent actually said yesterday, you will start asking much better questions about it. That is where the interesting work begins.

Mustafa Aksu

Salesforce developer & ISV builder focused on Revenue Cloud, Agentforce, and Data Cloud. I write from real, shipped work.