> ## Documentation Index
> Fetch the complete documentation index at: https://docs.prisme.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Outlook

> Outlook mail, calendar and contacts from Agent Factory agents and Builder workflows, via Microsoft Graph with per-user Microsoft Entra OAuth

<img src="https://mintcdn.com/prismeai/Oqq72tWGTtxufvRl/images/connectors/outlook.png?fit=max&auto=format&n=Oqq72tWGTtxufvRl&q=85&s=9fe387aa1be3bd1ea4fcdf0d3bfda49f" alt="Outlook" width="96" height="96" noZoom style={{ float: "left", marginRight: "1.25rem", marginBottom: "0.5rem" }} data-path="images/connectors/outlook.png" />

The Outlook app provides read/write access to a Microsoft 365 mailbox — mail, calendar and contacts — through the [Microsoft Graph](https://learn.microsoft.com/en-us/graph/overview) REST API (v1.0). It can be consumed two ways: as a remote MCP server that **Agent Factory** agents call as tools, or as a Builder app whose instructions you call directly from DSUL. The MCP surface groups every operation into **six entity tools** (`mail`, `mailFolders`, `calendars`, `events`, `contacts`, `contactFolders`), each driven by an `action` argument, and runs in the **tenant app-instance context** (it resolves the installing workspace's own credentials). Authentication is per-user and supports several modes:

* **Per-user OAuth2 — central client** (`oauthCentral`, recommended) — one Microsoft Entra OAuth Application is registered once by the platform maintainer; every end user signs in with their own Microsoft account. Nothing to register per tenant: each workspace just installs the app and clicks *Connect*.
* **Per-user OAuth2 — tenant client** (`oauth`) — paste your own Entra application (client) ID/secret in the connector config app. Each user signs in with their own account against your client (PKCE authorization-code flow).
* **Application — client credentials** (`clientCredentials`) — an Entra app with **application** Graph permissions and admin consent, acting on a target mailbox without an interactive sign-in. Best for back-office / service automations.
* **Direct access token** (`accessToken`) — a caller-managed Microsoft Graph access token, used as-is with no exchange.

<CardGroup cols={3}>
  <Card title="Mail" icon="envelope">
    Read, search, draft, send, reply, forward and move messages and attachments; browse and manage mail folders
  </Card>

  <Card title="Calendar & contacts" icon="calendar">
    List, create and update calendar events, respond to meeting invites and query a time window; manage personal contacts and contact folders
  </Card>

  <Card title="Flexible per-user auth" icon="key">
    Per-user Microsoft Entra OAuth (central or tenant client), application client-credentials, or a direct access token
  </Card>
</CardGroup>

## Who is this for?

This connector is used by three different roles. Jump to the section that matches yours — each one is self-contained.

<CardGroup cols={3}>
  <Card title="Agent builder" icon="robot">
    You build agents in **Agent Factory** and want them to read and act on Outlook mail, calendar and contacts. → *Agent builder* tab.
  </Card>

  <Card title="Platform admin" icon="shield-halved">
    You run the platform and set up the shared Microsoft Entra OAuth client once for everyone. → *Platform admin setup* accordion below.
  </Card>

  <Card title="Workspace builder" icon="puzzle-piece">
    You write Builder automations (DSUL) that call Outlook operations directly. → *Workspace builder* tab.
  </Card>
</CardGroup>

## Prerequisites (Microsoft side)

* A **Microsoft 365** account, and an **Azure / Microsoft Entra ID** tenant where you can register an application (or a maintainer who already did).
* An **app registration** in [Microsoft Entra ID](https://entra.microsoft.com) (Azure portal → **App registrations**), with a **client secret** created under **Certificates & secrets**.
* **Microsoft Graph delegated permissions** granted on the app (for the per-user OAuth modes), covering the resources you intend to use:
  * Mail: `Mail.ReadWrite`, `Mail.Send`
  * Calendar: `Calendars.ReadWrite`
  * Contacts: `Contacts.ReadWrite`
  * Sign-in / identity: `User.Read`, `openid`, `profile`, `offline_access`
* For the **application (client-credentials)** mode instead, grant the equivalent **application** permissions and have a Global Administrator grant admin consent.

The OAuth scopes requested by default are:

```text theme={null}
offline_access openid profile
https://graph.microsoft.com/Mail.ReadWrite
https://graph.microsoft.com/Mail.Send
https://graph.microsoft.com/Calendars.ReadWrite
https://graph.microsoft.com/Contacts.ReadWrite
https://graph.microsoft.com/User.Read
```

<Accordion title="Platform admin (Governance) — one-time platform setup" icon="shield-halved">
  **Goal:** two one-time tasks — (1) configure the shared **central Microsoft Entra OAuth client** so every workspace lets its users sign in with their own Microsoft account, and (2) expose Outlook as a reusable **capability** in AI Governance so agent builders can pick it without pasting endpoint URLs.

  ## 1. Configure the connector

  <Steps>
    <Step title="Register the OAuth Application in Microsoft Entra ID">
      In [Microsoft Entra ID](https://entra.microsoft.com) → **App registrations > New registration**, register a **Web** application. Add a **Redirect URI** pointing at the core workspace callback:

      ```text theme={null}
      <api-url>/workspaces/<workspace-id>/webhooks/oauthCallback
      ```

      (e.g. `https://api.studio.prisme.ai/v2/workspaces/08QVA1T/webhooks/oauthCallback` on production).

      <Warning>
        Microsoft Entra rejects redirect URIs that contain a colon in the path, so use the **raw workspace id** of the core Outlook workspace (`<workspace-id>`, e.g. `08QVA1T`) — **not** the `slug:outlook-next` form used by other connectors. Copy the exact URI from the connector's configuration app, which renders it for you.
      </Warning>

      Add the Microsoft Graph **delegated** permissions listed in *Prerequisites*, create a **client secret** under **Certificates & secrets**, and note the **Application (client) ID**, the **secret value**, and the **Directory (tenant) ID** (or use `common` / `organizations` for multi-tenant).
    </Step>

    <Step title="Enter the credentials through the configuration app">
      Open the central `outlook-next` workspace and launch its **Configuration app** — `<studio>/apps/outlook-next` (e.g. `https://studio.prisme.ai/apps/outlook-next`), also linked as `Configuration app` on the installed instance. Switch to the maintainer view and follow the in-app instructions to paste the **Client ID**, **Client Secret**, **Tenant** and (optionally) scopes — the app stores them in the core workspace's secrets for you. Do not edit Studio's raw Secrets by hand. These credentials stay in the `outlook-next` workspace and are never exposed to tenants or end users; token exchange is proxied through the core `centralTokenExchange` webhook so the client secret never leaves the core workspace.
    </Step>

    <Step title="Tell workspaces to use the central client">
      Each consuming workspace selects auth mode **`oauthCentral`** in the connector configuration app (no client id/secret to enter on their side). Their users then just click **Connect**.
    </Step>
  </Steps>

  ## 2. Declare the capability in AI Governance

  Generic connectors — broad tool surfaces meant to be shared across many agents, like Outlook — are best exposed as a named **capability** in AI Governance. Agent builders then enable that capability on their agents instead of pasting a raw MCP endpoint.

  <Steps>
    <Step title="Open AI Governance > Capabilities">
      Create (or edit) the **Outlook** capability.
    </Step>

    <Step title="Point it at the MCP endpoint">
      Set the capability's MCP server URL to the connector's **MCP Endpoint**, and set its **Scope** to:

      ```text theme={null}
      context_id,agent_id,user_id
      ```

      The `agent_id` in the scope is what lets the connector identify and authorize the calling agent.
    </Step>

    <Step title="Make it available to agent builders">
      Once created, the capability appears in the capability picker for agent builders in your organization, who enable it on their agents. Access to the catalog follows your organization's existing roles; there is no per-capability role grant.
    </Step>

    <Step title="Smoke-test">
      From an agent that has the capability, in a workspace configured for `oauthCentral`, trigger any tool. The user is prompted to connect once (Microsoft sign-in); subsequent calls reuse the stored token transparently and refresh it automatically.
    </Step>
  </Steps>

  <Note>
    The connector's configuration app also offers a one-click **Add to catalog** button (workspace owner / admin only) that publishes the Outlook capability to the organization-wide Capabilities catalog for you — the easiest way to expose it to agent builders without hand-editing Governance.
  </Note>

  <Warning>
    Declaring the capability makes the connector **available**; it does not by itself authorize a specific agent. This connector follows the **tenant-context model** — which agents may actually call it is gated per-workspace by the **authorized-agents allowlist** in the configuration app (see the *Workspace builder* tab). There is also **no OAuth auth-config JSON** to attach in Governance: connect / status / disconnect are handled by the connector's own webhooks, wired automatically.
  </Warning>
</Accordion>

***

<Tabs>
  <Tab title="Agent builder (Agent Factory)">
    ## Agent builder

    **Goal:** let an agent you build in Agent Factory read and act on Outlook mail, calendar and contacts through MCP tools.

    <Note>
      Before an agent can call the connector, a *Workspace builder* must have installed and configured the Outlook app in a workspace (see the *Workspace builder* tab), and — for the central OAuth mode — a *Platform admin* must have provisioned the shared Microsoft Entra OAuth client (see the *Platform admin setup* accordion above).
    </Note>

    This connector runs in the **tenant app-instance context**: your agent is authorized two ways at once — it is identified by the `agent_id` that Agent Factory injects through the capability *Scope*, and that agent must appear in the connector's **authorized-agents allowlist** (managed in the configuration app). The Microsoft Graph access token itself is resolved server-side from the configured auth mode.

    There are two ways to wire it up. Pick based on how much isolation you need.

    ## Option A — Enable the shared capability from the catalog

    The fastest path: a *Platform admin* has already published an **Outlook** capability (see the *Platform admin setup* accordion above, §2), so you just pick it from the catalog. A workspace owner can publish it in one click with the config app's **Add to catalog** button.

    <Steps>
      <Step title="Open your agent in Agent Factory">
        Open the agent you want to extend and go to its capabilities / tools.
      </Step>

      <Step title="Add the Outlook capability">
        Browse the capability catalog, select **Outlook**, and enable it. The MCP endpoint URL and the *Scope* (`context_id,agent_id,user_id`) are already wired by the admin — nothing to paste, and the shared instance accepts every agent, so there is no allowlist step on your side.
      </Step>

      <Step title="Connect a Microsoft account (OAuth modes)">
        On the first tool call, an unconnected user is prompted to sign in — Agent Factory surfaces a `connect_url`. Application (`clientCredentials`) and `accessToken` modes need no per-user sign-in.
      </Step>
    </Steps>

    <Note>
      Convenient, but your agent runs against a **shared, platform-managed instance**: its Microsoft credentials are owned by someone else and the instance accepts every agent that is granted the capability. Prefer Option B for anything beyond quick experiments.
    </Note>

    ## Option B — Run it from your own workspace (recommended)

    For production agents, install the connector in **your own workspace** and point the agent at *that* workspace's MCP endpoint.

    <Warning>
      **Prefer this mode for security.** Because the MCP runs in *your* app-instance context, the Microsoft credentials, the per-user OAuth tokens and the authorized-agents allowlist are all **scoped to your workspace** — not shared platform-wide. You decide exactly which agents may call it and which Microsoft account / auth mode backs them, and a misconfiguration elsewhere can never expose your mailbox. The shared catalog capability (Option A) is a broad surface many agents can reach; your own workspace is an isolated, least-privilege boundary.
    </Warning>

    <Steps>
      <Step title="Install and configure the connector in your workspace">
        Follow the *Workspace builder* tab: install **Outlook** in your workspace, open its **Configuration app**, choose the auth mode and connect a Microsoft account.
      </Step>

      <Step title="Allowlist your agent">
        In that workspace's config app, open **Authorized agents** and tick your agent (the **Install capability** button does this for you).
      </Step>

      <Step title="Add the MCP capability to your agent">
        In your agent, add a capability pointing at **your workspace's MCP Endpoint** URL, and set its **Scope** to:

        ```text theme={null}
        context_id,agent_id,user_id
        ```

        The `agent_id` is what lets the connector identify and authorize your agent — without it, every call is rejected with an explicit "agent could not be identified" message. This *Scope* is separate from the Microsoft Graph OAuth scopes.
      </Step>

      <Step title="Connect a Microsoft account (OAuth modes)">
        On the first tool call, the user is prompted to sign in (or uses **Connect** in the config app).
      </Step>
    </Steps>

    ## Brief the agent in its system prompt

    Whichever option you pick, wiring the capability is not enough — the agent must know the MCP exists and when to use it. Copy-pasteable starter:

    ```text theme={null}
    You have access to the Outlook MCP server (tools: mail, mailFolders, calendars, events, contacts, contactFolders). Each tool takes an `action` argument. Use it whenever the user asks about their Outlook email, calendar events or contacts — listing, searching, reading, sending, replying, scheduling or updating. Prefer calling a tool over guessing, and confirm with the user before any destructive or outbound action (send, reply, forward, delete, decline a meeting).
    ```

    <Note>
      **Legacy AI Knowledge agents** (no native MCP picker): add the connector under **Advanced > Tools > MCP** and paste the **MCP Endpoint** URL. The agent still has to be allowlisted in the config app and its identity propagated so the connector can read its `agent_id`.
    </Note>

    <Note>
      **Restricting to read-only (least privilege).** Outlook tools cover both reads and writes (send mail, create/update events and contacts). The requested OAuth scopes **are** the grant, so the connector only ever obtains what the **Scopes** field in the configuration app asks for. To allow only read access, set a read-only scope list there, e.g.:

      ```text theme={null}
      offline_access openid profile https://graph.microsoft.com/Mail.Read https://graph.microsoft.com/Calendars.Read https://graph.microsoft.com/Contacts.Read https://graph.microsoft.com/User.Read
      ```

      With central OAuth (`oauthCentral`) you do **not** create your own Entra client — keep `oauthCentral` and just enter the read-only scopes; your tenant scope overrides the platform default (the central app must expose these read permissions). Write calls (e.g. send mail) are then rejected by Microsoft Graph with `403 Forbidden`. Note this is set at the workspace level — a workspace editor can widen it again; for a hard guarantee, use an Entra app limited to read permissions.
    </Note>

    ## Available Tools

    Each tool takes an `action` argument selecting the concrete operation, plus the per-action parameters. Omit `userId` to target the signed-in user (`me`).

    | Tool             | Description                                                                                                                                                                   |
    | ---------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
    | `mail`           | Outlook mail messages. Actions: `list`, `get`, `create`, `update`, `delete`, `send`, `sendDraft`, `reply`, `replyAll`, `forward`, `move`, `listAttachments`, `getAttachment`. |
    | `mailFolders`    | Mail folders (well-known ids: `inbox`, `drafts`, `sentitems`, `deleteditems`). Actions: `list`, `get`, `create`, `delete`, `listMessages`, `listChildFolders`.                |
    | `calendars`      | Outlook calendars (default plus secondary). Actions: `list`, `get`, `create`, `delete`.                                                                                       |
    | `events`         | Calendar events. Actions: `list`, `view`, `get`, `create`, `update`, `delete`, `accept`, `decline`, `tentativelyAccept`, `listForCalendar`.                                   |
    | `contacts`       | Personal contacts. Actions: `list`, `get`, `create`, `update`, `delete`.                                                                                                      |
    | `contactFolders` | Contact folders. Actions: `list`, `get`, `create`, `listContacts`.                                                                                                            |

    ## Output Formats

    Every tool accepts an `outputFormat` argument that controls the MCP response shape:

    * **`both`** (default) — the structured payload, with its JSON also rendered as text.
    * **`verbose`** — a human-readable text view, optimized for LLM consumption.
    * **`structured`** — concise machine-readable JSON in `structuredContent`.

    ## Tool Details

    ### mail

    ```json theme={null}
    {
      "name": "mail",
      "arguments": {
        "action": "list",
        "filter": "isRead eq false",
        "orderby": "receivedDateTime desc",
        "top": 10
      }
    }
    ```

    | Parameter                                                   | Required                                        | Description                                                                                                                                            |
    | ----------------------------------------------------------- | ----------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------ |
    | `action`                                                    | Yes                                             | One of `list`, `get`, `create`, `update`, `delete`, `send`, `sendDraft`, `reply`, `replyAll`, `forward`, `move`, `listAttachments`, `getAttachment`.   |
    | `userId`                                                    | No                                              | Target mailbox; omit for the signed-in user (`me`).                                                                                                    |
    | `messageId`                                                 | For get/update/delete/send actions on a message | Message id.                                                                                                                                            |
    | `attachmentId`                                              | For getAttachment                               | Attachment id.                                                                                                                                         |
    | `filter` / `orderby` / `search` / `select` / `top` / `skip` | No                                              | OData query options (`$filter`, `$orderby`, `$search`, `$select`, `$top`, `$skip`).                                                                    |
    | `body`                                                      | For create/update/send/reply/forward/move       | Resource fields, e.g. `send` → `{ message: { subject, body, toRecipients }, saveToSentItems }`; `reply` → `{ comment }`; `move` → `{ destinationId }`. |

    ### events

    ```json theme={null}
    {
      "name": "events",
      "arguments": {
        "action": "view",
        "startDateTime": "2026-07-01T00:00:00Z",
        "endDateTime": "2026-07-08T00:00:00Z"
      }
    }
    ```

    | Parameter                       | Required                                               | Description                                                                                                              |
    | ------------------------------- | ------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------ |
    | `action`                        | Yes                                                    | One of `list`, `view`, `get`, `create`, `update`, `delete`, `accept`, `decline`, `tentativelyAccept`, `listForCalendar`. |
    | `eventId`                       | For get/update/delete/accept/decline/tentativelyAccept | Event id.                                                                                                                |
    | `calendarId`                    | For listForCalendar                                    | Calendar id (default calendar otherwise).                                                                                |
    | `startDateTime` / `endDateTime` | For `view`                                             | ISO 8601 window bounds (both required for the time-window view).                                                         |
    | `body`                          | For create/update                                      | Event resource `{ subject, start, end, attendees, … }`; for accept/decline → `{ comment, sendResponse }`.                |

    ### contacts

    ```json theme={null}
    {
      "name": "contacts",
      "arguments": {
        "action": "create",
        "body": {
          "givenName": "Ada",
          "surname": "Lovelace",
          "emailAddresses": [{ "address": "ada@x.io", "name": "Ada Lovelace" }]
        }
      }
    }
    ```

    | Parameter                               | Required              | Description                                                   |
    | --------------------------------------- | --------------------- | ------------------------------------------------------------- |
    | `action`                                | Yes                   | One of `list`, `get`, `create`, `update`, `delete`.           |
    | `contactId`                             | For get/update/delete | Contact id.                                                   |
    | `filter` / `orderby` / `search` / `top` | No                    | OData query options.                                          |
    | `body`                                  | For create/update     | Contact resource `{ givenName, surname, emailAddresses, … }`. |

    ### mailFolders

    ```json theme={null}
    {
      "name": "mailFolders",
      "arguments": {
        "action": "listMessages",
        "folderId": "inbox",
        "top": 25
      }
    }
    ```

    | Parameter  | Required                                     | Description                                                                    |
    | ---------- | -------------------------------------------- | ------------------------------------------------------------------------------ |
    | `action`   | Yes                                          | One of `list`, `get`, `create`, `delete`, `listMessages`, `listChildFolders`.  |
    | `folderId` | For get/delete/listMessages/listChildFolders | Folder id or well-known name (`inbox`, `drafts`, `sentitems`, `deleteditems`). |
    | `body`     | For create                                   | `{ displayName }`.                                                             |
  </Tab>

  <Tab title="Workspace builder (DSUL)">
    ## Workspace builder

    **Goal:** install the connector in a workspace, configure authentication and the agent allowlist, and call Outlook operations from your automations.

    ## Installation

    1. Go to **Apps** in your workspace
    2. Search for **Outlook** and install it
    3. Open the **Configuration app** (the link auto-populated on install) to choose the auth mode, provide credentials, connect, and allow the agents that may call the connector

    ## Configuration

    | Field                           | Description                                                                                                                                                                         |
    | ------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
    | **Configuration app**           | Auto-populated on install — open this link to configure authentication (mode + credentials), connect a Microsoft account (OAuth modes), and manage the authorized-agents allowlist. |
    | **Microsoft Graph API version** | `v1.0` (default) or `beta`.                                                                                                                                                         |

    The configuration app drives everything; the app instance itself has no per-field credential form. From it you pick one of:

    | Auth mode           | What you provide                                                                                                                               | Best for                                                           |
    | ------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------ |
    | `oauthCentral`      | Nothing — just click **Connect**                                                                                                               | Workspaces on a platform where the admin set up the central client |
    | `oauth`             | Your own Entra **Application (client) ID + Secret** (+ tenant; redirect URI `<api-url>/workspaces/<your-workspace-id>/webhooks/oauthCallback`) | You manage your own Microsoft Entra OAuth app                      |
    | `clientCredentials` | Entra **client ID + secret + tenant** with admin-consented **application** Graph permissions                                                   | Server-to-server / back-office, no interactive sign-in             |
    | `accessToken`       | A pre-minted Microsoft Graph **access token**                                                                                                  | Short-lived / caller-managed tokens                                |

    <Warning>
      Microsoft Entra rejects a colon in the redirect URI path, so for the `oauth` mode use your workspace's **raw id** (`<your-workspace-id>`) in the redirect URI — not the `slug:` form. The configuration app shows the exact URI to register.
    </Warning>

    <Note>
      Credentials are provisioned into the workspace's Secrets by the `onInstall` flow and resolved server-side. The agent allowlist (**Authorized agents**) gates which Agent Factory agents may call the MCP endpoint — see the *Agent builder* tab.
    </Note>

    ## Available Instructions

    Every instruction resolves credentials from the workspace configuration. Operations are grouped by Outlook resource; the MCP server exposes the same operations behind the six entity tools (see the *Agent builder* tab). All instructions accept an optional `userId` (omit to target the signed-in user `me`).

    ### Mail

    | Instruction        | Description                                                                                                                    | Returns                                                                              |
    | ------------------ | ------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------ |
    | `listMessages`     | List messages in the mailbox; filter with `$filter`, sort with `$orderby`, full-text with `$search`, page with `$top`/`$skip`. | `{ value: [ message ], "@odata.nextLink" }`                                          |
    | `getMessage`       | Fetch one message by `messageId`.                                                                                              | A message resource `{ id, subject, from, toRecipients, body, receivedDateTime, … }`. |
    | `createDraft`      | Create a draft message; `body` = message resource (`subject`, `body`, `toRecipients`, …).                                      | The created draft message `{ id, … }`.                                               |
    | `updateMessage`    | Update a draft/message by `messageId`; `body` = changed fields.                                                                | The updated message resource.                                                        |
    | `deleteMessage`    | Delete a message by `messageId`.                                                                                               | Empty (HTTP 204).                                                                    |
    | `sendMail`         | Send a message in one call; `body` = `{ message: { subject, body, toRecipients }, saveToSentItems }`.                          | Empty (HTTP 202 Accepted).                                                           |
    | `sendDraftMessage` | Send a previously created draft by `messageId`.                                                                                | Empty (HTTP 202 Accepted).                                                           |
    | `replyMessage`     | Reply to the sender of `messageId`; `body` = `{ comment }` or `{ message }`.                                                   | Empty (HTTP 202 Accepted).                                                           |
    | `replyAllMessage`  | Reply to all recipients of `messageId`.                                                                                        | Empty (HTTP 202 Accepted).                                                           |
    | `forwardMessage`   | Forward `messageId`; `body` = `{ comment, toRecipients }`.                                                                     | Empty (HTTP 202 Accepted).                                                           |
    | `moveMessage`      | Move `messageId` to a folder; `body` = `{ destinationId }`.                                                                    | The moved message in its new folder.                                                 |
    | `listAttachments`  | List a message's attachments.                                                                                                  | `{ value: [{ id, name, contentType, size, contentBytes }] }`                         |
    | `getAttachment`    | Get one attachment by `attachmentId` (base64 `contentBytes` inline).                                                           | An attachment resource `{ id, name, contentType, contentBytes }`.                    |

    ### Mail folders

    | Instruction          | Description                                         | Returns                                                             |
    | -------------------- | --------------------------------------------------- | ------------------------------------------------------------------- |
    | `listMailFolders`    | List mail folders with message counts.              | `{ value: [{ id, displayName, totalItemCount, unreadItemCount }] }` |
    | `getMailFolder`      | Get a folder by `folderId` (id or well-known name). | A mailFolder resource `{ id, displayName, … }`.                     |
    | `createMailFolder`   | Create a mail folder; `body` = `{ displayName }`.   | The created mailFolder.                                             |
    | `deleteMailFolder`   | Delete a mail folder by `folderId`.                 | Empty (HTTP 204).                                                   |
    | `listFolderMessages` | List messages inside `folderId`.                    | `{ value: [ message ], "@odata.nextLink" }`                         |
    | `listChildFolders`   | List child folders of `folderId`.                   | `{ value: [ mailFolder ] }`                                         |

    ### Calendars & events

    | Instruction              | Description                                                               | Returns                                                        |
    | ------------------------ | ------------------------------------------------------------------------- | -------------------------------------------------------------- |
    | `listCalendars`          | List the account's calendars.                                             | `{ value: [{ id, name, owner, … }] }`                          |
    | `getCalendar`            | Get a calendar by `calendarId`.                                           | A calendar resource `{ id, name, … }`.                         |
    | `createCalendar`         | Create a calendar; `body` = `{ name }`.                                   | The created calendar.                                          |
    | `deleteCalendar`         | Delete a calendar by `calendarId`.                                        | Empty (HTTP 204).                                              |
    | `listEvents`             | List events from the default calendar.                                    | `{ value: [ event ], "@odata.nextLink" }`                      |
    | `listCalendarView`       | List events in a time window (`startDateTime` + `endDateTime`, ISO 8601). | `{ value: [ event ] }`                                         |
    | `listCalendarEvents`     | List events of a specific `calendarId`.                                   | `{ value: [ event ] }`                                         |
    | `getEvent`               | Get an event by `eventId`.                                                | An event resource `{ id, subject, start, end, attendees, … }`. |
    | `createEvent`            | Create an event; `body` = `{ subject, start, end, attendees, … }`.        | The created event.                                             |
    | `updateEvent`            | Update an event by `eventId`; `body` = changed fields.                    | The updated event.                                             |
    | `deleteEvent`            | Delete/cancel an event by `eventId`.                                      | Empty (HTTP 204).                                              |
    | `acceptEvent`            | Accept a meeting invite; `body` = `{ comment, sendResponse }`.            | Empty (HTTP 202 Accepted).                                     |
    | `declineEvent`           | Decline a meeting invite.                                                 | Empty (HTTP 202 Accepted).                                     |
    | `tentativelyAcceptEvent` | Tentatively accept a meeting.                                             | Empty (HTTP 202 Accepted).                                     |

    ### Contacts

    | Instruction           | Description                                                             | Returns                                                      |
    | --------------------- | ----------------------------------------------------------------------- | ------------------------------------------------------------ |
    | `listContacts`        | List personal contacts.                                                 | `{ value: [ contact ], "@odata.nextLink" }`                  |
    | `getContact`          | Get a contact by `contactId`.                                           | A contact resource `{ id, displayName, emailAddresses, … }`. |
    | `createContact`       | Create a contact; `body` = `{ givenName, surname, emailAddresses, … }`. | The created contact.                                         |
    | `updateContact`       | Update a contact by `contactId`; `body` = changed fields.               | The updated contact.                                         |
    | `deleteContact`       | Delete a contact by `contactId`.                                        | Empty (HTTP 204).                                            |
    | `listContactFolders`  | List contact folders.                                                   | `{ value: [{ id, displayName }] }`                           |
    | `getContactFolder`    | Get a contact folder by `folderId`.                                     | A contactFolder resource.                                    |
    | `createContactFolder` | Create a contact folder; `body` = `{ displayName }`.                    | The created contactFolder.                                   |
    | `listFolderContacts`  | List contacts in a contact `folderId`.                                  | `{ value: [ contact ] }`                                     |

    <Note>
      `Returns` shows the shape of the operation output (the underlying Microsoft Graph resource). Microsoft Graph send/reply/forward operations return **HTTP 202 Accepted** with no body. `userId` defaults to the signed-in user (`me`) when omitted.
    </Note>

    ## DSUL Examples

    **List the 10 most recent unread messages:**

    ```yaml theme={null}
    - Outlook.listMessages:
        filter: "isRead eq false"
        orderby: receivedDateTime desc
        top: 10
      output: messages
    ```

    **Send an email:**

    ```yaml theme={null}
    - Outlook.sendMail:
        body:
          message:
            subject: 'Meeting follow-up'
            body:
              contentType: HTML
              content: '<p>Thank you for the meeting today.</p>'
            toRecipients:
              - emailAddress:
                  address: '{{recipient}}'
          saveToSentItems: true
    ```

    **List this week's calendar events in a time window:**

    ```yaml theme={null}
    - Outlook.listCalendarView:
        startDateTime: '2026-07-01T00:00:00Z'
        endDateTime: '2026-07-08T00:00:00Z'
      output: events
    ```

    **Create a calendar event with an attendee:**

    ```yaml theme={null}
    - Outlook.createEvent:
        body:
          subject: 'Project kickoff'
          start:
            dateTime: '2026-07-01T10:00:00'
            timeZone: 'Europe/Paris'
          end:
            dateTime: '2026-07-01T11:00:00'
            timeZone: 'Europe/Paris'
          attendees:
            - emailAddress:
                address: '{{attendeeEmail}}'
              type: required
      output: event
    ```
  </Tab>
</Tabs>

***

## Error Handling

| HTTP code     | Meaning                                                                                                                                 |
| ------------- | --------------------------------------------------------------------------------------------------------------------------------------- |
| `400`         | Bad request — invalid parameters or malformed body (e.g. bad OData filter, invalid event resource).                                     |
| `401`         | Unauthorized — the Microsoft Graph access token is missing, expired or revoked. The user must reconnect (OAuth modes).                  |
| `403`         | Forbidden — insufficient Graph scope/permission, missing admin consent (application mode), or the account lacks access to the resource. |
| `404`         | Not found — the message, folder, event, contact or calendar id does not exist or is not visible to the account.                         |
| `429`         | Throttled — Microsoft Graph rate limit; back off and retry (honor `Retry-After`).                                                       |
| `500` / `503` | Microsoft Graph service error — transient; retry shortly, no reconnection needed.                                                       |

### Common Issues

**"This agent is not authorized to use this connector"** — The calling agent is not in the allowlist. Open the configuration app → **Authorized agents** → tick this agent (or enable **Allow all agents**) and Save.

**"The calling agent could not be identified"** — The MCP capability *Scope* does not declare `agent_id`, so Agent Factory never injects the agent identity. Set the Scope to `context_id,agent_id,user_id` on the capability, then allow the agent in the config app.

**"Microsoft Graph is not connected for this user"** — No per-user OAuth token. Open the configuration app (OAuth mode) and click **Connect**, or use the agent's connect flow.

**"Microsoft Graph token refresh failed … must reconnect"** — The stored refresh token was revoked or expired (Microsoft Entra invalidated it, or it aged past its limit). The connection is dropped automatically; the user must reconnect from the config app.

**"Microsoft Graph not authenticated" / "OAuth is not configured"** — Neither a tenant OAuth client nor the central platform client is available. Set the client ID/secret/tenant in the config app, or ask the platform maintainer to provision the central Entra OAuth client.

**`client_credentials` exchange failed** — In application mode, check the Application (client) ID / secret, the tenant id, and that a Global Administrator granted **admin consent** for the application Graph permissions.

**Microsoft Entra redirect URI rejected** — Entra rejects a colon in the redirect URI path. Register the redirect URI with the workspace's **raw id** (`/workspaces/<workspace-id>/webhooks/oauthCallback`), not the `slug:` form — copy the exact value from the config app.

## External Resources

<CardGroup cols={2}>
  <Card title="Microsoft Graph API" icon="microsoft" href="https://learn.microsoft.com/en-us/graph/api/overview">
    Official reference for the Outlook mail, calendar and contacts REST APIs.
  </Card>

  <Card title="Tool Agents" icon="robot" href="/products/agent-factory/capabilities">
    Learn how Agent Factory agents consume MCP tools in Prisme.ai.
  </Card>
</CardGroup>
