Blog Post

Microsoft Foundry Blog
7 MIN READ

Building Permission-Aware Hosted Agents for SharePoint in Foundry Agent Service

heenarefai's avatar
heenarefai
Icon for Microsoft rankMicrosoft
Oct 12, 2026

This article shows how to build hosted agents in Foundry Agent Service, published to Microsoft teams that retrieve SharePoint content on behalf of each signed-in user, using a Foundry IQ knowledge base and the Foundry toolbox, so every answer reflects what each person is allowed to see.

Organizations increasingly publish agents to Microsoft Teams and Microsoft 365 Copilot that answer questions using internal knowledge sources. SharePoint is a very common source for this information; where many times access is different for every user. A finance employee, HR employee, and project manager may all ask the same question but have access to different documents. When an agent is hosted in Foundry Agent Service, the agent itself runs under its own identity. This creates an important challenge: how can retrieval respect the permissions of the person asking the question rather than the permissions of the agent? This post shows how to do that with built-in capabilities: a Foundry IQ knowledge base with a remote SharePoint knowledge source, connected to the agent through the Foundry toolbox.

Foundry IQ is the knowledge layer for agents, built on Azure AI Search. A knowledge base is its top-level resource: it orchestrates retrieval across one or more knowledge sources, which are connections to indexed or remote content. In this solution the only knowledge source is SharePoint, queried live as the signed-in user through the On-Behalf-Of (OBO) pattern, and the agent reaches the knowledge base through a toolbox.

Why agent identity is not enough

  1. Hosted agents run as their own agent identity. When Foundry Agent Service runs your Microsoft Agent Framework agent as a hosted agent, it authenticates as the agent, not as the person chatting with it.
  2. SharePoint permissions belong to users. Two people asking the same question may be allowed to see different documents.
  3. So grounded answers (RAG) need per-user retrieval. If retrieval runs as the agent, SharePoint can't check the asking user's access. Results are either empty or not filtered for that user.
  4. Therefore the user's token has to reach the retrieval step. Changing the model or the prompt can't fix this. The architecture has to carry the user's identity all the way to SharePoint.

This is the key architectural principle behind this solution. The hosted agent keeps using its own identity for model inference, while retrieval runs with the signed-in user's identity.

What you'll build

  • A hosted agent, published to Microsoft Teams, that answers from one or more SharePoint sites.
  • Answers limited to what each user can open in SharePoint, using On-Behalf-Of (identity passthrough) retrieval.
  • Clickable citations back to the source documents.
  • Built on out-of-the-box Foundry IQ and Foundry toolbox capabilities: no custom server to host, and no client secrets in the retrieval path.

The complete sample is on GitHub: SharePoint knowledge base sample

The sample repository contains the setup scripts and agent code used in this walkthrough. Before we run them, let’s trace how the user’s identity flows through the architecture and why it matters for permission trimming.

Note: Remote SharePoint knowledge sources in Foundry IQ were in preview at the time this article was written.

How it works

The agent runs as itself. Retrieval runs as the user. Three pieces carry the user's identity end to end:

  1. FoundryToolbox in the agent sends the per-request call ID with each tool call, so Foundry knows which user the call belongs to.
  2. A UserEntraToken connection passes that user's Microsoft Entra ID token to the Foundry IQ knowledge base on Azure AI Search. This is identity passthrough (On-Behalf-Of): every request downstream runs as the signed-in user.
  3. A remote SharePoint knowledge source queries SharePoint live through the Microsoft 365 Copilot Retrieval API as that user, scoped to the site paths you choose. Nothing is copied into an index.

Why not Work IQ?

Work IQ is a good choice when an agent should reason over a user’s broader Microsoft 365 work context. This pattern is intended for scenarios where the agent should answer from specific SharePoint sites, treating those sites as a defined knowledge boundary.

Use Work IQ when broad Microsoft 365 context is appropriate. Use this pattern when retrieval should be limited to selected SharePoint content. The right choice depends on the scope and behavior your scenario requires.

Before building the sample, let’s check the services and permissions the setup requires.

Before you start

You need a Foundry project with a model deployment, an Azure AI Search service and a SharePoint site containing the content you want the agent to use.The Search service must be in a region that supports agentic retrieval, in the same Microsoft Entra tenant as Microsoft 365.

Make sure the following permissions are in place:

RoleRequired permissions
Setup userSearch Service Contributor on the Azure AI Search service, and rights to create connections and toolboxes in the Foundry project
End usersSearch Index Data Reader on the Search service, Foundry Agent Consumer on the agent, a Microsoft 365 Copilot licence, and access to the documents in SharePoint

With the concepts established, let's build the end-to-end solution.

Build it in four steps

Clone the sample repository before running the setup scripts. The commands below assume you are running them from the repository root:

git clone https://github.com/Heenanl/hosted-agent-sharepoint-knowledge-base.git
Set-Location hosted-agent-sharepoint-knowledge-base
python -m pip install -r setup/requirements.txt
Copy-Item setup/.env.example setup/.env

Fill in setup/.env with your Foundry project, Azure AI Search, and SharePoint knowledge source values. The repository README contains the complete configuration and deployment instructions. The steps below highlight the key settings and decisions.

 

1. Create the knowledge base

Run setup/create_knowledge_base.py. It creates a remote SharePoint knowledge source and a knowledge base. The setting that limits retrieval to your site is:

"filterExpression": "Path:\"https://<TENANT>.sharepoint.com/sites/<SITE>/\""

2. Connect it to Foundry with the user's identity

Run setup/create_connection.py. It registers the knowledge base's MCP endpoint as a Foundry connection. The setting that matters most in the whole architecture is:

"authType": "UserEntraToken"

With UserEntraToken, Foundry forwards the signed-in user's token instead of a shared identity, so SharePoint can apply that user's permissions. Then run setup/create_toolbox.py. It wraps the connection in a toolbox that exposes only knowledge_base_retrieve.

3. Build the agent

The agent itself is small. The key line is tools=FoundryToolbox(credential):

agent = Agent(
    client=FoundryChatClient(project_endpoint=endpoint, model=model, credential=credential),
    instructions=INSTRUCTIONS,
    tools=FoundryToolbox(credential),
)

Two instructions in the agent's prompt made a visible difference in Teams:

  • Cite every source as a markdown link, using the Title and uri fields the tool returns.
  • If the tool returns nothing relevant, say that the available sources do not contain the answer. Do not guess.

The first gives users clickable citations. The second stops the model from filling gaps when a user can't see a document.

4. Deploy and publish to Teams

Follow the sample README to initialize the agent with azd ai agent init, set the required environment values, and deploy it with azd up. After deployment, publish the agent to Microsoft Teams and Microsoft 365 Copilot. The repository includes a publishing script, including support for Foundry projects on a private network. Users do not need a separate, tool-specific consent flow.

Prove the permission trimming

A good answer doesn't prove the right permissions were used. Test with two users and one document that only one of them can open:

UserSharePoint accessResult in Teams
ACan open the documentAnswer from the document, with a citation link
BCannot open the document"The available sources do not contain the answer."

In our testing, both users' requests reached the knowledge base, but only user A got content from the document, because the Microsoft 365 Copilot Retrieval API ran as each user. Run the test in separate conversations, and repeat it after any permission change.

Common pitfalls

Using a managed identity for the connection

The retrieval runs as the agent's managed identity, so SharePoint has no user to check permissions against. In our testing, a ProjectManagedIdentity connection failed with x-ms-query-source-authorization is invalid. Use UserEntraToken.

Forgetting Search Index Data Reader

Because each user's own token reaches Azure AI Search, every user needs this role, not just you. Otherwise the user can reach the agent, but retrieval fails for them. Assign the role to a security group once, replacing SEARCH_SERVICE, RESOURCE_GROUP and $GROUP_ID with your own values:

$SEARCH_ID = az search service show -n SEARCH_SERVICE -g RESOURCE_GROUP --query id -o tsv
az role assignment create --assignee $GROUP_ID --role 'Search Index Data Reader' --scope $SEARCH_ID

Using a custom MCP client instead of FoundryToolbox

A hand-built MCP client that attaches only the agent's credential drops the per-request call ID, which links a tool call to its user. In our testing with another OAuth tool, every user ended up running as whoever had consented first. FoundryToolbox fixed it.

Building a custom MCP proxy

A custom On-Behalf-Of (OBO) proxy can work, but you then own its hosting, secrets, token checks and patching. The knowledge base gives the same per-user retrieval with built-in components.

Once the setup and permission checks are complete, use the sample repository to try the full flow in your own environment. The links below provide more detail on the Foundry IQ and toolbox building blocks.

Get started

Acknowledgements

Thanks to Mahya Gheini and Linda Li from the Microsoft Foundry product team for their guidance on toolboxes and knowledge bases. 

Updated Oct 13, 2026
Version 2.0

2 Comments

  • symoiz's avatar
    symoiz
    Brass Contributor

    Permission-aware retrieval is essential when deploying AI agents over enterprise knowledge. Preserving SharePoint permissions throughout retrieval and response generation can help prevent unauthorized information exposure. I’d be interested in how permission changes and document-level access revocation are handled in real time.

    • heenarefai's avatar
      heenarefai
      Icon for Microsoft rankMicrosoft

      Great question. This pattern retrieves SharePoint content live at query time through the Copilot Retrieval API, using the signed-in user’s identity. It does not copy documents into a separate index, so document and permission changes are evaluated by SharePoint during subsequent retrieval requests.

      In practice, after access is revoked, the affected user should no longer receive that document in new grounded responses once the change has propagated through Microsoft 365.