Microsoft Graph — Outlook + SharePoint
InsightWorker uses Microsoft Graph for both Outlook tools (read_emails, search_emails, send_email, download_attachment) and SharePoint tools (sharepoint_list, sharepoint_search, sharepoint_read). One Azure AD app registration, one set of credentials, both surfaces.
This page walks through creating the app registration with the right permissions and configuring InsightWorker.
Step 1 — Create the Azure AD app registration
In the Azure Portal:
- Azure Active Directory → App registrations → New registration
- Name:
InsightWorker(anything you want — visible to admins) - Supported account types: usually "Accounts in this organizational directory only (Single tenant)". Pick Multitenant only if you have a real multi-tenant story.
- Redirect URI: leave blank for now (we use client credentials, not user delegated)
- Click Register
On the resulting page, note these two values:
- Application (client) ID → goes into
MS_GRAPH_CLIENT_ID - Directory (tenant) ID → goes into
MS_GRAPH_TENANT_ID
Step 2 — Create a client secret
- Same app registration → Certificates & secrets → New client secret
- Description:
insightworker primary(so you can find it later) - Expires: 24 months is the org default; pick what your security policy allows
- Click Add
Copy the secret VALUE immediately (not the secret ID — that's a different thing). Azure shows the value exactly once. If you lose it, you delete and recreate.
→ Goes into MS_GRAPH_CLIENT_SECRET.
Step 3 — Grant API permissions
Same app registration → API permissions → Add a permission → Microsoft Graph → Application permissions.
Add these:
| Permission | What it's for |
|---|---|
Mail.Read | read_emails, search_emails, download_attachment |
Mail.Send | send_email |
Sites.Read.All | sharepoint_list, sharepoint_search, sharepoint_read (broad — reads any SharePoint site) |
For tighter scope on SharePoint (recommended for regulated tenants):
- Use
Sites.Selectedinstead ofSites.Read.All - Then have your tenant admin grant your app to specific sites via PowerShell:
``powershell Connect-PnPOnline -Url https://tenant.sharepoint.com -Interactive Grant-PnPAzureADAppSitePermission -AppId <client-id> -DisplayName "InsightWorker" -Site https://tenant.sharepoint.com/sites/Underwriting -Permissions Read ``
After adding permissions, click Grant admin consent for <Tenant>. Without admin consent, the permissions are listed but not active — you'll get 403 on every call.
Step 4 — Configure InsightWorker
~/.insightworker/.env:
MS_GRAPH_TENANT_ID=c7fd5203-aca8-42d1-9499-13e0ff453765
MS_GRAPH_CLIENT_ID=c735984d-182c-4cbb-bd61-ae410927854e
MS_GRAPH_CLIENT_SECRET=<the value you copied in step 2>
MS_GRAPH_DEFAULT_USER_ID=you@yourdomain.com
# SharePoint default site (used by sharepoint_* tools when no site is given)
SHAREPOINT_DEFAULT_SITE=yourdomain.sharepoint.com:/sites/Underwriting
Restart the agent (CLI: re-run insightworker; VS Code: InsightWorker: New Chat; Desktop: relaunch).
Step 5 — Verify
In the chat:
List the top-level folders of our SharePoint site.
Should return a folder listing. If it returns 403, your admin consent didn't take effect (give it 60 seconds and retry; if still failing, re-check the Grant admin consent button in step 3).
List the most recent 5 emails in my inbox.
Should return five emails or (no recent emails). If you get "User not found", check MS_GRAPH_DEFAULT_USER_ID — it must be a real user in your tenant.
Common gotchas
| Symptom | Cause | Fix |
|---|---|---|
403 Forbidden on every call | Admin consent not granted | Re-click "Grant admin consent" in API permissions |
Insufficient privileges to complete the operation on SharePoint only | App has Mail.* but not Sites.* | Add Sites.Read.All (or Sites.Selected + per-site grant) and re-consent |
Application not found in directory | Wrong tenant ID | The tenant ID is on the app registration's overview page; copy from there, not from a different app |
| Client secret rejected | Used the secret ID instead of the value | The value column is what you need; if you lost it, delete + recreate the secret |
| Works for one user, fails for another | MS_GRAPH_DEFAULT_USER_ID hardcoded | Pass user_id as a tool argument when reading a different mailbox |
Rotation
Client secrets expire on the policy you set (default 24 months). When yours is approaching expiry:
- Add a new secret in step 2 (don't delete the old one yet).
- Update
MS_GRAPH_CLIENT_SECRETin.env. - Restart the agent.
- Verify it works.
- Then delete the old secret.
This zero-downtime rotation is standard practice. Don't delete the old secret until the new one's been verified.
See also
- providers/bedrock.md — for the LLM side
- tools/overview.md — full reference for all
outlook_*andsharepoint_*tools
Source: docs/authentication/microsoft-graph.md in the public repo. Open a PR with corrections.
