Grounding a Copilot Agent on Your Azure DevOps Wiki: From Connector to Cited Answers

The shape of the solution

Architecture: Azure DevOps Wiki → Copilot connector → declarative agent → user

Read it left to right:

  • The connector crawls your Azure DevOps Wiki and indexes the content into Microsoft 365, keeping each item’s permissions attached.
  • The declarative agent binds to that connector as its only knowledge source, and its instruction block enforces the behaviour on the right of the diagram: cite when the answer is in the wiki, refuse when it isn’t, never invent.

One property is easy to miss and worth calling out early:

Security comes for free

The connector is permission-trimmed. It maps Azure DevOps identities to Microsoft Entra ID, so a user only ever sees wiki content they could already open. You don't build access control into the agent - you inherit it from the connector.


Part 1 - Deploy the connector (Federated Credential)

Microsoft gives you the connector; you supply the plumbing.

Before you start

  • You are a Microsoft 365 admin.
  • You know which Azure DevOps organisation to index.
  • Third-party application access via OAuth is enabled in that organisation (Azure DevOps → Organization settingsPolicies). Without this toggle, the connector can't authenticate - full stop.

There are two supported authentication methods. I used - and recommend - Federated Credential, because it crawls with a Microsoft-published service principal rather than your admin account, so indexing doesn’t quietly break the day someone changes a password or leaves.

Follow these steps in order:

  1. Confirm the crawl app exists. Federated Credential uses a Microsoft-published enterprise app as the crawl account. In the Microsoft Entra admin center, search for the app ID 933838e2-bec1-440f-a634-9363c82e5b6d. If it isn’t there yet, opening the Copilot Connectors page in the admin center triggers provisioning - which can take a few hours, so do this first.

  2. Grant that app access to your Azure DevOps projects. In Azure DevOps → Organization settingsUsersAdd users, add the same app ID as a user, then:

    • assign the Basic access level - not Stakeholder;
    • add it to the Project Readers group (or equivalent) for the projects you want indexed;
    • clear the “send email invitation” option.
  3. Create the connection. In the Microsoft 365 admin center → CopilotConnectorsGallery, pick Azure DevOps Wiki. Set a display name, and for the instance URL enter only the organisation name - the segment after https://dev.azure.com/, e.g. contoso, not the full URL. Choose Federated Credential as the authentication type and authenticate when prompted.

  4. Roll out to a limited audience, then create. Toggle Rollout to limited audience and scope it to yourself or a small group before you choose Create. Indexing starts immediately - by default a full crawl daily, plus an incremental crawl every 15 minutes.

  5. Verify it reached Ready. Back in Connectors, wait for the connection state to show Ready (not Indexing).

Step 2 is the one that quietly decides whether your crawl works at all:

Lesson 1 - Basic, not Stakeholder

Stakeholder access looks like it should be enough for a read-only crawl, and the connector will happily list your pages. But it can't actually read them - so you get item listed but no longer accessible crawl errors and an agent that finds nothing. Give the crawl account Basic and the errors disappear.

Don't debug the agent too early

Until the connection shows Ready, an agent built on top of it will legitimately find nothing. Wait for the first crawl to finish before you conclude anything is broken.


Part 2 - Build the declarative agent

You could stop here and let people search the connector from Microsoft 365 search. But search returns links; an assistant returns answers. The declarative agent adds the personality and - more importantly - the guardrails.

I built it with TypeSpec and the Microsoft 365 Agents Toolkit rather than clicking it together in a portal, for three concrete reasons:

  • The agent’s behaviour lives in source control and gets code-reviewed like anything else.
  • The whole thing retargets to another tenant by changing one environment variable - no edit to the agent definition.
  • The instructions - the real intellectual property here - are versioned alongside the code.

Bind to the connection - by id, not by name

The agent’s only knowledge source is the connector, referenced by its connection id. In TypeSpec that’s a single capability:

op copilotConnectors is AgentCapabilities.CopilotConnectors<Connections = [
{
connectionId: "\${{ADO_WIKI_CONNECTION_ID}}";
}
]>;

The value is injected from an environment file at build time, which is what makes retargeting tenants a config change rather than a code change.

Lesson 2 - Bind to the Graph connection id, not the display name

The friendly name you typed in the admin center is not necessarily the id the manifest needs - and if you guess wrong, the agent silently returns nothing. Get the authoritative id from Microsoft Graph (with the ExternalConnection.Read.All scope):

GET https://graph.microsoft.com/v1.0/external/connections?$select=id,name

Use the id field of your Azure DevOps Wiki connection.

Write the instructions that actually do the grounding

Here’s the part that separates a trustworthy assistant from a plausible liar. A connector alone does not stop the model reaching for general knowledge - it will still blend in things it “knows” unless you forbid it. The instruction block is where you forbid it:

Source rule (strict grounding)
- Answer ONLY using content retrieved from the Azure DevOps Wiki connector.
- Do NOT use general world knowledge, prior training, or web content. This agent has no web access.
- Never invent, guess, or infer facts that are not present in the retrieved wiki content.

When you do NOT find relevant content
- Say plainly that you could not find the answer in the Azure DevOps Wiki.
- Do NOT answer from general knowledge as a substitute.

Lesson 3 - The instructions keep the agent honest, not the connector

Two sentences do the heavy lifting: answer only from what you retrieve, and say so when the wiki has no answer. Round it out by telling the agent to preserve the guide's numbered steps and reference tables, and to always cite the source page.

Finish the agent with:

  • A handful of conversation starters that mirror your most common wiki topics - “How do I request access to a SharePoint site?”, “How do I submit an IT ticket?” - so first-time users immediately see what the agent is for.
  • A provision + preview pass: VS Code Agents Toolkit → Provision (or atk provision), then open the agent from the agents drawer at m365.cloud.microsoft/chat.

Test it honestly

The temptation is to ask a question you know the wiki answers, see a tidy cited response, and declare victory. Don’t stop there - the interesting test is the one that should fail.

Test What you ask A grounded agent does this
✅ In the wiki A topic your wiki covers Answers directly, keeps the steps in order and any table intact, and gives a citation that opens the real page
❌ Not in the wiki “What’s the capital of France?” or an undocumented internal topic Says it couldn’t find the answer in the wiki - and stops there

The failing test is the point

An agent that cheerfully answers off-wiki questions is telling you the instructions aren't holding - and that's exactly the failure your users would never notice until it handed them the wrong policy. Always test the case that should say "I don't know."


Ship it safely

Because the agent is read-only and the connector is permission-trimmed, this is a comfortable pattern to roll out - but still stage it. When you publish to your organisation, the app lands as Pending approval in the Microsoft 365 admin center (Integrated Apps). On approval, resist the urge to pick Everyone on day one.

Lesson 4 - Roll out staged

Move through these gates, not straight to the end:

  1. Publish & approve the app.
  2. Hold it at No users while you validate in production.
  3. Assign it to a specific Entra ID group - a pilot team.
  4. Only then widen to Everyone.

If something's wrong, you've contained it to a group, not the whole company.


When to reach for this pattern

Use the connector-plus-declarative-agent approach when your source of truth already lives in Azure DevOps Wiki and you want answers that are grounded, cited, permission-aware, and read-only - internal how-to and knowledge-base scenarios are the sweet spot. If instead you need an agent that takes actions, calls APIs, or orchestrates a multi-step workflow, that’s Copilot Studio territory; a declarative agent is deliberately narrower, and that narrowness is a feature.

The mental model to carry away is the split we started with. Deploying the connector is the easy half, and most guides stop there. The half that earns your users’ trust is four sentences of instructions telling the agent to answer only from the wiki and to admit when it can’t - plus the discipline to actually test the case where it should say “I don’t know.”

Author: Ejaz Hussain
Link: https://office365clinic.com/2026/08/22/grounding-copilot-agent-azure-devops-wiki/
Copyright Notice: All articles in this blog are licensed under CC BY-NC-SA 4.0 unless stating additionally.