Skip to main content
The source type is copilot_studio_dataverse. It connects to one Power Platform environment and queries the conversationtranscripts table on a 15-minute cadence.

What it reads

The puller queries two Dataverse tables per run: Each conversation produces one trace, with:
  • Each user question paired with the agent’s answer as a turn
  • Tool calls the agent made, including unfinished ones
  • The person’s directory account identifier on each question
  • A flag when the agent was edited after the conversation happened
  • A label when the conversation was a design-time test

What the admin sets up

In the Microsoft Entra admin centre

Done once for the whole organisation:
  1. App registrations → New registration. Give it a name (e.g. langwatch-copilot-reader), choose the single-tenant option.
  2. Copy the Application (client) ID and Directory (tenant) ID from the overview page.
  3. Certificates & secrets → New client secret. Copy the Value column immediately; Microsoft never shows it again.
  4. (Optional) API permissions → Microsoft Graph → Application permissions → Directory.Read.All → Grant admin consent. This lets LangWatch show department and job title beside each conversation. Skip it and conversations still arrive, without the org context.

In the Power Platform admin centre

Repeated for every environment that has agents:
  1. Environments → pick the environment → Settings → Users + permissions → Application users → New app user.
  2. Paste the Application ID, choose a business unit, and assign the Service Reader role.
Service Reader is the tightest stock role that grants read access to both bot and conversationtranscripts at organisation-wide reach. The similarly named Bot Transcript Viewer only reads records the account created itself, which for a service account is none. See the security roles reference for details.

In LangWatch

Create a source of type Microsoft Copilot Studio and fill in: The environment URL must be an https address on a domain Microsoft serves Power Platform from (.dynamics.com, .microsoftdynamics.us, .appsplatform.us, .dynamics.cn). Environments on a custom domain need a support ticket.

How a run works

  1. The puller exchanges the application credentials for a short-lived token scoped to the environment.
  2. It reads the agent table once (for names).
  3. It pages through the transcript table from where the last run left off.
  4. Multi-row conversations are stitched back together by their shared name and start time.
  5. Activities are paired into turns and emitted as OTLP spans.
The cursor is a (createdon, conversationtranscriptid) pair so it never skips or re-reads a row. Default cadence is every 15 minutes.

Security boundaries

  • Credentials stay in the environment. Every request goes to the configured Power Platform address. A next-page link pointing elsewhere stops the walk. Redirects are never followed.
  • The environment URL is checked at save time. An address outside Microsoft’s known Power Platform domains is refused before it is stored.
  • Directory access is optional. When Directory.Read.All is granted, the puller resolves the person’s directory identifier to a name and department. Without it, conversations still arrive with the raw aadObjectId only.

What shows up

Each conversation trace includes these attributes:
  • copilot_studio.agent_name: the agent that answered
  • copilot_studio.agent_changed_since: true when the agent was edited after the conversation
  • copilot_studio.design_mode: true for conversations held while building the agent
  • copilot_studio.transcript_batches: which pieces this conversation was built from
  • copilot_studio.conversation_incomplete: true when a piece is missing from the middle
  • langwatch.user.id: the person’s directory account on each user turn
The model attribute is microsoft/copilot-studio, a product label, not a priced model. The agent record in the environment does not expose which model the agent uses.

Limitations

  • Microsoft deletes transcripts roughly 30 days out, so the first run’s lookback is capped at 30 days.
  • Dataverse caps a single transcript row at roughly 1 MB. Long conversations are stored across multiple rows; the puller stitches them, but a missing piece (a row that was already deleted) marks the conversation incomplete.
  • Agent names require the credential to read the bot table. If it cannot, conversations still arrive but without an agent name, and the log says why.
  • The transcript has no token counts and no cost figures. Those come from Azure cost reports, which require a separate billing-plan setup.
Last modified on August 27, 2026