When you publish a Microsoft Fabric Data Agent, the portal hands you what looks like a single "connect programmatically" story. It isn't. There are really two consumption surfaces with different protocols, different client libraries, and a subtle trap for anyone building a real application on top. I hit this while prototyping a chat UI over a Data Agent, so this is the guide I wish I'd had.

First, what a Data Agent is (30 seconds)

A Fabric Data Agent is a published artifact that answers natural-language questions grounded in the data it can reach in OneLake — Lakehouses, Warehouses, semantic models, and so on. You configure it once with instructions, data-source descriptions, and example queries, and it becomes a reusable Q&A brain over your governed data. The interesting part is how you call it from outside the Fabric portal.

Path 1 — The MCP server endpoint

This is the newer, strategically-favored surface. When published, the agent exposes an endpoint shaped like:

https://api.fabric.microsoft.com/v1/mcp/workspaces/{WorkspaceId}/dataagents/{DataAgentId}/agent

The whole agent is exposed as a single MCP tool — the client sends a question to that one tool and gets back a grounded answer. It does not leak the underlying tables or schemas, which is intentional and keeps the abstraction (and the governance boundary) intact.

The trap: this is not a plain REST endpoint you can POST arbitrary JSON to. It speaks the Model Context Protocol over streamable HTTP, so a call follows the MCP message flow:

  1. initialize — the handshake
  2. tools/list — discover the tool
  3. tools/call — actually ask your question

An MCP client library (e.g. the MCP Python SDK) handles that dance for you. You attach a valid Fabric bearer token to every request. A generic HTTP client that skips the handshake will simply fail.

The payoff is build once, consume everywhere. The same agent can answer in Fabric, in M365 Copilot, in a Copilot Studio agent, in a Foundry-hosted agent, and in a developer's VS Code session — one governed artifact, many surfaces.

Path 2 — The Published URL and Python client SDK

This is the established, turnkey path, and it's what most of the older tutorials show. You copy the Published URL from the agent's Settings, then query it programmatically. Historically this was done inside a Fabric notebook with a polling loop; for external apps it has matured into the fabric-data-agent-client Python package.

A stripped-down backend call looks like this:

python
from azure.identity import InteractiveBrowserCredential
from fabric_data_agent_client import FabricDataAgentClient

# Load these from config/secrets — never hard-code real tenant IDs or URLs.
TENANT_ID      = "<your-tenant-id>"
DATA_AGENT_URL = "<your-published-data-agent-url>"

# The user signs in through the browser; queries run under THEIR identity.
credential = InteractiveBrowserCredential(tenant_id=TENANT_ID)
client = FabricDataAgentClient(
    credential=credential,
    data_agent_url=DATA_AGENT_URL,   # the Published URL from Settings
)

answer = client.ask("<your natural-language question here>")
print(answer)

It's the fastest supported way to bolt an agent onto a web app when you just want chat/Q&A over one agent.

The distinction that trips everyone up

Don't confuse either of the above with the management-plane SDK (fabric-data-agent-sdk). That one is for lifecycle work — creating the artifact, wiring data sources, setting instructions, publishing. It is not how you query the agent at runtime. Keep the two planes straight:

  • Management plane → create / configure / publish the agent (SDK or REST).
  • Runtime plane → ask the agent questions (MCP endpoint, or Published URL / client SDK).

Microsoft is steering people toward the MCP endpoint as the primary runtime consumption surface going forward.

Now the part that actually decides your architecture: auth

Here's the thing that matters more than protocol choice. The Data Agent runs its queries under the end user's identity, so Row-Level Security, Column-Level Security, and Purview policies all still apply. As of today that means:

  • The agent supports user identity only. Service Principal (SPN) authentication is not supported for runtime querying.
  • So you cannot put one service account behind your app and let it answer for everyone. Each user needs their own Entra ID token, which means an on-behalf-of (OBO) flow.

This constraint is true for both paths, and it's the single biggest thing to design around.

So — which one for a front-end app?

Two rules first, then the pick.

Rule 1: Never call either endpoint from browser JavaScript. Token exposure and CORS make that a non-starter.

Rule 2: Use a backend-for-frontend (BFF). Your UI talks to your API; that backend holds the Fabric bearer token (acquired via OBO from the signed-in user) and calls the agent. Roughly:

Browser (React)  →  Your BFF API  →  Fabric Data Agent
  user signs in       acquires OBO       MCP endpoint
  (Entra ID)          Fabric token       or client SDK

Now the decision:

  • Simple chat/Q&A over one agent, ship fast? Use the fabric-data-agent-client SDK in your backend. Microsoft has a doc aimed at exactly the "add a Data Agent to a web app" scenario, and it handles the auth handshake for you.
  • Agentic app, multiple agents, or you want your data layer to plug into AI frameworks the standard way? Use the MCP endpoint with an MCP client in your backend. More moving parts, but it's the future-proof, orchestration-friendly choice.

One gotcha before you ship

Teams consuming the agent through the SDK/endpoint sometimes get weaker answers than the Fabric UI gives. The reason is that programmatic calls don't automatically pull in all the semantic-model context the portal injects. The fix is to push that context into the agent itself — its instructions and data-source descriptions — so it travels with every call, rather than relying on the caller to supply it. If your agent encodes real business logic (join-key naming, which columns to use for a given calculation, how a metric should be aggregated), bake it in at the agent level.

Caveats

Both runtime paths are still in preview and the surface is moving quickly. Pin your SDK and API versions, and re-check the docs before you commit anything to production. But the mental model above — two runtime surfaces, one management plane, user-identity auth via a BFF — should hold steady even as the details shift.


If you're building on Fabric Data Agents and want to compare notes on the OBO token flow, that's the part worth getting right first — everything else is downstream of it.