Building a Data Agent on Azure AI Foundry Grounded in Microsoft Fabric

The question that actually matters when someone asks me to build "an agent that can answer questions about our data" is never "which model." It's: how do I do this without reimplementing my organization's entire access-control model inside the agent layer? Every enterprise I've worked with already has row-level security baked into a semantic model somewhere — years of careful work deciding which region manager sees which region's numbers, which analyst sees unmasked PII and which doesn't. Connect an LLM directly to a warehouse and you either rebuild all of that from scratch behind the agent, badly, or you ship a demo that quietly ignores it. Neither is acceptable in production. That's the actual hard problem, and it's the one this article is about solving — not "how do I connect an LLM to a database," which is the easy 20% everyone demos.

The good news is Microsoft shipped a real answer to this for the Fabric-plus-Foundry combination, and it's more interesting than the marketing slide makes it sound. I already covered what a Fabric Data Agent is and how you build one inside Fabric itself — go read that first if you don't have one yet, because this article assumes you're starting from a Fabric Data Agent already published in a workspace, and it won't re-explain that part. What this piece covers is the other half: taking that already-published Fabric Data Agent and grounding a separate agent — one built and hosted on Azure AI Foundry — in it, with the underlying Fabric security model carried through intact.

Wait, is it Azure AI Foundry or Microsoft Foundry?

Microsoft Foundry is the current name — the platform was rebranded from Azure AI Foundry at Microsoft Build 2026, around May of this year. If you've been calling it Azure AI Foundry, you're not wrong exactly, you're just a few months behind the branding, and you're in good company: most people still say it that way, plenty of docs and URLs still live under the old `azure/ai-foundry` path alongside the newer `azure/foundry` one, and search traffic hasn't caught up either. I'm keeping "Azure AI Foundry" in this article's title because that's still what most people search for, but I'll use both names through the piece, the way I've flagged other Microsoft renames on this blog before — RoboMaker's retirement, IoT Central's sunset, IoT FleetWise's shift — because knowing a product got renamed (and which docs are stale as a result) is genuinely useful operational knowledge, not pedantry. If you're auditing an existing deployment and see `ai-foundry` in a resource name or ARM template, that's not a bug, it's just an artifact of when it was provisioned.

What does Microsoft Foundry Agent Service actually give you?

Foundry Agent Service is a managed platform for building, deploying, and scaling AI agents without owning the compute, container orchestration, or scaling logic yourself. You bring your own framework and pick from a genuinely large model catalog — Microsoft advertises access to more than 11,000 models spanning foundational, open-weight, reasoning, multimodal, and industry-specific families from OpenAI, Anthropic, Meta, Google, xAI, Hugging Face, and Microsoft's own MAI multimodal line. You can author a simple prompt agent directly in the Foundry portal with no code at all, or define one through the SDKs or REST API when you need real control over tools and orchestration.

The part worth knowing about if you're planning a build in the second half of 2026: hosted agents — agents that run inside Agent Service's own managed sandboxes, each session getting dedicated compute, memory, and filesystem access, with deployment that's framework-agnostic so an agent built with one SDK doesn't need a rewrite to run there — are expected to reach general availability by early July 2026. If you're reading this shortly after publication, that's already landed or is about to. The platform also bundles identity, memory, and observability as built-ins rather than things you bolt on: an agent gets a manageable identity out of the box, conversation state persists without you standing up your own store, and there's a trace you can actually look at when something goes wrong. If that trio sounds familiar, it should — it's a concrete, shipping instance of exactly the harness concerns I laid out generally in the agent harness piece: identity is part of the permission story, memory is part of context management, and observability is what makes the verification loop possible at all. Foundry isn't inventing a new idea here, it's productizing one that was already the right shape.

One more piece that matters for this specific build: Toolboxes, in public preview as of this writing, give an agent a single managed endpoint for tools, skills, MCP clients, and enterprise data integrations, with versioning and project-scoped artifacts that can themselves be exposed back out over MCP. That's a direct, real-world instance of the MCP-as-connection-layer pattern I've covered in MCP vs. Agent Skills and building MCP servers — worth knowing about even though this article's core mechanism, `MicrosoftFabricAgentTool`, is a native tool rather than something you'd typically route through a Toolbox. Toolboxes also reach into something Microsoft calls "Microsoft IQ," which includes a preview capability called "Fabric IQ" for tapping Fabric data with less custom plumbing — I'd treat that as an emerging capability worth watching rather than something to design around yet, since it's considerably less documented than the mechanism this article actually walks through.

And distribution: publishing a Foundry agent directly into Microsoft Teams and Microsoft 365 Copilot reached general availability in June 2026. Any agent you build in Foundry can land in the tools people already have open all day, with identity, permissions, and policy flowing through automatically instead of you building a second front door. That's the same distribution logic the Fabric Data Agent itself already has — publish once, reach people who'll never open your authoring surface — just one layer up the stack.

How do you actually ground a Foundry agent in Fabric data?

The mechanism is a specific tool: `MicrosoftFabricAgentTool`. In Agent Service, you create an agent and add an already-published Fabric Data Agent as one of its knowledge sources by supplying two IDs — the workspace ID and the artifact ID of that Fabric Data Agent. At query time, the Foundry agent evaluates the user's question and decides whether it should route to the Fabric tool at all, versus answering from something else it knows or declining to answer. If it routes there, the Fabric Data Agent takes over from that point and does its own reasoning about which underlying source — Lakehouse, Warehouse, semantic model, Eventhouse — actually holds the answer.

Here's the build sequence, as I'd actually walk a team through it:

  1. Prerequisite: a Fabric Data Agent already published in a workspace, with a known workspace ID and artifact ID. This is Fabric-side work — building and publishing the data agent, curating its instructions and example queries, connecting it to the right Lakehouse/Warehouse/semantic model sources. I cover all of that in the Fabric AI article; don't skip the semantic-model curation step there, because everything downstream in this article inherits whatever quality that step produced.
  2. Create a Foundry project and an agent inside it. Standard Agent Service setup — pick a model for the top-level agent's own reasoning (this doesn't have to be the same model family or even the same vendor as anything used inside Fabric), and decide whether this is a hosted agent or one you're running through your own compute.
  3. Attach `MicrosoftFabricAgentTool` to the agent, passing the workspace ID and artifact ID from step 1. This is the wiring step, and it's genuinely a few lines — the tool definition is what tells the Foundry agent "this Fabric Data Agent exists and here's how to reach it," nothing more exotic than that.
  4. Confirm delegated end-user identity actually flows through to the Fabric query. This is the step that matters more than every other step in this list combined, and I'll spend the next section on why. Don't treat it as a checkbox — verify it, with a real test user, before you trust any answer this agent gives you.
  5. Test with a real question and confirm two things separately: that the answer is actually grounded in real data rather than hallucinated, and that it respects the asking user's actual data access. Test with at least two different users who have different Fabric permissions and confirm they get different, correctly-scoped answers to the same question.
  6. Optionally publish the agent to Teams or Microsoft 365 Copilot once you trust it, for the same distribution reasons covered above — this is the step that turns a working prototype into something the business actually uses.
graph TD
    USER["End user
asks a question in Teams / M365 Copilot"] --> FA["Foundry agent
decides how to answer"] FA -->|"routes to Fabric knowledge source"| TOOL["MicrosoftFabricAgentTool
workspace ID + artifact ID"] FA -->|"answers directly, no Fabric needed"| ANSWER1["Answer returned"] TOOL --> IDENTITY["Delegated identity
query runs as the end user, not a service principal"] IDENTITY --> FDA["Fabric Data Agent
decides which source holds the answer"] FDA --> SRC["OneLake sources
Lakehouse / Warehouse / semantic model / Eventhouse"] SRC -->|"RLS / OLS enforced per the asking user"| FDA FDA --> FA FA --> ANSWER2["Answer returned to end user"]

The identity handoff at the "Delegated identity" step is the whole point of this architecture. The query against Fabric runs as the specific person who asked the question, not as a shared service account — whatever row-level or object-level security already exists in the Fabric semantic layer gets enforced exactly as if that person had opened the report themselves.

Here's what that wiring looks like in illustrative Python — treat this as a pattern to adapt, not a verbatim copy-paste from current SDK docs, since exact method names shift release to release and I'm not going to fabricate a signature I haven't verified character-for-character against whatever SDK version you're on:

# Illustrative shape of creating a Foundry agent and grounding it
# in a published Fabric Data Agent. Check current Foundry SDK docs
# for exact method names and parameter shapes before shipping this.

from azure.ai.projects import AIProjectClient
from azure.ai.projects.models import MicrosoftFabricAgentTool
from azure.identity import DefaultAzureCredential

project = AIProjectClient(
    endpoint="https://.services.ai.azure.com",
    credential=DefaultAzureCredential(),
)

fabric_tool = MicrosoftFabricAgentTool(
    workspace_id="c1c8b1e2-...-fabric-workspace",
    artifact_id="a94f6d31-...-data-agent-artifact",
)

agent = project.agents.create_agent(
    model="gpt-4.1",
    name="ops-data-agent",
    instructions=(
        "Answer questions about operational and financial data by "
        "querying the connected Fabric Data Agent. Do not guess at "
        "numbers you have not retrieved from the tool."
    ),
    tools=fabric_tool.definitions,
)

# Delegated identity: the run must be created with the end user's
# own credential context so the Fabric query executes on their behalf,
# not under the project's service identity.
thread = project.agents.create_thread()
project.agents.create_message(
    thread_id=thread.id,
    role="user",
    content="What were our Q3 returns by region?",
)
run = project.agents.create_run(
    thread_id=thread.id,
    agent_id=agent.id,
    # on-behalf-of / delegated auth context configured per your
    # identity provider — this is the step to verify, not assume
)

Why does the delegated-identity step matter more than the wiring itself?

Because it's the difference between an agent that's secure by inheritance and one that's a data-exfiltration tool with a chat UI bolted on. When the Foundry agent invokes `MicrosoftFabricAgentTool`, the query against Fabric runs on behalf of the specific person who asked the question — using their own identity, not a shared service principal representing "the agent" as a single generic caller. That's a deliberate design choice, and it's the right one: it means whatever row-level security or object-level security is already modeled in the Fabric semantic layer — the same security a business analyst has lived under for years opening reports directly — gets enforced automatically at the agent layer too, without the Foundry side reimplementing a single rule of it.

Concretely: if your Fabric semantic model already restricts a regional sales manager to their own region's rows via RLS, that same manager asking the Foundry agent "what were our returns last quarter" gets an answer scoped to their region — not because you wrote a filter into the agent's system prompt (which would be trivially bypassable and a nightmare to keep in sync), but because the query underneath is running as them. This is what actually solves the problem I opened with. You didn't rebuild the access model. You inherited it.

A Foundry agent grounded in a Fabric Data Agent is two stacked agentic decision points, and a wrong answer can originate at either one. The Foundry agent decides whether and how to invoke the Fabric tool in the first place — it can misroute a question, decline to use the tool when it should, or misinterpret what the tool returned. Then, independently, the Fabric Data Agent decides how to answer from the underlying sources, with its own chance of picking the wrong table, generating a bad KQL or SQL query, or misreading a semantic model relationship. Debugging this setup means having visibility into both layers' traces, not just the top-level Foundry agent's log. I've seen teams stare at a wrong answer, watch the Foundry-side trace show a clean, reasonable-looking tool invocation, and conclude "the agent is bad" — when the actual fault was a poorly-modeled Fabric semantic layer underneath that fed back a confidently wrong result the Foundry agent had no way to know was wrong. If you only instrument the top layer, you will misdiagnose Fabric-side failures as Foundry-side bugs, and you'll spend your debugging time in the wrong codebase.

Does delegated identity mean the security is automatically correct?

No — and this is worth stating plainly rather than as a vague caveat. Delegated identity enforces whatever security already exists in the Fabric semantic model. It does not create new security, and it does not audit or improve the security that's already there. If a Fabric semantic model has sloppy RLS — a rule that's technically present but wrong, a table that was never covered by row-level security at all, an object-level permission that's broader than anyone intended — none of that gets fixed by putting a Foundry agent in front of it. What changes is the surface area: a badly-secured Fabric semantic model that used to be reachable only by someone who knew to open Power BI and build a report is now reachable through a conversational agent surface too, potentially published into Teams where far more people will casually ask it things than would ever have opened the underlying report.

This is the same lesson I wrote about for the Fabric Data Agent on its own — a bad semantic model produces a confidently wrong answer with no visual cue anything's off — except now it's one layer further from the source data and one layer more convenient to reach, which if anything raises the stakes rather than lowering them. The actual prerequisite work for this whole build isn't the Foundry-side wiring, which is genuinely a few lines of configuration. It's making sure the Fabric semantic layer underneath was already correct before you gave it a second, more accessible front door.

How does this compare to other agent-hosting platforms?

Worth one honest sentence of contrast rather than a deep comparison: Databricks' Omnigent takes a different philosophy entirely — it's a meta-harness that sits above existing agent CLIs like Claude Code and Codex, composing and governing them, rather than a platform for building and grounding a single agent against a specific enterprise data source the way Foundry Agent Service plus `MicrosoftFabricAgentTool` does here. Different vendor, different problem being solved — Omnigent is about controlling a fleet of coding agents, this is about one agent answering business questions safely.

What to carry away

The mechanism itself — `MicrosoftFabricAgentTool` referencing a workspace ID and an artifact ID — is simple enough that the wiring isn't where the real work is. The real work is making sure the delegated end-user identity actually flows through to the Fabric query, and verifying that with real test users before you trust a single answer this agent gives anyone. Get that right and you've genuinely solved the hard problem: an agent that answers real questions over real enterprise data without you rebuilding your organization's access-control model from scratch inside the agent layer. Get it wrong, or skip verifying it, and you've built a fluent, convenient way to leak whatever your Fabric semantic model was already failing to protect — and because it's two stacked agentic decision points, a wrong or leaked answer can come from either layer, so instrument both, not just the one you built.