Back to Blog

Building a Custom Microsoft Graph Connector With the SDK - When and Why

August 30, 20268 min readMichael Ridland

Copilot is only as useful as the data it can see. That sounds obvious, but it is the thing that trips up most of the Australian businesses we talk to about Microsoft 365 Copilot. They switch it on, ask it about a project or a customer, and get a shrug, because the answer lives in a line-of-business system Copilot has never heard of. The knowledge is sitting right there in the company. Copilot just cannot reach it.

Graph connectors are how you fix that. They pull external content into the Microsoft 365 semantic index so that Copilot, and Microsoft Search alongside it, can find and reason over it. Microsoft ships a gallery of prebuilt connectors for the common systems, and if one of those covers your source you should use it and move on. But plenty of the systems that matter to a business are not in that gallery. A custom in-house app. An old case management system. A bespoke inventory database that some contractor wrote in 2014 and that still runs half the warehouse. When there is no connector for the thing you need, you build one, and that is where the Graph connector SDK comes in.

Microsoft's custom connector SDK sample is the reference point for this. I want to talk through what building one is actually like, based on the connector work we do, rather than the tidy version the docs imply.

What a Graph connector actually does

Strip away the jargon and a connector does three jobs. It defines a schema, which is your way of telling Microsoft 365 what your data looks like and which fields matter. It ingests the content, pushing your records in as external items so they land in the semantic index. And it carries the permissions along with each item, so that a person only ever sees search results and Copilot answers drawn from content they were already allowed to see.

That third job is the one people underestimate, and it is the most important. When you push a customer record or a contract into the index, you are not just making it searchable. You are making it available to Copilot's reasoning for anyone whose query touches it. Get the permissions wrong and you have quietly built a data leak, where someone asks Copilot an innocent question and it happily summarises a document they should never have been able to open. Getting permissions right, so every external item carries an access control list that mirrors the source system, is most of the real work in a serious connector.

Where the SDK earns its place

You do not strictly need the SDK. The Graph connector APIs are just REST, and you can talk to them directly from any language that can make an HTTPS call. We have built connectors both ways. So what does the SDK give you that raw API calls do not?

Mostly, it handles the boring, error-prone plumbing so you can spend your time on the part that is actually specific to your data. Registering and updating the connection. Pushing items in batches instead of one painful call at a time. Retry and throttling behaviour, which matters more than you would think, because the ingestion APIs will throttle you the moment you try to load anything at real scale, and hand-rolling sensible backoff is a job nobody enjoys. The SDK gives you a structured way to do all of that, and the sample project shows the shape of a working connector end to end rather than leaving you to assemble it from API reference pages.

The honest framing: the SDK does not remove the hard parts of a connector. It removes the tedious parts. The hard parts, mapping your source schema to something useful, working out the permission model, deciding what to index and what to skip, are yours no matter which approach you take. What the SDK buys you is not having to reinvent the transport layer while you work on those.

The crawl problem nobody mentions in the demo

Every connector demo ingests a handful of records once and looks great. Production is not that. Production has a hundred thousand records that change constantly, and your connector has to keep the index in step with a source that never sits still.

That means you are not building a one-shot import. You are building two ongoing crawls. A full crawl that walks the entire source and rebuilds the index from scratch, which you run occasionally. And an incremental crawl that only picks up what changed since last time, which you run often. The incremental crawl is where the design effort goes, because to do it well your source needs some reliable way to answer "what changed since this timestamp", and a surprising number of older systems cannot answer that cleanly. When the source has no proper change-tracking, you end up choosing between crawling everything constantly, which is slow and expensive, or building your own change-detection layer, which is real work. This is the kind of thing worth knowing before you promise anyone a delivery date.

Deletions are their own small trap. If a record is removed from the source, your connector has to remove it from the index too, otherwise Copilot keeps confidently citing a customer who churned eighteen months ago. It is easy to build ingestion and forget removal, and you only notice when someone asks why a deleted thing is still showing up.

When to build one, and when not to

I will save you some money here. Do not build a custom connector as your first move. Check the prebuilt gallery first, because if Microsoft already ships a connector for your source, building your own is pure wasted effort and a maintenance burden you signed up for voluntarily.

Build custom when the data genuinely matters to how your people work, there is no prebuilt option, and the source is stable enough to be worth wiring in. A custom connector is a piece of software that has to be run, monitored, and maintained. If the platform's APIs shift, or your source system changes its schema, someone has to keep the connector alive. That is fine when the connector unlocks something valuable, and it is a poor trade when you have built one for a system three people query twice a year.

This is exactly the sort of call we help clients make on our Microsoft AI consulting work. Half the value is stopping people building things they do not need. The other half is building the ones they do need properly, so they carry permissions correctly and keep the index fresh without babysitting.

How we approach connector projects

When we build a Graph connector for a client, the sequence is fairly consistent, and almost none of it is about the SDK itself.

We start with the permission model, because it is the thing that will hurt most if it is wrong. Before any code, we work out how access is decided in the source system and how that maps to the access control lists on external items. If we cannot express the source's permissions cleanly, that is a red flag we would rather hit on a whiteboard than in production.

Then the schema. We are deliberate about what gets indexed, because more is not better. A connector that pushes every field of every record gives Copilot a noisy pile to dig through. A connector that pushes the fields people actually search on, with sensible titles and useful metadata, gives cleaner answers. Deciding what to leave out is as important as deciding what to include.

Then ingestion and crawl strategy, full and incremental, with the change-detection question settled up front rather than discovered halfway through. And then the unglamorous production concerns: where the connector runs, how it authenticates, how you know when it has silently stopped syncing. A connector that dies quietly is worse than no connector, because people keep trusting a Copilot that is now working from stale data.

This is the same discipline we bring to our broader AI agent development work. The interesting part is always the reasoning layer on top, but the thing that decides whether it survives contact with real users is the boring engineering underneath: data access, permissions, keeping things in sync.

The short version

The Graph connector SDK is the right tool when you need to get business data into Microsoft 365 Copilot and no prebuilt connector exists. It handles the transport plumbing, batching, throttling, and connection management so you can focus on the parts that are specific to your data. What it does not do is make the hard decisions for you: how to model permissions so nobody sees what they should not, what to index and what to skip, and how to keep the index in step with a source that keeps changing. Build a custom connector when the data genuinely matters and there is no off-the-shelf option, treat it as production software that needs monitoring, and get the permission model right before you write a line of ingestion code.

If you are looking at Copilot and realising the data your people actually need is locked inside systems it cannot see, that gap is exactly what a connector closes, and it is squarely what we do. Have a look at our services or get in touch and tell us where your knowledge is trapped.